blob: a11a43777a1aa908d1dec5edba281fc23417915d [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
vivek mehtaa51fd402016-02-04 19:49:33 -08002 * Copyright (C) 2013-2016 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "audio_hw_primary"
Haynes Mathew George03c40102016-01-29 17:57:48 -080018#define ATRACE_TAG ATRACE_TAG_AUDIO
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080019/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070020/*#define VERY_VERY_VERBOSE_LOGGING*/
21#ifdef VERY_VERY_VERBOSE_LOGGING
22#define ALOGVV ALOGV
23#else
24#define ALOGVV(a...) do { } while(0)
25#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080026
27#include <errno.h>
28#include <pthread.h>
29#include <stdint.h>
30#include <sys/time.h>
31#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080032#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070033#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070034#include <sys/resource.h>
35#include <sys/prctl.h>
Kevin Rocardb5c28192017-05-02 15:30:20 -070036#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080037
Haynes Mathew Georgee6e2d442018-02-22 18:51:56 -080038#include <log/log.h>
Haynes Mathew George03c40102016-01-29 17:57:48 -080039#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040#include <cutils/str_parms.h>
41#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070042#include <cutils/atomic.h>
Andy Hung572633e2019-02-19 11:58:24 -080043#include <utils/Timers.h> // systemTime
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080044
Eric Laurentb23d5282013-05-14 15:27:20 -070045#include <hardware/audio_effect.h>
Andy Hung31aca912014-03-20 17:14:59 -070046#include <hardware/audio_alsaops.h>
Suren Baghdasaryan7f924c22018-12-21 15:07:18 -080047#include <processgroup/sched_policy.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070048#include <system/thread_defs.h>
Phil Burkbc991042017-02-24 08:06:44 -080049#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070050#include <audio_effects/effect_aec.h>
51#include <audio_effects/effect_ns.h>
Andy Hungfc044e12017-03-20 09:24:22 -070052#include <audio_utils/clock.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include "audio_hw.h"
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -080054#include "audio_extn.h"
Wei Wangf4837d52017-11-21 14:51:20 -080055#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070056#include "platform_api.h"
57#include <platform.h>
Vineeta Srivastava4b89e372014-06-19 14:21:42 -070058#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080059
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070060#include "sound/compress_params.h"
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -080061#include "audio_extn/tfa_98xx.h"
jasmine cha270b7762018-03-30 15:41:33 +080062#include "audio_extn/maxxaudio.h"
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070063
Eric Laurent397db572016-05-11 11:31:47 -070064/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
65 * COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
Marco Nelissen32093f52015-04-08 15:14:02 -070066#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070067// 2 buffers causes problems with high bitrate files
68#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070069/* ToDo: Check and update a proper value in msec */
70#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
vivek mehta4a824772017-06-08 19:05:49 -070071/* treat as unsigned Q1.13 */
72#define APP_TYPE_GAIN_DEFAULT 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070073#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
vivek mehta4a824772017-06-08 19:05:49 -070074
75/* treat as unsigned Q1.13 */
vivek mehtaa68fea62017-06-08 19:04:02 -070076#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070077
Eric Laurent51f3c662018-04-10 18:21:34 -070078#define RECORD_GAIN_MIN 0.0f
79#define RECORD_GAIN_MAX 1.0f
80#define RECORD_VOLUME_CTL_MAX 0x2000
81
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070082#define PROXY_OPEN_RETRY_COUNT 100
83#define PROXY_OPEN_WAIT_TIME 20
84
vivek mehtadae44712015-07-27 14:13:18 -070085#define MIN_CHANNEL_COUNT 1
86#define DEFAULT_CHANNEL_COUNT 2
87
Jean-Michel Trivic0750692015-10-12 12:12:32 -070088#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
89#define MAX_CHANNEL_COUNT 1
90#else
vivek mehtadae44712015-07-27 14:13:18 -070091#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
92#define XSTR(x) STR(x)
93#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070094#endif
Eric Laurent74b55762017-07-09 17:04:53 -070095#define MAX_HIFI_CHANNEL_COUNT 8
vivek mehtadae44712015-07-27 14:13:18 -070096
Haynes Mathew George03c40102016-01-29 17:57:48 -080097#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
98
Glenn Kasten4f993392014-05-14 07:30:48 -070099static unsigned int configured_low_latency_capture_period_size =
100 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
101
Eric Laurent0e46adf2016-12-16 12:49:24 -0800102
103#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Phil Burkbc991042017-02-24 08:06:44 -0800104#define MMAP_PERIOD_COUNT_MIN 32
105#define MMAP_PERIOD_COUNT_MAX 512
106#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
Eric Laurent0e46adf2016-12-16 12:49:24 -0800107
Andy Hung31aca912014-03-20 17:14:59 -0700108/* This constant enables extended precision handling.
109 * TODO The flag is off until more testing is done.
110 */
111static const bool k_enable_extended_precision = false;
112
Eric Laurentb23d5282013-05-14 15:27:20 -0700113struct pcm_config pcm_config_deep_buffer = {
vivek mehtadae44712015-07-27 14:13:18 -0700114 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700115 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
116 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
117 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
118 .format = PCM_FORMAT_S16_LE,
119 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
120 .stop_threshold = INT_MAX,
121 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
122};
123
124struct pcm_config pcm_config_low_latency = {
vivek mehtadae44712015-07-27 14:13:18 -0700125 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700126 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
127 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
128 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
129 .format = PCM_FORMAT_S16_LE,
130 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
131 .stop_threshold = INT_MAX,
132 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
133};
134
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -0800135struct pcm_config pcm_config_haptics_audio = {
136 .channels = 1,
137 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
138 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
139 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
140 .format = PCM_FORMAT_S16_LE,
141 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
142 .stop_threshold = INT_MAX,
143 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
144};
145
146struct pcm_config pcm_config_haptics = {
147 .channels = 1,
148 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
149 .period_count = 2,
150 .format = PCM_FORMAT_S16_LE,
151 .stop_threshold = INT_MAX,
152 .avail_min = 0,
153};
154
Haynes Mathew George03c40102016-01-29 17:57:48 -0800155static int af_period_multiplier = 4;
156struct pcm_config pcm_config_rt = {
157 .channels = DEFAULT_CHANNEL_COUNT,
158 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
159 .period_size = ULL_PERIOD_SIZE, //1 ms
160 .period_count = 512, //=> buffer size is 512ms
161 .format = PCM_FORMAT_S16_LE,
162 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
163 .stop_threshold = INT_MAX,
164 .silence_threshold = 0,
165 .silence_size = 0,
166 .avail_min = ULL_PERIOD_SIZE, //1 ms
167};
168
Eric Laurentb23d5282013-05-14 15:27:20 -0700169struct pcm_config pcm_config_hdmi_multi = {
170 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
171 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
172 .period_size = HDMI_MULTI_PERIOD_SIZE,
173 .period_count = HDMI_MULTI_PERIOD_COUNT,
174 .format = PCM_FORMAT_S16_LE,
175 .start_threshold = 0,
176 .stop_threshold = INT_MAX,
177 .avail_min = 0,
178};
179
Eric Laurent0e46adf2016-12-16 12:49:24 -0800180struct pcm_config pcm_config_mmap_playback = {
181 .channels = DEFAULT_CHANNEL_COUNT,
182 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
183 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800184 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800185 .format = PCM_FORMAT_S16_LE,
186 .start_threshold = MMAP_PERIOD_SIZE*8,
187 .stop_threshold = INT32_MAX,
188 .silence_threshold = 0,
189 .silence_size = 0,
190 .avail_min = MMAP_PERIOD_SIZE, //1 ms
191};
192
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800193struct pcm_config pcm_config_hifi = {
194 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
195 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
196 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
197 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
198 .format = PCM_FORMAT_S24_3LE,
199 .start_threshold = 0,
200 .stop_threshold = INT_MAX,
201 .avail_min = 0,
202};
203
Eric Laurentb23d5282013-05-14 15:27:20 -0700204struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700205 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700206 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
207 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700208 .stop_threshold = INT_MAX,
209 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700210};
211
Haynes Mathew George03c40102016-01-29 17:57:48 -0800212struct pcm_config pcm_config_audio_capture_rt = {
213 .channels = DEFAULT_CHANNEL_COUNT,
214 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
215 .period_size = ULL_PERIOD_SIZE,
216 .period_count = 512,
217 .format = PCM_FORMAT_S16_LE,
218 .start_threshold = 0,
219 .stop_threshold = INT_MAX,
220 .silence_threshold = 0,
221 .silence_size = 0,
222 .avail_min = ULL_PERIOD_SIZE, //1 ms
223};
224
Eric Laurent0e46adf2016-12-16 12:49:24 -0800225struct pcm_config pcm_config_mmap_capture = {
226 .channels = DEFAULT_CHANNEL_COUNT,
227 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
228 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800229 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800230 .format = PCM_FORMAT_S16_LE,
231 .start_threshold = 0,
232 .stop_threshold = INT_MAX,
233 .silence_threshold = 0,
234 .silence_size = 0,
235 .avail_min = MMAP_PERIOD_SIZE, //1 ms
236};
237
vivek mehtaa68fea62017-06-08 19:04:02 -0700238struct pcm_config pcm_config_voip = {
239 .channels = 1,
240 .period_count = 2,
241 .format = PCM_FORMAT_S16_LE,
242 .stop_threshold = INT_MAX,
243 .avail_min = 0,
244};
245
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700246#define AFE_PROXY_CHANNEL_COUNT 2
247#define AFE_PROXY_SAMPLING_RATE 48000
248
jiabinad481a72018-07-23 12:03:17 -0700249#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 256
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700250#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
251
252struct pcm_config pcm_config_afe_proxy_playback = {
253 .channels = AFE_PROXY_CHANNEL_COUNT,
254 .rate = AFE_PROXY_SAMPLING_RATE,
255 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
256 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
257 .format = PCM_FORMAT_S16_LE,
258 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
259 .stop_threshold = INT_MAX,
260 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
261};
262
jiabinad481a72018-07-23 12:03:17 -0700263#define AFE_PROXY_RECORD_PERIOD_SIZE 256
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700264#define AFE_PROXY_RECORD_PERIOD_COUNT 4
265
266struct pcm_config pcm_config_afe_proxy_record = {
267 .channels = AFE_PROXY_CHANNEL_COUNT,
268 .rate = AFE_PROXY_SAMPLING_RATE,
269 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
270 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
271 .format = PCM_FORMAT_S16_LE,
272 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
jiabin5d0261e2018-05-25 09:43:59 -0700273 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700274 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
275};
276
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700277const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700278 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
279 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -0800280 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800281 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700282 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700283 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700284 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800285 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700286
Eric Laurentb23d5282013-05-14 15:27:20 -0700287 [USECASE_AUDIO_RECORD] = "audio-record",
288 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800289 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George569b7482017-05-08 14:44:27 -0700290 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700291
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800292 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
293 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700294
Eric Laurentb23d5282013-05-14 15:27:20 -0700295 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700296 [USECASE_VOICE2_CALL] = "voice2-call",
297 [USECASE_VOLTE_CALL] = "volte-call",
298 [USECASE_QCHAT_CALL] = "qchat-call",
299 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800300 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
301 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700302
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700303 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
304 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
305
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700306 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
307 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
vivek mehta781065c2017-04-04 12:55:01 -0700308
309 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
310 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
311 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
312
vivek mehtaa68fea62017-06-08 19:04:02 -0700313 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
314 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Nadav Bar3d72cfc2018-01-07 12:19:24 +0200315
316 [USECASE_INCALL_MUSIC_UPLINK] = "incall-music-uplink",
Aniket Kumar Lata99546312018-03-19 21:38:38 -0700317
318 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700319};
320
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800321
322#define STRING_TO_ENUM(string) { #string, string }
323
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800324struct string_to_enum {
325 const char *name;
326 uint32_t value;
327};
328
Haynes Mathew George569b7482017-05-08 14:44:27 -0700329static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800330 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
331 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
332 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Eric Laurent74b55762017-07-09 17:04:53 -0700333 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
Haynes Mathew George569b7482017-05-08 14:44:27 -0700334 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
Eric Laurent74b55762017-07-09 17:04:53 -0700335 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
336 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
337 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
338 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
339 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
340 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
341 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
342 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
343 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800344};
345
Haynes Mathew George5191a852013-09-11 14:19:36 -0700346static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700347static struct audio_device *adev = NULL;
Andy Hung9e737de2017-05-22 10:51:22 -0700348static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700349static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700350//cache last MBDRC cal step level
351static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700352
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800353static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
354static int set_compr_volume(struct audio_stream_out *stream, float left, float right);
355
Haynes Mathew George03c40102016-01-29 17:57:48 -0800356static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
357 int flags __unused)
358{
359 int dir = 0;
360 switch (uc_id) {
361 case USECASE_AUDIO_RECORD_LOW_LATENCY:
362 dir = 1;
363 case USECASE_AUDIO_PLAYBACK_ULL:
364 break;
365 default:
366 return false;
367 }
368
369 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
370 PCM_PLAYBACK : PCM_CAPTURE);
371 if (adev->adm_is_noirq_avail)
372 return adev->adm_is_noirq_avail(adev->adm_data,
373 adev->snd_card, dev_id, dir);
374 return false;
375}
376
377static void register_out_stream(struct stream_out *out)
378{
379 struct audio_device *adev = out->dev;
380 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
381 return;
382
383 if (!adev->adm_register_output_stream)
384 return;
385
386 adev->adm_register_output_stream(adev->adm_data,
387 out->handle,
388 out->flags);
389
390 if (!adev->adm_set_config)
391 return;
392
393 if (out->realtime) {
394 adev->adm_set_config(adev->adm_data,
395 out->handle,
396 out->pcm, &out->config);
397 }
398}
399
400static void register_in_stream(struct stream_in *in)
401{
402 struct audio_device *adev = in->dev;
403 if (!adev->adm_register_input_stream)
404 return;
405
406 adev->adm_register_input_stream(adev->adm_data,
407 in->capture_handle,
408 in->flags);
409
410 if (!adev->adm_set_config)
411 return;
412
413 if (in->realtime) {
414 adev->adm_set_config(adev->adm_data,
415 in->capture_handle,
416 in->pcm,
417 &in->config);
418 }
419}
420
421static void request_out_focus(struct stream_out *out, long ns)
422{
423 struct audio_device *adev = out->dev;
424
Haynes Mathew George03c40102016-01-29 17:57:48 -0800425 if (adev->adm_request_focus_v2) {
426 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
427 } else if (adev->adm_request_focus) {
428 adev->adm_request_focus(adev->adm_data, out->handle);
429 }
430}
431
432static void request_in_focus(struct stream_in *in, long ns)
433{
434 struct audio_device *adev = in->dev;
435
Haynes Mathew George03c40102016-01-29 17:57:48 -0800436 if (adev->adm_request_focus_v2) {
437 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
438 } else if (adev->adm_request_focus) {
439 adev->adm_request_focus(adev->adm_data, in->capture_handle);
440 }
441}
442
443static void release_out_focus(struct stream_out *out, long ns __unused)
444{
445 struct audio_device *adev = out->dev;
446
447 if (adev->adm_abandon_focus)
448 adev->adm_abandon_focus(adev->adm_data, out->handle);
449}
450
451static void release_in_focus(struct stream_in *in, long ns __unused)
452{
453 struct audio_device *adev = in->dev;
454 if (adev->adm_abandon_focus)
455 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
456}
457
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700458static int parse_snd_card_status(struct str_parms * parms, int * card,
459 card_status_t * status)
460{
461 char value[32]={0};
462 char state[32]={0};
463
464 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
465
466 if (ret < 0)
467 return -1;
468
469 // sscanf should be okay as value is of max length 32.
470 // same as sizeof state.
471 if (sscanf(value, "%d,%s", card, state) < 2)
472 return -1;
473
474 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
475 CARD_STATUS_OFFLINE;
476 return 0;
477}
478
vivek mehta40125092017-08-21 18:48:51 -0700479// always call with adev lock held
480void send_gain_dep_calibration_l() {
481 if (last_known_cal_step >= 0)
482 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
483}
484
vivek mehta1a9b7c02015-06-25 11:49:38 -0700485__attribute__ ((visibility ("default")))
486bool audio_hw_send_gain_dep_calibration(int level) {
487 bool ret_val = false;
488 ALOGV("%s: enter ... ", __func__);
489
490 pthread_mutex_lock(&adev_init_lock);
491
492 if (adev != NULL && adev->platform != NULL) {
493 pthread_mutex_lock(&adev->lock);
vivek mehta40125092017-08-21 18:48:51 -0700494 last_known_cal_step = level;
495 send_gain_dep_calibration_l();
vivek mehta1a9b7c02015-06-25 11:49:38 -0700496 pthread_mutex_unlock(&adev->lock);
497 } else {
498 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
499 }
500
501 pthread_mutex_unlock(&adev_init_lock);
502
503 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
504 return ret_val;
505}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700506
jasmine cha270b7762018-03-30 15:41:33 +0800507#ifdef MAXXAUDIO_QDSP_ENABLED
508bool audio_hw_send_ma_parameter(int stream_type, float vol, bool active)
509{
510 bool ret = false;
511 ALOGV("%s: enter ...", __func__);
512
513 pthread_mutex_lock(&adev_init_lock);
514
515 if (adev != NULL && adev->platform != NULL) {
516 pthread_mutex_lock(&adev->lock);
517 ret = audio_extn_ma_set_state(adev, stream_type, vol, active);
518 pthread_mutex_unlock(&adev->lock);
519 }
520
521 pthread_mutex_unlock(&adev_init_lock);
522
523 ALOGV("%s: exit with ret %d", __func__, ret);
524 return ret;
525}
526#else
527#define audio_hw_send_ma_parameter(stream_type, vol, active) (0)
528#endif
529
vivek mehtaa8d7c922016-05-25 14:40:44 -0700530__attribute__ ((visibility ("default")))
531int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
532 int table_size) {
533 int ret_val = 0;
534 ALOGV("%s: enter ... ", __func__);
535
536 pthread_mutex_lock(&adev_init_lock);
537 if (adev == NULL) {
538 ALOGW("%s: adev is NULL .... ", __func__);
539 goto done;
540 }
541
542 pthread_mutex_lock(&adev->lock);
543 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
544 pthread_mutex_unlock(&adev->lock);
545done:
546 pthread_mutex_unlock(&adev_init_lock);
547 ALOGV("%s: exit ... ", __func__);
548 return ret_val;
549}
550
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700551static bool is_supported_format(audio_format_t format)
552{
Eric Laurent8251ac82014-07-23 11:00:25 -0700553 switch (format) {
554 case AUDIO_FORMAT_MP3:
555 case AUDIO_FORMAT_AAC_LC:
556 case AUDIO_FORMAT_AAC_HE_V1:
557 case AUDIO_FORMAT_AAC_HE_V2:
558 return true;
559 default:
560 break;
561 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700562 return false;
563}
564
juyuchenbe5c67e2018-08-29 17:19:20 +0800565static bool is_supported_24bits_audiosource(audio_source_t source)
566{
567 switch (source) {
568 case AUDIO_SOURCE_UNPROCESSED:
569#ifdef ENABLED_24BITS_CAMCORDER
570 case AUDIO_SOURCE_CAMCORDER:
571#endif
572 return true;
573 default:
574 break;
575 }
576 return false;
577}
578
Haynes Mathew George03c40102016-01-29 17:57:48 -0800579static inline bool is_mmap_usecase(audio_usecase_t uc_id)
580{
581 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
582 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
583}
584
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700585static int get_snd_codec_id(audio_format_t format)
586{
587 int id = 0;
588
Eric Laurent8251ac82014-07-23 11:00:25 -0700589 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700590 case AUDIO_FORMAT_MP3:
591 id = SND_AUDIOCODEC_MP3;
592 break;
593 case AUDIO_FORMAT_AAC:
594 id = SND_AUDIOCODEC_AAC;
595 break;
596 default:
597 ALOGE("%s: Unsupported audio format", __func__);
598 }
599
600 return id;
601}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800602
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800603static int audio_ssr_status(struct audio_device *adev)
604{
605 int ret = 0;
606 struct mixer_ctl *ctl;
607 const char *mixer_ctl_name = "Audio SSR Status";
608
609 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
610 ret = mixer_ctl_get_value(ctl, 0);
611 ALOGD("%s: value: %d", __func__, ret);
612 return ret;
613}
614
vivek mehta4a824772017-06-08 19:05:49 -0700615static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
616{
617 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
618}
619
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800620static bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
621{
622 return out_snd_device == SND_DEVICE_OUT_BT_SCO ||
623 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
624 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
625 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
626 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
627 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC;
628
629}
630
631static bool is_a2dp_device(snd_device_t out_snd_device)
632{
633 return out_snd_device == SND_DEVICE_OUT_BT_A2DP;
634}
635
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800636int enable_audio_route(struct audio_device *adev,
637 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800638{
yixuanjiang509f0a72018-09-06 18:37:23 +0800639 snd_device_t snd_device;
Andy Hung11f10e22018-10-19 17:47:12 -0700640 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800641
642 if (usecase == NULL)
643 return -EINVAL;
644
645 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
646
yixuanjiang509f0a72018-09-06 18:37:23 +0800647 if (usecase->type == PCM_CAPTURE)
648 snd_device = usecase->in_snd_device;
649 else
650 snd_device = usecase->out_snd_device;
Yamit Mehtae3b99562016-09-16 22:44:00 +0530651 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Chafb2ea2c2019-03-04 18:12:47 +0800652 audio_extn_ma_set_device(usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800653 audio_extn_utils_send_audio_calibration(adev, usecase);
Andy Hung11f10e22018-10-19 17:47:12 -0700654
655 // we shouldn't truncate mixer_path
656 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
657 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
658 // this also appends to mixer_path
yixuanjiang509f0a72018-09-06 18:37:23 +0800659 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Andy Hung11f10e22018-10-19 17:47:12 -0700660
yixuanjiang509f0a72018-09-06 18:37:23 +0800661 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700662 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700663 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800664
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800665 ALOGV("%s: exit", __func__);
666 return 0;
667}
668
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800669int disable_audio_route(struct audio_device *adev,
670 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800671{
yixuanjiang509f0a72018-09-06 18:37:23 +0800672 snd_device_t snd_device;
Andy Hung11f10e22018-10-19 17:47:12 -0700673 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800674
675 if (usecase == NULL)
676 return -EINVAL;
677
678 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
yixuanjiang509f0a72018-09-06 18:37:23 +0800679 if (usecase->type == PCM_CAPTURE)
680 snd_device = usecase->in_snd_device;
681 else
682 snd_device = usecase->out_snd_device;
Andy Hung11f10e22018-10-19 17:47:12 -0700683
684 // we shouldn't truncate mixer_path
685 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
686 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
687 // this also appends to mixer_path
yixuanjiang509f0a72018-09-06 18:37:23 +0800688 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700689 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Andy Hung11f10e22018-10-19 17:47:12 -0700690
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700691 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000692 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800693
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800694 ALOGV("%s: exit", __func__);
695 return 0;
696}
697
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800698int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700699 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800700{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700701 int i, num_devices = 0;
702 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800703 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800704 if (snd_device < SND_DEVICE_MIN ||
705 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800706 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800707 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800708 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700709
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700710 platform_send_audio_calibration(adev->platform, snd_device);
711
vivek mehtade4849c2016-03-03 17:23:38 -0800712 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700713 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700714 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800715 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700716 }
717
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700718 /* due to the possibility of calibration overwrite between listen
719 and audio, notify sound trigger hal before audio calibration is sent */
720 audio_extn_sound_trigger_update_device_status(snd_device,
721 ST_EVENT_SND_DEVICE_BUSY);
722
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700723 if (audio_extn_spkr_prot_is_enabled())
724 audio_extn_spkr_prot_calib_cancel(adev);
725
zhaoyang yin4211fad2015-06-04 21:13:25 +0800726 audio_extn_dsm_feedback_enable(adev, snd_device, true);
727
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700728 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800729 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
juyuchen1d05ba32018-03-31 16:03:51 +0800730 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700731 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
732 audio_extn_spkr_prot_is_enabled()) {
Aniket Kumar Lata9d6679a2018-04-11 18:13:23 -0700733 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800734 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700735 }
736 if (audio_extn_spkr_prot_start_processing(snd_device)) {
737 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800738 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700739 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700740 } else if (platform_can_split_snd_device(snd_device,
741 &num_devices,
742 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700743 for (i = 0; i < num_devices; i++) {
744 enable_snd_device(adev, new_snd_devices[i]);
745 }
vivek mehtab6506412015-08-07 16:55:17 -0700746 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700747 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800748 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
749 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
750 ALOGE(" %s: Invalid sound device returned", __func__);
751 goto on_error;
752 }
Ed Tam70b5c142016-03-21 19:14:29 -0700753
Eric Laurent2e140aa2016-06-30 17:14:46 -0700754 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Aniket Kumar Lataa158e862018-05-11 17:28:40 -0700755
756 if (is_a2dp_device(snd_device) &&
757 (audio_extn_a2dp_start_playback() < 0)) {
758 ALOGE("%s: failed to configure A2DP control path", __func__);
759 goto on_error;
760 }
761
vivek mehtade4849c2016-03-03 17:23:38 -0800762 audio_route_apply_and_update_path(adev->audio_route, device_name);
763 }
764on_success:
765 adev->snd_dev_ref_cnt[snd_device]++;
766 ret_val = 0;
767on_error:
768 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800769}
770
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800771int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700772 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800773{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700774 int i, num_devices = 0;
775 snd_device_t new_snd_devices[2];
776
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800777 if (snd_device < SND_DEVICE_MIN ||
778 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800779 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800780 return -EINVAL;
781 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700782 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
783 ALOGE("%s: device ref cnt is already 0", __func__);
784 return -EINVAL;
785 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800786 audio_extn_tfa_98xx_disable_speaker(snd_device);
787
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700788 adev->snd_dev_ref_cnt[snd_device]--;
789 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800790 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800791
792 if (is_a2dp_device(snd_device))
793 audio_extn_a2dp_stop_playback();
794
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700795 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800796 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700797 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700798 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
799 audio_extn_spkr_prot_is_enabled()) {
800 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700801
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700802 // FIXME b/65363602: bullhead is the only Nexus with audio_extn_spkr_prot_is_enabled()
803 // and does not use speaker swap. As this code causes a problem with device enable ref
804 // counting we remove it for now.
vivek mehtae59cfb22017-06-16 15:57:11 -0700805 // when speaker device is disabled, reset swap.
806 // will be renabled on usecase start
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700807 // platform_set_swap_channels(adev, false);
vivek mehtae59cfb22017-06-16 15:57:11 -0700808
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700809 } else if (platform_can_split_snd_device(snd_device,
810 &num_devices,
811 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700812 for (i = 0; i < num_devices; i++) {
813 disable_snd_device(adev, new_snd_devices[i]);
814 }
vivek mehtab6506412015-08-07 16:55:17 -0700815 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700816 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800817 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
818 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
819 ALOGE(" %s: Invalid sound device returned", __func__);
820 return -EINVAL;
821 }
822
Eric Laurent2e140aa2016-06-30 17:14:46 -0700823 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800824 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700825 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700826 audio_extn_sound_trigger_update_device_status(snd_device,
827 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700828 }
vivek mehtab6506412015-08-07 16:55:17 -0700829
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800830 return 0;
831}
832
Vignesh Kulothungan64698822018-01-23 11:25:18 -0800833#ifdef DYNAMIC_ECNS_ENABLED
834static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
835 struct stream_in *in,
836 struct audio_effect_config effect_config,
837 unsigned int param_value)
838{
839 char mixer_ctl_name[] = "Audio Effect";
840 long set_values[6];
841
842 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
843 if (!ctl) {
844 ALOGE("%s: Could not get mixer ctl - %s",
845 __func__, mixer_ctl_name);
846 return -EINVAL;
847 }
848
849 set_values[0] = 1; //0:Rx 1:Tx
850 set_values[1] = in->app_type_cfg.app_type;
851 set_values[2] = (long)effect_config.module_id;
852 set_values[3] = (long)effect_config.instance_id;
853 set_values[4] = (long)effect_config.param_id;
854 set_values[5] = param_value;
855
856 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
857
858 return 0;
859
860}
861
862static int update_effect_param_ecns(struct audio_usecase *usecase,
863 unsigned int module_id, int effect_type,
864 unsigned int *param_value)
865{
866 int ret = 0;
867 struct audio_effect_config other_effect_config;
868 struct stream_in *in = NULL;
869
870 if (!usecase)
871 return -EINVAL;
872
873 in = usecase->stream.in;
874
875 /* Get the effect config data of the other effect */
876 ret = platform_get_effect_config_data(usecase->in_snd_device,
877 &other_effect_config,
878 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
879 if (ret < 0) {
880 ALOGE("%s Failed to get effect params %d", __func__, ret);
881 return ret;
882 }
883
884 if (module_id == other_effect_config.module_id) {
885 //Same module id for AEC/NS. Values need to be combined
886 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
887 ((effect_type == EFFECT_NS) && (in->enable_aec)))
888 *param_value |= other_effect_config.param_value;
889 }
890
891 return ret;
892}
893
894static int enable_disable_effect(struct audio_device *adev, struct stream_in *in,
895 int effect_type, bool enable)
896{
897 struct audio_effect_config effect_config;
898 struct audio_usecase *usecase = NULL;
899 int ret = 0;
900 unsigned int param_value = 0;
901
902 if (!in) {
903 ALOGE("%s: Invalid input stream", __func__);
904 return -EINVAL;
905 }
906
907 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
908
909 usecase = get_usecase_from_list(adev, in->usecase);
910
911 ret = platform_get_effect_config_data(usecase->in_snd_device,
912 &effect_config, effect_type);
913 if (ret < 0) {
914 ALOGE("%s Failed to get module id %d", __func__, ret);
915 return ret;
916 }
917 ALOGV("%s: module %d app_type %d usecase->id:%d usecase->in_snd_device:%d",
918 __func__, effect_config.module_id, in->app_type_cfg.app_type,
919 usecase->id, usecase->in_snd_device);
920
921 if (enable)
922 param_value = effect_config.param_value;
923
924 /*Special handling for AEC & NS effects Param values need to be
925 updated if module ids are same*/
926
927 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
928 ret = update_effect_param_ecns(usecase, effect_config.module_id,
929 effect_type, &param_value);
930 if (ret < 0)
931 return ret;
932 }
933
934 ret = send_effect_enable_disable_mixer_ctl(adev, in,
935 effect_config, param_value);
936
937 return ret;
938}
939
940static int check_and_enable_effect(struct audio_device *adev)
941{
942 int ret = 0;
943
944 struct listnode *node;
945 struct stream_in *in = NULL;
946
947 list_for_each(node, &adev->usecase_list)
948 {
949 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
950 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL) {
951 in = usecase->stream.in;
952
953 if (in->standby)
954 continue;
955
956 if (in->enable_aec) {
957 ret = enable_disable_effect(adev, in, EFFECT_AEC, true);
958 }
959
960 if (in->enable_ns &&
961 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
962 ret = enable_disable_effect(adev, in, EFFECT_NS, true);
963 }
964 }
965 }
966
967 return ret;
968}
969#else
970#define enable_disable_effect(w, x, y, z) -ENOSYS
971#define check_and_enable_effect(x) -ENOSYS
972#endif
973
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700974/*
975 legend:
976 uc - existing usecase
977 new_uc - new usecase
978 d1, d11, d2 - SND_DEVICE enums
979 a1, a2 - corresponding ANDROID device enums
980 B, B1, B2 - backend strings
981
982case 1
983 uc->dev d1 (a1) B1
984 new_uc->dev d1 (a1), d2 (a2) B1, B2
985
986 resolution: disable and enable uc->dev on d1
987
988case 2
989 uc->dev d1 (a1) B1
990 new_uc->dev d11 (a1) B1
991
992 resolution: need to switch uc since d1 and d11 are related
993 (e.g. speaker and voice-speaker)
994 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
995
996case 3
997 uc->dev d1 (a1) B1
998 new_uc->dev d2 (a2) B2
999
1000 resolution: no need to switch uc
1001
1002case 4
1003 uc->dev d1 (a1) B
1004 new_uc->dev d2 (a2) B
1005
1006 resolution: disable enable uc-dev on d2 since backends match
1007 we cannot enable two streams on two different devices if they
1008 share the same backend. e.g. if offload is on speaker device using
1009 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1010 using the same backend, offload must also be switched to voice-handset.
1011
1012case 5
1013 uc->dev d1 (a1) B
1014 new_uc->dev d1 (a1), d2 (a2) B
1015
1016 resolution: disable enable uc-dev on d2 since backends match
1017 we cannot enable two streams on two different devices if they
1018 share the same backend.
1019
1020case 6
1021 uc->dev d1 a1 B1
1022 new_uc->dev d2 a1 B2
1023
1024 resolution: no need to switch
1025
1026case 7
1027
1028 uc->dev d1 (a1), d2 (a2) B1, B2
1029 new_uc->dev d1 B1
1030
1031 resolution: no need to switch
1032
1033*/
1034static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
1035 struct audio_usecase *new_uc,
1036 snd_device_t new_snd_device)
1037{
1038 audio_devices_t a1 = uc->stream.out->devices;
1039 audio_devices_t a2 = new_uc->stream.out->devices;
1040
1041 snd_device_t d1 = uc->out_snd_device;
1042 snd_device_t d2 = new_snd_device;
1043
1044 // Treat as a special case when a1 and a2 are not disjoint
1045 if ((a1 != a2) && (a1 & a2)) {
1046 snd_device_t d3[2];
1047 int num_devices = 0;
1048 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
1049 &num_devices,
1050 d3);
1051 if (ret < 0) {
1052 if (ret != -ENOSYS) {
1053 ALOGW("%s failed to split snd_device %d",
1054 __func__,
1055 popcount(a1) > 1 ? d1 : d2);
1056 }
1057 goto end;
1058 }
1059
1060 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1061 // But if it does happen, we need to give priority to d2 if
1062 // the combo devices active on the existing usecase share a backend.
1063 // This is because we cannot have a usecase active on a combo device
1064 // and a new usecase requests one device in this combo pair.
1065 if (platform_check_backends_match(d3[0], d3[1])) {
1066 return d2; // case 5
1067 } else {
1068 return d1; // case 1
1069 }
1070 } else {
1071 if (platform_check_backends_match(d1, d2)) {
1072 return d2; // case 2, 4
1073 } else {
1074 return d1; // case 6, 3
1075 }
1076 }
1077
1078end:
1079 return d2; // return whatever was calculated before.
1080}
1081
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001082static void check_and_route_playback_usecases(struct audio_device *adev,
1083 struct audio_usecase *uc_info,
1084 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001085{
1086 struct listnode *node;
1087 struct audio_usecase *usecase;
1088 bool switch_device[AUDIO_USECASE_MAX];
1089 int i, num_uc_to_switch = 0;
1090
Haynes Mathew George137a2ee2017-05-23 17:03:35 -07001091 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
1092 uc_info,
1093 snd_device);
David Linee3fe402017-03-13 10:00:42 -07001094
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001095 /* For a2dp device reconfigure all active sessions
1096 * with new AFE encoder format based on a2dp state
1097 */
1098 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Aniket Kumar Lata9723a962018-05-16 17:41:55 -07001099 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1100 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001101 audio_extn_a2dp_is_force_device_switch()) {
1102 force_routing = true;
1103 }
1104
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001105 /*
1106 * This function is to make sure that all the usecases that are active on
1107 * the hardware codec backend are always routed to any one device that is
1108 * handled by the hardware codec.
1109 * For example, if low-latency and deep-buffer usecases are currently active
1110 * on speaker and out_set_parameters(headset) is received on low-latency
1111 * output, then we have to make sure deep-buffer is also switched to headset,
1112 * because of the limitation that both the devices cannot be enabled
1113 * at the same time as they share the same backend.
1114 */
1115 /* Disable all the usecases on the shared backend other than the
1116 specified usecase */
1117 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1118 switch_device[i] = false;
1119
1120 list_for_each(node, &adev->usecase_list) {
1121 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -07001122 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
1123 continue;
1124
1125 if (force_routing ||
1126 (usecase->out_snd_device != snd_device &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -07001127 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
1128 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -07001129 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001130 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1131 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -07001132 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001133 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001134 switch_device[usecase->id] = true;
1135 num_uc_to_switch++;
1136 }
1137 }
1138
1139 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001140 list_for_each(node, &adev->usecase_list) {
1141 usecase = node_to_item(node, struct audio_usecase, list);
1142 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001143 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +09001144 }
1145 }
1146
Haynes Mathew George2d809e02016-09-22 17:38:16 -07001147 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +09001148 list_for_each(node, &adev->usecase_list) {
1149 usecase = node_to_item(node, struct audio_usecase, list);
1150 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -07001151 d_device = derive_playback_snd_device(usecase, uc_info,
1152 snd_device);
1153 enable_snd_device(adev, d_device);
1154 /* Update the out_snd_device before enabling the audio route */
1155 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001156 }
1157 }
1158
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001159 /* Re-route all the usecases on the shared backend other than the
1160 specified usecase to new snd devices */
1161 list_for_each(node, &adev->usecase_list) {
1162 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001163 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001164 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001165 }
1166 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001167 }
1168}
1169
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001170static void check_and_route_capture_usecases(struct audio_device *adev,
1171 struct audio_usecase *uc_info,
1172 snd_device_t snd_device)
1173{
1174 struct listnode *node;
1175 struct audio_usecase *usecase;
1176 bool switch_device[AUDIO_USECASE_MAX];
1177 int i, num_uc_to_switch = 0;
1178
vivek mehta4ed66e62016-04-15 23:33:34 -07001179 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
1180
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001181 /*
1182 * This function is to make sure that all the active capture usecases
1183 * are always routed to the same input sound device.
1184 * For example, if audio-record and voice-call usecases are currently
1185 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1186 * is received for voice call then we have to make sure that audio-record
1187 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1188 * because of the limitation that two devices cannot be enabled
1189 * at the same time if they share the same backend.
1190 */
1191 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1192 switch_device[i] = false;
1193
1194 list_for_each(node, &adev->usecase_list) {
1195 usecase = node_to_item(node, struct audio_usecase, list);
1196 if (usecase->type != PCM_PLAYBACK &&
1197 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -07001198 usecase->in_snd_device != snd_device &&
Carter Hsu0a1160c2018-10-04 09:24:36 +08001199 ((uc_info->type == VOICE_CALL &&
1200 usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL) ||
1201 platform_check_backends_match(snd_device,\
1202 usecase->in_snd_device)) &&
Anish Kumarff864712015-06-03 13:35:11 -07001203 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001204 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1205 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001206 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001207 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001208 switch_device[usecase->id] = true;
1209 num_uc_to_switch++;
1210 }
1211 }
1212
1213 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001214 list_for_each(node, &adev->usecase_list) {
1215 usecase = node_to_item(node, struct audio_usecase, list);
1216 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001217 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001218 }
1219 }
1220
1221 list_for_each(node, &adev->usecase_list) {
1222 usecase = node_to_item(node, struct audio_usecase, list);
1223 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001224 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001225 }
1226 }
1227
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001228 /* Re-route all the usecases on the shared backend other than the
1229 specified usecase to new snd devices */
1230 list_for_each(node, &adev->usecase_list) {
1231 usecase = node_to_item(node, struct audio_usecase, list);
1232 /* Update the in_snd_device only before enabling the audio route */
1233 if (switch_device[usecase->id] ) {
1234 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001235 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001236 }
1237 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001238 }
1239}
1240
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001241/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001242static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001243{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001244 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001245 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001246
1247 switch (channels) {
1248 /*
1249 * Do not handle stereo output in Multi-channel cases
1250 * Stereo case is handled in normal playback path
1251 */
1252 case 6:
1253 ALOGV("%s: HDMI supports 5.1", __func__);
1254 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1255 break;
1256 case 8:
1257 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
1258 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1259 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
1260 break;
1261 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001262 ALOGE("HDMI does not support multi channel playback");
1263 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001264 break;
1265 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001266 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001267}
1268
Andy Hung18859412017-08-09 11:47:21 -07001269static ssize_t read_usb_sup_sample_rates(bool is_playback,
1270 uint32_t *supported_sample_rates,
1271 uint32_t max_rates)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001272{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001273 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1274 supported_sample_rates,
1275 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001276#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001277 for (ssize_t i=0; i<count; i++) {
1278 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1279 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001280 }
1281#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001282 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001283}
1284
Haynes Mathew George569b7482017-05-08 14:44:27 -07001285static int read_usb_sup_channel_masks(bool is_playback,
1286 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001287 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001288{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001289 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001290 int channel_count;
1291 uint32_t num_masks = 0;
1292 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1293 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001294 }
Eric Laurent74b55762017-07-09 17:04:53 -07001295 if (is_playback) {
Andy Hung6c1afb12017-12-22 11:34:41 -08001296 // start from 2 channels as framework currently doesn't support mono.
1297 // TODO: consider only supporting channel index masks beyond stereo here.
1298 for (channel_count = FCC_2;
1299 channel_count <= channels && num_masks < max_masks;
1300 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001301 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1302 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001303 for (channel_count = FCC_2;
1304 channel_count <= channels && num_masks < max_masks;
1305 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001306 supported_channel_masks[num_masks++] =
1307 audio_channel_mask_for_index_assignment_from_count(channel_count);
1308 }
1309 } else {
1310 // For capture we report all supported channel masks from 1 channel up.
1311 channel_count = MIN_CHANNEL_COUNT;
1312 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1313 // indexed mask
1314 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
Andy Hung88ce1d92018-10-29 18:31:12 -07001315 const audio_channel_mask_t mask =
Eric Laurent74b55762017-07-09 17:04:53 -07001316 audio_channel_in_mask_from_count(channel_count);
Andy Hung88ce1d92018-10-29 18:31:12 -07001317 supported_channel_masks[num_masks++] = mask;
1318 const audio_channel_mask_t index_mask =
1319 audio_channel_mask_for_index_assignment_from_count(channel_count);
1320 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
1321 supported_channel_masks[num_masks++] = index_mask;
1322 }
Eric Laurent74b55762017-07-09 17:04:53 -07001323 }
1324 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001325#ifdef NDEBUG
1326 for (size_t i = 0; i < num_masks; ++i) {
1327 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1328 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
1329 }
1330#endif
Eric Laurent74b55762017-07-09 17:04:53 -07001331 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001332}
1333
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001334static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001335 audio_format_t *supported_formats,
1336 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001337{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001338 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001339 switch (bitwidth) {
1340 case 24:
1341 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001342 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001343 break;
1344 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001345 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001346 break;
1347 case 16:
1348 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001349 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001350 break;
1351 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001352 ALOGV("%s: %s supported format %d", __func__,
1353 is_playback ? "P" : "C", bitwidth);
1354 return 1;
1355}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001356
Haynes Mathew George569b7482017-05-08 14:44:27 -07001357static int read_usb_sup_params_and_compare(bool is_playback,
1358 audio_format_t *format,
1359 audio_format_t *supported_formats,
1360 uint32_t max_formats,
1361 audio_channel_mask_t *mask,
1362 audio_channel_mask_t *supported_channel_masks,
1363 uint32_t max_masks,
1364 uint32_t *rate,
1365 uint32_t *supported_sample_rates,
1366 uint32_t max_rates) {
1367 int ret = 0;
1368 int num_formats;
1369 int num_masks;
1370 int num_rates;
1371 int i;
1372
1373 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1374 max_formats);
1375 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1376 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001377
Haynes Mathew George569b7482017-05-08 14:44:27 -07001378 num_rates = read_usb_sup_sample_rates(is_playback,
1379 supported_sample_rates, max_rates);
1380
1381#define LUT(table, len, what, dflt) \
1382 for (i=0; i<len && (table[i] != what); i++); \
1383 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1384
1385 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1386 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1387 LUT(supported_sample_rates, num_rates, *rate, 0);
1388
1389#undef LUT
1390 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001391}
1392
Andy Hungd9653bd2017-08-01 19:31:39 -07001393static bool is_usb_ready(struct audio_device *adev, bool is_playback)
1394{
1395 // Check if usb is ready.
1396 // The usb device may have been removed quickly after insertion and hence
1397 // no longer available. This will show up as empty channel masks, or rates.
1398
1399 pthread_mutex_lock(&adev->lock);
1400 uint32_t supported_sample_rate;
1401
1402 // we consider usb ready if we can fetch at least one sample rate.
1403 const bool ready = read_usb_sup_sample_rates(
1404 is_playback, &supported_sample_rate, 1 /* max_rates */) > 0;
1405 pthread_mutex_unlock(&adev->lock);
1406 return ready;
1407}
1408
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001409static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1410{
1411 struct audio_usecase *usecase;
1412 struct listnode *node;
1413
1414 list_for_each(node, &adev->usecase_list) {
1415 usecase = node_to_item(node, struct audio_usecase, list);
1416 if (usecase->type == VOICE_CALL) {
1417 ALOGV("%s: usecase id %d", __func__, usecase->id);
1418 return usecase->id;
1419 }
1420 }
1421 return USECASE_INVALID;
1422}
1423
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001424struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1425 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001426{
1427 struct audio_usecase *usecase;
1428 struct listnode *node;
1429
1430 list_for_each(node, &adev->usecase_list) {
1431 usecase = node_to_item(node, struct audio_usecase, list);
1432 if (usecase->id == uc_id)
1433 return usecase;
1434 }
1435 return NULL;
1436}
1437
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001438static bool force_device_switch(struct audio_usecase *usecase)
1439{
1440 if (usecase->stream.out == NULL) {
1441 ALOGE("%s: stream.out is NULL", __func__);
1442 return false;
1443 }
1444
1445 // Force all A2DP output devices to reconfigure for proper AFE encode format
1446 // Also handle a case where in earlier A2DP start failed as A2DP stream was
1447 // in suspended state, hence try to trigger a retry when we again get a routing request.
1448 if ((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
1449 audio_extn_a2dp_is_force_device_switch()) {
1450 ALOGD("%s: Force A2DP device switch to update new encoder config", __func__);
1451 return true;
1452 }
1453
1454 return false;
1455}
1456
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001457struct stream_in *adev_get_active_input(const struct audio_device *adev)
1458{
1459 struct listnode *node;
1460 struct stream_in *last_active_in = NULL;
1461
1462 /* Get last added active input.
1463 * TODO: We may use a priority mechanism to pick highest priority active source */
1464 list_for_each(node, &adev->usecase_list)
1465 {
1466 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
1467 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL) {
1468 last_active_in = usecase->stream.in;
1469 }
1470 }
1471
1472 return last_active_in;
1473}
1474
1475struct stream_in *get_voice_communication_input(const struct audio_device *adev)
1476{
1477 struct listnode *node;
1478
1479 /* First check active inputs with voice communication source and then
1480 * any input if audio mode is in communication */
1481 list_for_each(node, &adev->usecase_list)
1482 {
1483 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
1484 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
1485 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1486 return usecase->stream.in;
1487 }
1488 }
1489 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
1490 return adev_get_active_input(adev);
1491 }
1492 return NULL;
1493}
1494
HW Leef88584d2019-03-18 17:27:18 +08001495int select_devices_with_force_switch(struct audio_device *adev,
1496 audio_usecase_t uc_id,
1497 bool force_switch)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001498{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001499 snd_device_t out_snd_device = SND_DEVICE_NONE;
1500 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001501 struct audio_usecase *usecase = NULL;
1502 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001503 struct audio_usecase *hfp_usecase = NULL;
1504 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001505 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001506 int status = 0;
Eric Laurentf4520b02017-09-20 18:31:58 -07001507 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1508 USECASE_AUDIO_PLAYBACK_VOIP);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001509
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001510 usecase = get_usecase_from_list(adev, uc_id);
1511 if (usecase == NULL) {
1512 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1513 return -EINVAL;
1514 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001515
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001516 if ((usecase->type == VOICE_CALL) ||
1517 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001518 out_snd_device = platform_get_output_snd_device(adev->platform,
1519 usecase->stream.out->devices);
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001520 in_snd_device = platform_get_input_snd_device(adev->platform,
1521 NULL,
1522 usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001523 usecase->devices = usecase->stream.out->devices;
1524 } else {
1525 /*
1526 * If the voice call is active, use the sound devices of voice call usecase
1527 * so that it would not result any device switch. All the usecases will
1528 * be switched to new device when select_devices() is called for voice call
1529 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001530 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001531 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001532 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001533 vc_usecase = get_usecase_from_list(adev,
1534 get_voice_usecase_id_from_list(adev));
1535 if ((vc_usecase != NULL) &&
1536 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
juyuchend194b432018-11-16 14:15:16 +08001537 (vc_usecase->devices == AUDIO_DEVICE_OUT_HEARING_AID) ||
1538 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001539 in_snd_device = vc_usecase->in_snd_device;
1540 out_snd_device = vc_usecase->out_snd_device;
1541 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001542 } else if (audio_extn_hfp_is_active(adev)) {
1543 hfp_ucid = audio_extn_hfp_get_usecase();
1544 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1545 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1546 in_snd_device = hfp_usecase->in_snd_device;
1547 out_snd_device = hfp_usecase->out_snd_device;
1548 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001549 }
1550 if (usecase->type == PCM_PLAYBACK) {
1551 usecase->devices = usecase->stream.out->devices;
1552 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001553 if (out_snd_device == SND_DEVICE_NONE) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001554 struct stream_out *voip_out = adev->primary_output;
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001555 struct stream_in *voip_in = get_voice_communication_input(adev);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001556
Eric Laurentb23d5282013-05-14 15:27:20 -07001557 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001558 usecase->stream.out->devices);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001559
1560 if (voip_usecase)
1561 voip_out = voip_usecase->stream.out;
1562
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001563 if (usecase->stream.out == voip_out && voip_in != NULL) {
1564 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001565 }
1566 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001567 } else if (usecase->type == PCM_CAPTURE) {
1568 usecase->devices = usecase->stream.in->device;
1569 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001570 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001571 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001572 struct stream_in *voip_in = get_voice_communication_input(adev);
1573
1574 if (voip_in != NULL) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001575
1576 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1577 USECASE_AUDIO_PLAYBACK_VOIP);
1578
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001579 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001580 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1581 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001582 } else if (voip_usecase) {
1583 out_device = voip_usecase->stream.out->devices;
juyuchend194b432018-11-16 14:15:16 +08001584 } else if (adev->primary_output &&
1585 !adev->primary_output->standby) {
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001586 out_device = adev->primary_output->devices;
juyuchend194b432018-11-16 14:15:16 +08001587 } else {
1588 /* forcing speaker o/p device to get matching i/p pair
1589 in case o/p is not routed from same primary HAL */
1590 out_device = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001591 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001592 }
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001593 in_snd_device = platform_get_input_snd_device(adev->platform,
1594 usecase->stream.in,
1595 out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001596 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001597 }
1598 }
1599
1600 if (out_snd_device == usecase->out_snd_device &&
1601 in_snd_device == usecase->in_snd_device) {
HW Leef88584d2019-03-18 17:27:18 +08001602 if (!force_device_switch(usecase) && !force_switch)
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001603 return 0;
1604 }
1605
1606 if (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready()) {
1607 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1608 return 0;
1609 }
1610
Aniket Kumar Lata9723a962018-05-16 17:41:55 -07001611 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
1612 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001613 (!audio_extn_a2dp_is_ready())) {
1614 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
juyuchen9baad392018-06-05 19:02:10 +08001615 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
1616 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
1617 else
1618 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001619 }
1620
juyuchen66c4ecf2018-08-06 15:39:34 +08001621 if (usecase->id == USECASE_INCALL_MUSIC_UPLINK) {
1622 out_snd_device = SND_DEVICE_OUT_VOICE_MUSIC_TX;
1623 }
1624
Eric Laurent2bafff12016-03-17 12:17:23 -07001625 if (out_snd_device != SND_DEVICE_NONE &&
1626 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1627 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1628 __func__,
1629 use_case_table[uc_id],
1630 adev->last_logged_snd_device[uc_id][0],
1631 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1632 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1633 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1634 -1,
1635 out_snd_device,
1636 platform_get_snd_device_name(out_snd_device),
1637 platform_get_snd_device_acdb_id(out_snd_device));
1638 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1639 }
1640 if (in_snd_device != SND_DEVICE_NONE &&
1641 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1642 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1643 __func__,
1644 use_case_table[uc_id],
1645 adev->last_logged_snd_device[uc_id][1],
1646 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1647 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1648 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1649 -1,
1650 in_snd_device,
1651 platform_get_snd_device_name(in_snd_device),
1652 platform_get_snd_device_acdb_id(in_snd_device));
1653 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1654 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001655
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001656 /*
1657 * Limitation: While in call, to do a device switch we need to disable
1658 * and enable both RX and TX devices though one of them is same as current
1659 * device.
1660 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001661 if ((usecase->type == VOICE_CALL) &&
1662 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1663 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001664 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001665 /* Disable sidetone only if voice call already exists */
1666 if (voice_is_call_state_active(adev))
1667 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001668 }
1669
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001670 /* Disable current sound devices */
1671 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001672 disable_audio_route(adev, usecase);
1673 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001674 }
1675
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001676 if (usecase->in_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->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001679 }
1680
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001681 /* Applicable only on the targets that has external modem.
1682 * New device information should be sent to modem before enabling
1683 * the devices to reduce in-call device switch time.
1684 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001685 if ((usecase->type == VOICE_CALL) &&
1686 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1687 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001688 status = platform_switch_voice_call_enable_device_config(adev->platform,
1689 out_snd_device,
1690 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001691 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001692
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001693 /* Enable new sound devices */
1694 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001695 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001696 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) ||
1697 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001698 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001699 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001700 }
1701
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001702 if (in_snd_device != SND_DEVICE_NONE) {
1703 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001704 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001705 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001706
Eric Laurentb23d5282013-05-14 15:27:20 -07001707 if (usecase->type == VOICE_CALL)
1708 status = platform_switch_voice_call_device_post(adev->platform,
1709 out_snd_device,
1710 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001711
sangwoo170731f2013-06-08 15:36:36 +09001712 usecase->in_snd_device = in_snd_device;
1713 usecase->out_snd_device = out_snd_device;
1714
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001715 audio_extn_tfa_98xx_set_mode();
1716
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001717 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001718
Vignesh Kulothungan64698822018-01-23 11:25:18 -08001719 /* If input stream is already running the effect needs to be
1720 applied on the new input device that's being enabled here. */
1721 if (in_snd_device != SND_DEVICE_NONE)
1722 check_and_enable_effect(adev);
1723
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001724 /* Applicable only on the targets that has external modem.
1725 * Enable device command should be sent to modem only after
1726 * enabling voice call mixer controls
1727 */
vivek mehta765eb642015-08-07 19:46:06 -07001728 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001729 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1730 out_snd_device,
1731 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001732 /* Enable sidetone only if voice call already exists */
1733 if (voice_is_call_state_active(adev))
1734 voice_set_sidetone(adev, out_snd_device, true);
1735 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001736
Yung Ti Sue9d64f92018-06-22 17:38:47 +08001737 if (usecase->type != PCM_CAPTURE && voip_usecase) {
Eric Laurentf4520b02017-09-20 18:31:58 -07001738 struct stream_out *voip_out = voip_usecase->stream.out;
1739 audio_extn_utils_send_app_type_gain(adev,
1740 voip_out->app_type_cfg.app_type,
1741 &voip_out->app_type_cfg.gain[0]);
1742 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001743 return status;
1744}
1745
HW Leef88584d2019-03-18 17:27:18 +08001746int select_devices(struct audio_device *adev,
1747 audio_usecase_t uc_id)
1748{
1749 return select_devices_with_force_switch(adev, uc_id, false);
1750}
1751
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001752static int stop_input_stream(struct stream_in *in)
1753{
1754 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001755 struct audio_usecase *uc_info;
1756 struct audio_device *adev = in->dev;
1757
Eric Laurent994a6932013-07-17 11:51:42 -07001758 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001759 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001760
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001761 uc_info = get_usecase_from_list(adev, in->usecase);
1762 if (uc_info == NULL) {
1763 ALOGE("%s: Could not find the usecase (%d) in the list",
1764 __func__, in->usecase);
1765 return -EINVAL;
1766 }
1767
vivek mehta781065c2017-04-04 12:55:01 -07001768 /* Close in-call recording streams */
1769 voice_check_and_stop_incall_rec_usecase(adev, in);
1770
Eric Laurent150dbfe2013-02-27 14:31:02 -08001771 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001772 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001773
1774 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001775 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001776
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001777 list_remove(&uc_info->list);
1778 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001779
Eric Laurent994a6932013-07-17 11:51:42 -07001780 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001781 return ret;
1782}
1783
1784int start_input_stream(struct stream_in *in)
1785{
1786 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001787 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001788 struct audio_usecase *uc_info;
1789 struct audio_device *adev = in->dev;
1790
Eric Laurent994a6932013-07-17 11:51:42 -07001791 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001792
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001793 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1794 return -EIO;
1795
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001796 if (in->card_status == CARD_STATUS_OFFLINE ||
1797 adev->card_status == CARD_STATUS_OFFLINE) {
1798 ALOGW("in->card_status or adev->card_status offline, try again");
1799 ret = -EAGAIN;
1800 goto error_config;
1801 }
1802
vivek mehta781065c2017-04-04 12:55:01 -07001803 /* Check if source matches incall recording usecase criteria */
1804 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1805 if (ret)
1806 goto error_config;
1807 else
1808 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1809
Eric Laurentb23d5282013-05-14 15:27:20 -07001810 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001811 if (in->pcm_device_id < 0) {
1812 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1813 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001814 ret = -EINVAL;
1815 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001816 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001817
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001818 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1819 uc_info->id = in->usecase;
1820 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001821 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001822 uc_info->devices = in->device;
1823 uc_info->in_snd_device = SND_DEVICE_NONE;
1824 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001825
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001826 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001827
Wei Wangf4837d52017-11-21 14:51:20 -08001828 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001829 audio_extn_perf_lock_acquire();
1830
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001831 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001832
Eric Laurent0e46adf2016-12-16 12:49:24 -08001833 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001834 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001835 ALOGE("%s: pcm stream not ready", __func__);
1836 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001837 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001838 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001839 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001840 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1841 goto error_open;
1842 }
1843 } else {
1844 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1845 unsigned int pcm_open_retry_count = 0;
1846
1847 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1848 flags |= PCM_MMAP | PCM_NOIRQ;
1849 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1850 } else if (in->realtime) {
1851 flags |= PCM_MMAP | PCM_NOIRQ;
1852 }
1853
1854 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1855 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1856
1857 while (1) {
1858 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1859 flags, &in->config);
1860 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1861 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1862 if (in->pcm != NULL) {
1863 pcm_close(in->pcm);
1864 in->pcm = NULL;
1865 }
1866 if (pcm_open_retry_count-- == 0) {
1867 ret = -EIO;
1868 goto error_open;
1869 }
1870 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1871 continue;
1872 }
1873 break;
1874 }
1875
1876 ALOGV("%s: pcm_prepare", __func__);
1877 ret = pcm_prepare(in->pcm);
1878 if (ret < 0) {
1879 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001880 pcm_close(in->pcm);
1881 in->pcm = NULL;
1882 goto error_open;
1883 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001884 if (in->realtime) {
1885 ret = pcm_start(in->pcm);
1886 if (ret < 0) {
1887 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1888 pcm_close(in->pcm);
1889 in->pcm = NULL;
1890 goto error_open;
1891 }
1892 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001893 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001894 register_in_stream(in);
Vignesh Kulothungan64698822018-01-23 11:25:18 -08001895 check_and_enable_effect(adev);
Wei Wangf4837d52017-11-21 14:51:20 -08001896 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001897 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001898 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001899
Eric Laurent0e46adf2016-12-16 12:49:24 -08001900 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001901
1902error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001903 stop_input_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001904 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001905 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001906
1907error_config:
Eric Laurent2bafff12016-03-17 12:17:23 -07001908 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001909 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001910}
1911
Eric Laurenta1478072015-09-21 17:21:52 -07001912void lock_input_stream(struct stream_in *in)
1913{
1914 pthread_mutex_lock(&in->pre_lock);
1915 pthread_mutex_lock(&in->lock);
1916 pthread_mutex_unlock(&in->pre_lock);
1917}
1918
1919void lock_output_stream(struct stream_out *out)
1920{
1921 pthread_mutex_lock(&out->pre_lock);
1922 pthread_mutex_lock(&out->lock);
1923 pthread_mutex_unlock(&out->pre_lock);
1924}
1925
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001926/* must be called with out->lock locked */
1927static int send_offload_cmd_l(struct stream_out* out, int command)
1928{
1929 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1930
1931 ALOGVV("%s %d", __func__, command);
1932
1933 cmd->cmd = command;
1934 list_add_tail(&out->offload_cmd_list, &cmd->node);
1935 pthread_cond_signal(&out->offload_cond);
1936 return 0;
1937}
1938
1939/* must be called iwth out->lock locked */
1940static void stop_compressed_output_l(struct stream_out *out)
1941{
1942 out->offload_state = OFFLOAD_STATE_IDLE;
1943 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001944 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001945 if (out->compr != NULL) {
1946 compress_stop(out->compr);
1947 while (out->offload_thread_blocked) {
1948 pthread_cond_wait(&out->cond, &out->lock);
1949 }
1950 }
1951}
1952
1953static void *offload_thread_loop(void *context)
1954{
1955 struct stream_out *out = (struct stream_out *) context;
1956 struct listnode *item;
1957
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001958 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1959 set_sched_policy(0, SP_FOREGROUND);
1960 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1961
1962 ALOGV("%s", __func__);
juyuchenb0f5bfd2018-12-12 17:58:09 +08001963
Eric Laurenta1478072015-09-21 17:21:52 -07001964 lock_output_stream(out);
juyuchenb0f5bfd2018-12-12 17:58:09 +08001965 out->offload_state = OFFLOAD_STATE_IDLE;
1966 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001967 for (;;) {
1968 struct offload_cmd *cmd = NULL;
1969 stream_callback_event_t event;
1970 bool send_callback = false;
1971
1972 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1973 __func__, list_empty(&out->offload_cmd_list),
1974 out->offload_state);
1975 if (list_empty(&out->offload_cmd_list)) {
1976 ALOGV("%s SLEEPING", __func__);
1977 pthread_cond_wait(&out->offload_cond, &out->lock);
1978 ALOGV("%s RUNNING", __func__);
1979 continue;
1980 }
1981
1982 item = list_head(&out->offload_cmd_list);
1983 cmd = node_to_item(item, struct offload_cmd, node);
1984 list_remove(item);
1985
1986 ALOGVV("%s STATE %d CMD %d out->compr %p",
1987 __func__, out->offload_state, cmd->cmd, out->compr);
1988
1989 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1990 free(cmd);
1991 break;
1992 }
1993
1994 if (out->compr == NULL) {
1995 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001996 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001997 pthread_cond_signal(&out->cond);
1998 continue;
1999 }
2000 out->offload_thread_blocked = true;
2001 pthread_mutex_unlock(&out->lock);
2002 send_callback = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002003 switch (cmd->cmd) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002004 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
2005 compress_wait(out->compr, -1);
2006 send_callback = true;
2007 event = STREAM_CBK_EVENT_WRITE_READY;
2008 break;
2009 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002010 compress_next_track(out->compr);
2011 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002012 send_callback = true;
2013 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08002014 /* Resend the metadata for next iteration */
2015 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002016 break;
2017 case OFFLOAD_CMD_DRAIN:
2018 compress_drain(out->compr);
2019 send_callback = true;
2020 event = STREAM_CBK_EVENT_DRAIN_READY;
2021 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002022 case OFFLOAD_CMD_ERROR:
2023 send_callback = true;
2024 event = STREAM_CBK_EVENT_ERROR;
2025 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002026 default:
2027 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2028 break;
2029 }
Eric Laurenta1478072015-09-21 17:21:52 -07002030 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002031 out->offload_thread_blocked = false;
2032 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07002033 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08002034 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002035 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002036 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002037 free(cmd);
2038 }
2039
2040 pthread_cond_signal(&out->cond);
2041 while (!list_empty(&out->offload_cmd_list)) {
2042 item = list_head(&out->offload_cmd_list);
2043 list_remove(item);
2044 free(node_to_item(item, struct offload_cmd, node));
2045 }
2046 pthread_mutex_unlock(&out->lock);
2047
2048 return NULL;
2049}
2050
2051static int create_offload_callback_thread(struct stream_out *out)
2052{
2053 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2054 list_init(&out->offload_cmd_list);
2055 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2056 offload_thread_loop, out);
2057 return 0;
2058}
2059
2060static int destroy_offload_callback_thread(struct stream_out *out)
2061{
Eric Laurenta1478072015-09-21 17:21:52 -07002062 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002063 stop_compressed_output_l(out);
2064 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2065
2066 pthread_mutex_unlock(&out->lock);
2067 pthread_join(out->offload_thread, (void **) NULL);
2068 pthread_cond_destroy(&out->offload_cond);
2069
2070 return 0;
2071}
2072
Eric Laurent07eeafd2013-10-06 12:52:49 -07002073static bool allow_hdmi_channel_config(struct audio_device *adev)
2074{
2075 struct listnode *node;
2076 struct audio_usecase *usecase;
2077 bool ret = true;
2078
2079 list_for_each(node, &adev->usecase_list) {
2080 usecase = node_to_item(node, struct audio_usecase, list);
2081 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2082 /*
2083 * If voice call is already existing, do not proceed further to avoid
2084 * disabling/enabling both RX and TX devices, CSD calls, etc.
2085 * Once the voice call done, the HDMI channels can be configured to
2086 * max channels of remaining use cases.
2087 */
2088 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08002089 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07002090 __func__);
2091 ret = false;
2092 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002093 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
2094 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07002095 "no change in HDMI channels", __func__);
2096 ret = false;
2097 break;
2098 }
2099 }
2100 }
2101 return ret;
2102}
2103
2104static int check_and_set_hdmi_channels(struct audio_device *adev,
2105 unsigned int channels)
2106{
2107 struct listnode *node;
2108 struct audio_usecase *usecase;
2109
2110 /* Check if change in HDMI channel config is allowed */
2111 if (!allow_hdmi_channel_config(adev))
2112 return 0;
2113
2114 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08002115 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002116 return 0;
2117 }
2118
2119 platform_set_hdmi_channels(adev->platform, channels);
2120 adev->cur_hdmi_channels = channels;
2121
2122 /*
2123 * Deroute all the playback streams routed to HDMI so that
2124 * the back end is deactivated. Note that backend will not
2125 * be deactivated if any one stream is connected to it.
2126 */
2127 list_for_each(node, &adev->usecase_list) {
2128 usecase = node_to_item(node, struct audio_usecase, list);
2129 if (usecase->type == PCM_PLAYBACK &&
2130 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002131 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002132 }
2133 }
2134
2135 /*
2136 * Enable all the streams disabled above. Now the HDMI backend
2137 * will be activated with new channel configuration
2138 */
2139 list_for_each(node, &adev->usecase_list) {
2140 usecase = node_to_item(node, struct audio_usecase, list);
2141 if (usecase->type == PCM_PLAYBACK &&
2142 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002143 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002144 }
2145 }
2146
2147 return 0;
2148}
2149
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002150static int check_and_set_usb_service_interval(struct audio_device *adev,
2151 struct audio_usecase *uc_info,
2152 bool min)
2153{
2154 struct listnode *node;
2155 struct audio_usecase *usecase;
2156 bool switch_usecases = false;
2157 bool reconfig = false;
2158
2159 if ((uc_info->id != USECASE_AUDIO_PLAYBACK_MMAP) &&
2160 (uc_info->id != USECASE_AUDIO_PLAYBACK_ULL))
2161 return -1;
2162
2163 /* set if the valid usecase do not already exist */
2164 list_for_each(node, &adev->usecase_list) {
2165 usecase = node_to_item(node, struct audio_usecase, list);
2166 if (usecase->type == PCM_PLAYBACK &&
2167 (audio_is_usb_out_device(usecase->devices & AUDIO_DEVICE_OUT_ALL_USB))) {
2168 switch (usecase->id) {
2169 case USECASE_AUDIO_PLAYBACK_MMAP:
2170 case USECASE_AUDIO_PLAYBACK_ULL:
2171 // cannot reconfig while mmap/ull is present.
2172 return -1;
2173 default:
2174 switch_usecases = true;
2175 break;
2176 }
2177 }
2178 if (switch_usecases)
2179 break;
2180 }
2181 /*
2182 * client can try to set service interval in start_output_stream
2183 * to min or to 0 (i.e reset) in stop_output_stream .
2184 */
2185 unsigned long service_interval =
2186 audio_extn_usb_find_service_interval(min, true /*playback*/);
2187 int ret = platform_set_usb_service_interval(adev->platform,
2188 true /*playback*/,
2189 service_interval,
2190 &reconfig);
2191 /* no change or not supported or no active usecases */
2192 if (ret || !reconfig || !switch_usecases)
2193 return -1;
2194 return 0;
2195#undef VALID_USECASE
2196}
2197
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002198static int stop_output_stream(struct stream_out *out)
2199{
2200 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002201 struct audio_usecase *uc_info;
2202 struct audio_device *adev = out->dev;
HW Lee88512e92018-06-12 15:26:09 +08002203 bool has_voip_usecase =
2204 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002205
Eric Laurent994a6932013-07-17 11:51:42 -07002206 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002207 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002208 uc_info = get_usecase_from_list(adev, out->usecase);
2209 if (uc_info == NULL) {
2210 ALOGE("%s: Could not find the usecase (%d) in the list",
2211 __func__, out->usecase);
2212 return -EINVAL;
2213 }
2214
Haynes Mathew George41f86652014-06-17 14:22:15 -07002215 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2216 if (adev->visualizer_stop_output != NULL)
2217 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
2218 if (adev->offload_effects_stop_output != NULL)
2219 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002220 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2221 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2222 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07002223 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002224
Arun Mirpuri0cc2f312018-05-29 17:26:07 -07002225 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
2226 voice_set_device_mute_flag(adev, false);
2227
Eric Laurent150dbfe2013-02-27 14:31:02 -08002228 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002229 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002230
2231 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002232 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002233
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002234 list_remove(&uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002235
Eric Laurent0499d4f2014-08-25 22:39:29 -05002236 audio_extn_extspk_update(adev->extspk);
2237
Eric Laurent07eeafd2013-10-06 12:52:49 -07002238 /* Must be called after removing the usecase from list */
2239 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2240 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
HW Lee88512e92018-06-12 15:26:09 +08002241 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002242 ret = check_and_set_usb_service_interval(adev, uc_info, false /*min*/);
2243 if (ret == 0) {
2244 /* default service interval was successfully updated,
2245 reopen USB backend with new service interval */
2246 check_and_route_playback_usecases(adev, uc_info, uc_info->out_snd_device);
2247 }
2248 ret = 0;
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07002249 }
juyuchend194b432018-11-16 14:15:16 +08002250 /* 1) media + voip output routing to handset must route media back to
2251 speaker when voip stops.
2252 2) trigger voip input to reroute when voip output changes to
2253 hearing aid. */
HW Lee88512e92018-06-12 15:26:09 +08002254 if (has_voip_usecase ||
2255 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
2256 struct listnode *node;
2257 struct audio_usecase *usecase;
2258 list_for_each(node, &adev->usecase_list) {
2259 usecase = node_to_item(node, struct audio_usecase, list);
juyuchend194b432018-11-16 14:15:16 +08002260 if ((usecase->type == PCM_CAPTURE &&
2261 usecase->id != USECASE_AUDIO_RECORD_VOIP)
2262 || usecase == uc_info)
HW Lee88512e92018-06-12 15:26:09 +08002263 continue;
2264
2265 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
2266 __func__, usecase->id, use_case_table[usecase->id],
2267 out->usecase, use_case_table[out->usecase]);
2268 select_devices(adev, usecase->id);
2269 }
2270 }
2271
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002272 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07002273 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002274 return ret;
2275}
2276
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002277struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
2278 unsigned int flags, unsigned int pcm_open_retry_count,
2279 struct pcm_config *config)
2280{
2281 struct pcm* pcm = NULL;
2282
2283 while (1) {
2284 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
2285 if (pcm == NULL || !pcm_is_ready(pcm)) {
2286 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
2287 if (pcm != NULL) {
2288 pcm_close(pcm);
2289 pcm = NULL;
2290 }
2291 if (pcm_open_retry_count-- == 0)
2292 return NULL;
2293
2294 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2295 continue;
2296 }
2297 break;
2298 }
2299
2300 if (pcm_is_ready(pcm)) {
2301 int ret = pcm_prepare(pcm);
2302 if (ret < 0) {
2303 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2304 pcm_close(pcm);
2305 pcm = NULL;
2306 }
2307 }
2308
2309 return pcm;
2310}
2311
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002312int start_output_stream(struct stream_out *out)
2313{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002314 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002315 struct audio_usecase *uc_info;
2316 struct audio_device *adev = out->dev;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002317 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002318
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002319 ALOGV("%s: enter: usecase(%d: %s) %s devices(%#x)",
2320 __func__, out->usecase, use_case_table[out->usecase],
2321 out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS ? "(with haptics)" : "",
2322 out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002323
2324 if (out->card_status == CARD_STATUS_OFFLINE ||
2325 adev->card_status == CARD_STATUS_OFFLINE) {
2326 ALOGW("out->card_status or adev->card_status offline, try again");
2327 ret = -EAGAIN;
2328 goto error_config;
2329 }
2330
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002331 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2332 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002333 if (out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002334 a2dp_combo = true;
2335 } else {
2336 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2337 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2338 ret = -EAGAIN;
2339 goto error_config;
2340 }
2341 }
2342 }
2343 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002344 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002345 if (out->pcm_device_id < 0) {
2346 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2347 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002348 ret = -EINVAL;
2349 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002350 }
2351
2352 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
2353 uc_info->id = out->usecase;
2354 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002355 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002356 uc_info->devices = out->devices;
2357 uc_info->in_snd_device = SND_DEVICE_NONE;
2358 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002359
Eric Laurent07eeafd2013-10-06 12:52:49 -07002360 /* This must be called before adding this usecase to the list */
2361 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2362 check_and_set_hdmi_channels(adev, out->config.channels);
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002363 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
2364 check_and_set_usb_service_interval(adev, uc_info, true /*min*/);
2365 /* USB backend is not reopened immediately.
2366 This is eventually done as part of select_devices */
2367 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002368
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002369 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002370
Wei Wangf4837d52017-11-21 14:51:20 -08002371 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002372 audio_extn_perf_lock_acquire();
2373
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002374 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2375 (!audio_extn_a2dp_is_ready())) {
2376 if (!a2dp_combo) {
2377 check_a2dp_restore_l(adev, out, false);
2378 } else {
2379 audio_devices_t dev = out->devices;
juyuchen9baad392018-06-05 19:02:10 +08002380 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2381 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2382 else
2383 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002384 select_devices(adev, out->usecase);
2385 out->devices = dev;
2386 }
2387 } else {
2388 select_devices(adev, out->usecase);
2389 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002390
Eric Laurent0499d4f2014-08-25 22:39:29 -05002391 audio_extn_extspk_update(adev->extspk);
2392
Arun Mirpuri0cc2f312018-05-29 17:26:07 -07002393 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
2394 voice_set_device_mute_flag(adev, true);
2395
Andy Hung31aca912014-03-20 17:14:59 -07002396 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002397 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002398 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2399 out->pcm = NULL;
2400 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
2401 COMPRESS_IN, &out->compr_config);
2402 if (out->compr && !is_compress_ready(out->compr)) {
2403 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2404 compress_close(out->compr);
2405 out->compr = NULL;
2406 ret = -EIO;
2407 goto error_open;
2408 }
2409 if (out->offload_callback)
2410 compress_nonblock(out->compr, out->non_blocking);
2411
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07002412 if (adev->visualizer_start_output != NULL) {
2413 int capture_device_id =
2414 platform_get_pcm_device_id(USECASE_AUDIO_RECORD_AFE_PROXY,
2415 PCM_CAPTURE);
2416 adev->visualizer_start_output(out->handle, out->pcm_device_id,
2417 adev->snd_card, capture_device_id);
2418 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002419 if (adev->offload_effects_start_output != NULL)
2420 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
2421 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002422 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002423 ALOGE("%s: pcm stream not ready", __func__);
2424 goto error_open;
2425 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002426 ret = pcm_start(out->pcm);
2427 if (ret < 0) {
2428 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2429 goto error_open;
2430 }
2431 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07002432 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002433 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002434
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002435 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2436 flags |= PCM_MMAP | PCM_NOIRQ;
2437 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002438 } else if (out->realtime) {
2439 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07002440 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002441
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002442 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
2443 flags, pcm_open_retry_count,
2444 &(out->config));
2445 if (out->pcm == NULL) {
2446 ret = -EIO;
2447 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002448 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002449
2450 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
2451 if (adev->haptic_pcm != NULL) {
2452 pcm_close(adev->haptic_pcm);
2453 adev->haptic_pcm = NULL;
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002454 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002455 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
2456 adev->haptic_pcm_device_id,
2457 flags, pcm_open_retry_count,
2458 &(adev->haptics_config));
2459 // failure to open haptics pcm shouldnt stop audio,
2460 // so do not close audio pcm in case of error
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002461 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002462
Eric Laurent0e46adf2016-12-16 12:49:24 -08002463 if (out->realtime) {
2464 ret = pcm_start(out->pcm);
2465 if (ret < 0) {
2466 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
2467 pcm_close(out->pcm);
2468 out->pcm = NULL;
2469 goto error_open;
2470 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002471 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002472 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002473
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002474 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08002475 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002476 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002477 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07002478
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002479 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2480 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2481 audio_low_latency_hint_start();
2482 }
2483
vivek mehtae59cfb22017-06-16 15:57:11 -07002484 // consider a scenario where on pause lower layers are tear down.
2485 // so on resume, swap mixer control need to be sent only when
2486 // backend is active, hence rather than sending from enable device
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002487 // sending it from start of stream
vivek mehtae59cfb22017-06-16 15:57:11 -07002488
2489 platform_set_swap_channels(adev, true);
2490
Eric Laurent994a6932013-07-17 11:51:42 -07002491 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002492 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002493error_open:
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002494 if (adev->haptic_pcm) {
2495 pcm_close(adev->haptic_pcm);
2496 adev->haptic_pcm = NULL;
2497 }
Wei Wangf4837d52017-11-21 14:51:20 -08002498 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002499 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002500 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002501error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002502 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002503}
2504
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002505static int check_input_parameters(uint32_t sample_rate,
2506 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07002507 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002508{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002509 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2510 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002511 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2512 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002513 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2514 return -EINVAL;
2515 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002516
Eric Laurent74b55762017-07-09 17:04:53 -07002517 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2518 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002519 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002520 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002521 return -EINVAL;
2522 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002523
2524 switch (sample_rate) {
2525 case 8000:
2526 case 11025:
2527 case 12000:
2528 case 16000:
2529 case 22050:
2530 case 24000:
2531 case 32000:
2532 case 44100:
2533 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002534 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002535 break;
2536 default:
vivek mehtadae44712015-07-27 14:13:18 -07002537 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002538 return -EINVAL;
2539 }
2540
2541 return 0;
2542}
2543
Kevin Rocarda325aa22018-04-03 09:15:52 -07002544/** Add a value in a list if not already present.
2545 * @return true if value was successfully inserted or already present,
2546 * false if the list is full and does not contain the value.
2547 */
2548static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
2549 for (size_t i = 0; i < list_length; i++) {
2550 if (list[i] == value) return true; // value is already present
2551 if (list[i] == 0) { // no values in this slot
2552 list[i] = value;
2553 return true; // value inserted
2554 }
2555 }
2556 return false; // could not insert value
2557}
2558
2559/** Add channel_mask in supported_channel_masks if not already present.
2560 * @return true if channel_mask was successfully inserted or already present,
2561 * false if supported_channel_masks is full and does not contain channel_mask.
2562 */
2563static void register_channel_mask(audio_channel_mask_t channel_mask,
2564 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
2565 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
2566 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
2567}
2568
2569/** Add format in supported_formats if not already present.
2570 * @return true if format was successfully inserted or already present,
2571 * false if supported_formats is full and does not contain format.
2572 */
2573static void register_format(audio_format_t format,
2574 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
2575 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
2576 "%s: stream can not declare supporting its format %x", __func__, format);
2577}
2578/** Add sample_rate in supported_sample_rates if not already present.
2579 * @return true if sample_rate was successfully inserted or already present,
2580 * false if supported_sample_rates is full and does not contain sample_rate.
2581 */
2582static void register_sample_rate(uint32_t sample_rate,
2583 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
2584 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
2585 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
2586}
2587
vivek mehtaa68fea62017-06-08 19:04:02 -07002588static size_t get_stream_buffer_size(size_t duration_ms,
2589 uint32_t sample_rate,
2590 audio_format_t format,
2591 int channel_count,
2592 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002593{
2594 size_t size = 0;
2595
vivek mehtaa68fea62017-06-08 19:04:02 -07002596 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002597 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002598 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002599
2600 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002601
Glenn Kasten4f993392014-05-14 07:30:48 -07002602 /* make sure the size is multiple of 32 bytes
2603 * At 48 kHz mono 16-bit PCM:
2604 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2605 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2606 */
2607 size += 0x1f;
2608 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002609
2610 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002611}
2612
2613static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2614{
2615 struct stream_out *out = (struct stream_out *)stream;
2616
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002617 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002618}
2619
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002620static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002621{
2622 return -ENOSYS;
2623}
2624
2625static size_t out_get_buffer_size(const struct audio_stream *stream)
2626{
2627 struct stream_out *out = (struct stream_out *)stream;
2628
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002629 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2630 return out->compr_config.fragment_size;
2631 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002632 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002633 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002634}
2635
2636static uint32_t out_get_channels(const struct audio_stream *stream)
2637{
2638 struct stream_out *out = (struct stream_out *)stream;
2639
2640 return out->channel_mask;
2641}
2642
2643static audio_format_t out_get_format(const struct audio_stream *stream)
2644{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002645 struct stream_out *out = (struct stream_out *)stream;
2646
2647 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002648}
2649
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002650static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002651{
2652 return -ENOSYS;
2653}
2654
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002655/* must be called with out->lock locked */
2656static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002657{
2658 struct stream_out *out = (struct stream_out *)stream;
2659 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002660 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002661
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002662 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002663 if (adev->adm_deregister_stream)
2664 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002665 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002666 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002667 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2668 if (out->pcm) {
2669 pcm_close(out->pcm);
2670 out->pcm = NULL;
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002671
2672 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
2673 if (adev->haptic_pcm) {
2674 pcm_close(adev->haptic_pcm);
2675 adev->haptic_pcm = NULL;
2676 }
2677
2678 if (adev->haptic_buffer != NULL) {
2679 free(adev->haptic_buffer);
2680 adev->haptic_buffer = NULL;
2681 adev->haptic_buffer_size = 0;
2682 }
2683 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002684 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002685 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002686 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002687 out->playback_started = false;
2688 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002689 } else {
2690 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002691 out->gapless_mdata.encoder_delay = 0;
2692 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002693 if (out->compr != NULL) {
2694 compress_close(out->compr);
2695 out->compr = NULL;
2696 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002697 }
Phil Burkbc991042017-02-24 08:06:44 -08002698 if (do_stop) {
2699 stop_output_stream(out);
2700 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002701 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002702 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002703 return 0;
2704}
2705
2706static int out_standby(struct audio_stream *stream)
2707{
2708 struct stream_out *out = (struct stream_out *)stream;
2709
2710 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2711 out->usecase, use_case_table[out->usecase]);
2712
2713 lock_output_stream(out);
2714 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002715 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002716 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002717 return 0;
2718}
2719
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002720static int out_on_error(struct audio_stream *stream)
2721{
2722 struct stream_out *out = (struct stream_out *)stream;
2723 struct audio_device *adev = out->dev;
2724 bool do_standby = false;
2725
2726 lock_output_stream(out);
2727 if (!out->standby) {
2728 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2729 stop_compressed_output_l(out);
2730 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2731 } else
2732 do_standby = true;
2733 }
2734 pthread_mutex_unlock(&out->lock);
2735
2736 if (do_standby)
2737 return out_standby(&out->stream.common);
2738
2739 return 0;
2740}
2741
Andy Hung7401c7c2016-09-21 12:41:21 -07002742static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002743{
Andy Hung7401c7c2016-09-21 12:41:21 -07002744 struct stream_out *out = (struct stream_out *)stream;
2745
2746 // We try to get the lock for consistency,
2747 // but it isn't necessary for these variables.
2748 // If we're not in standby, we may be blocked on a write.
2749 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2750 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2751 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2752
Andy Hung572633e2019-02-19 11:58:24 -08002753 char buffer[256]; // for statistics formatting
2754 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
2755 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
2756
Andy Hung241e36f2019-02-19 12:00:38 -08002757 if (out->start_latency_ms.n > 0) {
2758 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
2759 dprintf(fd, " Start latency ms: %s\n", buffer);
2760 }
2761
Andy Hung7401c7c2016-09-21 12:41:21 -07002762 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002763 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002764 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002765
2766 // dump error info
2767 (void)error_log_dump(
2768 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002769
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002770 return 0;
2771}
2772
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002773static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2774{
2775 int ret = 0;
2776 char value[32];
2777 struct compr_gapless_mdata tmp_mdata;
2778
2779 if (!out || !parms) {
2780 return -EINVAL;
2781 }
2782
2783 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2784 if (ret >= 0) {
2785 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2786 } else {
2787 return -EINVAL;
2788 }
2789
2790 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2791 if (ret >= 0) {
2792 tmp_mdata.encoder_padding = atoi(value);
2793 } else {
2794 return -EINVAL;
2795 }
2796
2797 out->gapless_mdata = tmp_mdata;
2798 out->send_new_metadata = 1;
2799 ALOGV("%s new encoder delay %u and padding %u", __func__,
2800 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2801
2802 return 0;
2803}
2804
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002805static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2806{
2807 return out == adev->primary_output || out == adev->voice_tx_output;
2808}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002809
Kevin Rocard1e02c882017-08-09 15:26:07 -07002810static int get_alive_usb_card(struct str_parms* parms) {
2811 int card;
2812 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2813 !audio_extn_usb_alive(card)) {
2814 return card;
2815 }
2816 return -ENODEV;
2817}
2818
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002819static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2820{
2821 struct stream_out *out = (struct stream_out *)stream;
2822 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002823 struct audio_usecase *usecase;
2824 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002825 struct str_parms *parms;
2826 char value[32];
2827 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002828 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002829 int status = 0;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002830 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002831
Eric Laurent2e140aa2016-06-30 17:14:46 -07002832 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002833 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002834 parms = str_parms_create_str(kvpairs);
2835 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2836 if (ret >= 0) {
2837 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002838
Eric Laurenta1478072015-09-21 17:21:52 -07002839 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002840
2841 // The usb driver needs to be closed after usb device disconnection
2842 // otherwise audio is no longer played on the new usb devices.
2843 // By forcing the stream in standby, the usb stack refcount drops to 0
2844 // and the driver is closed.
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002845 if (val == AUDIO_DEVICE_NONE &&
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002846 audio_is_usb_out_device(out->devices)) {
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002847 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2848 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2849 out_standby_l(&out->stream.common);
2850 }
2851 val = AUDIO_DEVICE_OUT_SPEAKER;
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002852 }
2853
Eric Laurent150dbfe2013-02-27 14:31:02 -08002854 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002855
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002856 /*
2857 * When HDMI cable is unplugged the music playback is paused and
2858 * the policy manager sends routing=0. But the audioflinger
2859 * continues to write data until standby time (3sec).
2860 * As the HDMI core is turned off, the write gets blocked.
2861 * Avoid this by routing audio to speaker until standby.
2862 */
2863 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2864 val == AUDIO_DEVICE_NONE) {
2865 val = AUDIO_DEVICE_OUT_SPEAKER;
2866 }
2867
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002868 /*
2869 * When A2DP is disconnected the
2870 * music playback is paused and the policy manager sends routing=0
2871 * But the audioflingercontinues to write data until standby time
2872 * (3sec). As BT is turned off, the write gets blocked.
2873 * Avoid this by routing audio to speaker until standby.
2874 */
2875 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2876 (val == AUDIO_DEVICE_NONE) &&
2877 !audio_extn_a2dp_is_ready()) {
2878 val = AUDIO_DEVICE_OUT_SPEAKER;
2879 }
2880
2881 /* To avoid a2dp to sco overlapping / BT device improper state
2882 * check with BT lib about a2dp streaming support before routing
2883 */
2884 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2885 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002886 if (val & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002887 //combo usecase just by pass a2dp
2888 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2889 bypass_a2dp = true;
2890 } else {
2891 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2892 /* update device to a2dp and don't route as BT returned error
2893 * However it is still possible a2dp routing called because
2894 * of current active device disconnection (like wired headset)
2895 */
2896 out->devices = val;
2897 pthread_mutex_unlock(&out->lock);
2898 pthread_mutex_unlock(&adev->lock);
2899 status = -ENOSYS;
2900 goto routing_fail;
2901 }
2902 }
2903 }
2904
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002905 audio_devices_t new_dev = val;
2906
2907 // Workaround: If routing to an non existing usb device, fail gracefully
2908 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002909 int card;
2910 if (audio_is_usb_out_device(new_dev) &&
2911 (card = get_alive_usb_card(parms)) >= 0) {
2912
2913 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002914 pthread_mutex_unlock(&adev->lock);
2915 pthread_mutex_unlock(&out->lock);
2916 status = -ENOSYS;
2917 goto routing_fail;
2918 }
2919
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002920 /*
2921 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002922 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002923 * the select_devices(). But how do we undo this?
2924 *
2925 * For example, music playback is active on headset (deep-buffer usecase)
2926 * and if we go to ringtones and select a ringtone, low-latency usecase
2927 * will be started on headset+speaker. As we can't enable headset+speaker
2928 * and headset devices at the same time, select_devices() switches the music
2929 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2930 * So when the ringtone playback is completed, how do we undo the same?
2931 *
2932 * We are relying on the out_set_parameters() call on deep-buffer output,
2933 * once the ringtone playback is ended.
2934 * NOTE: We should not check if the current devices are same as new devices.
2935 * Because select_devices() must be called to switch back the music
2936 * playback to headset.
2937 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002938 if (new_dev != AUDIO_DEVICE_NONE) {
2939 bool same_dev = out->devices == new_dev;
2940 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002941
Eric Laurenta7657192014-10-09 21:09:33 -07002942 if (output_drives_call(adev, out)) {
Vignesh Kulothungana5c9da12017-11-10 11:41:24 -08002943 if (!voice_is_call_state_active(adev)) {
Eric Laurenta7657192014-10-09 21:09:33 -07002944 if (adev->mode == AUDIO_MODE_IN_CALL) {
2945 adev->current_call_output = out;
2946 ret = voice_start_call(adev);
2947 }
2948 } else {
2949 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002950 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002951 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002952 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002953
2954 if (!out->standby) {
2955 if (!same_dev) {
2956 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002957 // inform adm before actual routing to prevent glitches.
2958 if (adev->adm_on_routing_change) {
2959 adev->adm_on_routing_change(adev->adm_data,
2960 out->handle);
2961 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002962 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002963 if (!bypass_a2dp) {
2964 select_devices(adev, out->usecase);
2965 } else {
juyuchen9baad392018-06-05 19:02:10 +08002966 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2967 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2968 else
2969 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002970 select_devices(adev, out->usecase);
2971 out->devices = new_dev;
2972 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002973 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002974
2975 // on device switch force swap, lower functions will make sure
2976 // to check if swap is allowed or not.
2977
2978 if (!same_dev)
2979 platform_set_swap_channels(adev, true);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002980
2981 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2982 out->a2dp_compress_mute &&
2983 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
2984 pthread_mutex_lock(&out->compr_mute_lock);
2985 out->a2dp_compress_mute = false;
2986 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
2987 pthread_mutex_unlock(&out->compr_mute_lock);
2988 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002989 }
2990
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002991 }
2992
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002993 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002994 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002995
2996 /*handles device and call state changes*/
2997 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002998 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002999 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003000
3001 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3002 parse_compress_metadata(out, parms);
3003 }
3004
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003005 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003006 ALOGV("%s: exit: code(%d)", __func__, status);
3007 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003008}
3009
Haynes Mathew George569b7482017-05-08 14:44:27 -07003010static bool stream_get_parameter_channels(struct str_parms *query,
3011 struct str_parms *reply,
3012 audio_channel_mask_t *supported_channel_masks) {
3013 int ret = -1;
Andy Hung64fdb452018-09-07 11:25:33 -07003014 char value[ARRAY_SIZE(channels_name_to_enum_table) * 32 /* max channel name size */];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003015 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003016 size_t i, j;
3017
3018 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
3019 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003020 value[0] = '\0';
3021 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003022 while (supported_channel_masks[i] != 0) {
3023 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
3024 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003025 if (!first) {
3026 strcat(value, "|");
3027 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003028 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003029 first = false;
3030 break;
3031 }
3032 }
3033 i++;
3034 }
3035 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003036 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003037 return ret >= 0;
3038}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003039
Haynes Mathew George569b7482017-05-08 14:44:27 -07003040static bool stream_get_parameter_formats(struct str_parms *query,
3041 struct str_parms *reply,
3042 audio_format_t *supported_formats) {
3043 int ret = -1;
3044 char value[256];
3045 int i;
3046
3047 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
3048 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003049 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07003050 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003051 case AUDIO_FORMAT_PCM_16_BIT:
3052 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
3053 break;
3054 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
3055 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
3056 break;
3057 case AUDIO_FORMAT_PCM_32_BIT:
3058 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
3059 break;
3060 default:
3061 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07003062 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003063 break;
3064 }
3065 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003066 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003067 return ret >= 0;
3068}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003069
Haynes Mathew George569b7482017-05-08 14:44:27 -07003070static bool stream_get_parameter_rates(struct str_parms *query,
3071 struct str_parms *reply,
3072 uint32_t *supported_sample_rates) {
3073
3074 int i;
3075 char value[256];
3076 int ret = -1;
3077 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
3078 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003079 value[0] = '\0';
3080 i=0;
3081 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003082 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003083 int avail = sizeof(value) - cursor;
3084 ret = snprintf(value + cursor, avail, "%s%d",
3085 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07003086 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003087 if (ret < 0 || ret >= avail) {
3088 // if cursor is at the last element of the array
3089 // overwrite with \0 is duplicate work as
3090 // snprintf already put a \0 in place.
3091 // else
3092 // we had space to write the '|' at value[cursor]
3093 // (which will be overwritten) or no space to fill
3094 // the first element (=> cursor == 0)
3095 value[cursor] = '\0';
3096 break;
3097 }
3098 cursor += ret;
3099 ++i;
3100 }
3101 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
3102 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003103 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003104 return ret >= 0;
3105}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003106
Haynes Mathew George569b7482017-05-08 14:44:27 -07003107static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
3108{
3109 struct stream_out *out = (struct stream_out *)stream;
3110 struct str_parms *query = str_parms_create_str(keys);
3111 char *str;
3112 struct str_parms *reply = str_parms_create();
3113 bool replied = false;
3114 ALOGV("%s: enter: keys - %s", __func__, keys);
3115
3116 replied |= stream_get_parameter_channels(query, reply,
3117 &out->supported_channel_masks[0]);
3118 replied |= stream_get_parameter_formats(query, reply,
3119 &out->supported_formats[0]);
3120 replied |= stream_get_parameter_rates(query, reply,
3121 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003122 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003123 str = str_parms_to_str(reply);
3124 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07003125 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003126 }
3127 str_parms_destroy(query);
3128 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07003129 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003130 return str;
3131}
3132
3133static uint32_t out_get_latency(const struct audio_stream_out *stream)
3134{
Haynes Mathew George03c40102016-01-29 17:57:48 -08003135 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003136 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003137 uint32_t latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003138
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003139 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3140 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003141 else if ((out->realtime) ||
3142 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003143 // since the buffer won't be filled up faster than realtime,
3144 // return a smaller number
3145 period_ms = (out->af_period_multiplier * out->config.period_size *
3146 1000) / (out->config.rate);
3147 hw_delay = platform_render_latency(out->usecase)/1000;
3148 return period_ms + hw_delay;
3149 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003150
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003151 latency = (out->config.period_count * out->config.period_size * 1000) /
3152 (out->config.rate);
3153
3154 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
3155 latency += audio_extn_a2dp_get_encoder_latency();
3156
3157 return latency;
3158}
3159
3160static int set_compr_volume(struct audio_stream_out *stream, float left,
3161 float right)
3162{
3163 struct stream_out *out = (struct stream_out *)stream;
3164 int volume[2];
3165 char mixer_ctl_name[128];
3166 struct audio_device *adev = out->dev;
3167 struct mixer_ctl *ctl;
3168 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
3169 PCM_PLAYBACK);
3170
3171 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3172 "Compress Playback %d Volume", pcm_device_id);
3173 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3174 if (!ctl) {
3175 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3176 __func__, mixer_ctl_name);
3177 return -EINVAL;
3178 }
3179 ALOGV("%s: ctl for mixer cmd - %s, left %f, right %f",
3180 __func__, mixer_ctl_name, left, right);
3181 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3182 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3183 mixer_ctl_set_array(ctl, volume, sizeof(volume) / sizeof(volume[0]));
3184
3185 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003186}
3187
3188static int out_set_volume(struct audio_stream_out *stream, float left,
3189 float right)
3190{
Eric Laurenta9024de2013-04-04 09:19:12 -07003191 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003192 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003193
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003194 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07003195 /* only take left channel into account: the API is for stereo anyway */
3196 out->muted = (left == 0.0f);
3197 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003198 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003199 pthread_mutex_lock(&out->compr_mute_lock);
3200 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
3201 if (!out->a2dp_compress_mute)
3202 ret = set_compr_volume(stream, left, right);
3203 out->volume_l = left;
3204 out->volume_r = right;
3205 pthread_mutex_unlock(&out->compr_mute_lock);
3206 return ret;
vivek mehtaa68fea62017-06-08 19:04:02 -07003207 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07003208 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
3209 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
3210 if (!out->standby) {
3211 // if in standby, cached volume will be sent after stream is opened
3212 audio_extn_utils_send_app_type_gain(out->dev,
3213 out->app_type_cfg.app_type,
3214 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07003215 }
vivek mehtaa68fea62017-06-08 19:04:02 -07003216 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07003217 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003218
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003219 return -ENOSYS;
3220}
3221
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003222// note: this call is safe only if the stream_cb is
3223// removed first in close_output_stream (as is done now).
3224static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3225{
3226 if (!stream || !parms)
3227 return;
3228
3229 struct stream_out *out = (struct stream_out *)stream;
3230 struct audio_device *adev = out->dev;
3231
3232 card_status_t status;
3233 int card;
3234 if (parse_snd_card_status(parms, &card, &status) < 0)
3235 return;
3236
3237 pthread_mutex_lock(&adev->lock);
3238 bool valid_cb = (card == adev->snd_card);
3239 pthread_mutex_unlock(&adev->lock);
3240
3241 if (!valid_cb)
3242 return;
3243
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003244 lock_output_stream(out);
3245 if (out->card_status != status)
3246 out->card_status = status;
3247 pthread_mutex_unlock(&out->lock);
3248
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07003249 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
3250 use_case_table[out->usecase],
3251 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3252
3253 if (status == CARD_STATUS_OFFLINE)
3254 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003255
3256 return;
3257}
3258
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003259#ifdef NO_AUDIO_OUT
3260static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05003261 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003262{
3263 struct stream_out *out = (struct stream_out *)stream;
3264
3265 /* No Output device supported other than BT for playback.
3266 * Sleep for the amount of buffer duration
3267 */
Eric Laurenta1478072015-09-21 17:21:52 -07003268 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05003269 usleep(bytes * 1000000 / audio_stream_out_frame_size(
3270 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003271 out_get_sample_rate(&out->stream.common));
3272 pthread_mutex_unlock(&out->lock);
3273 return bytes;
3274}
3275#endif
3276
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003277static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3278 size_t bytes)
3279{
3280 struct stream_out *out = (struct stream_out *)stream;
3281 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07003282 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07003283 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003284
Eric Laurenta1478072015-09-21 17:21:52 -07003285 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07003286 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07003287 const size_t frame_size = audio_stream_out_frame_size(stream);
3288 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07003289
Eric Laurent0e46adf2016-12-16 12:49:24 -08003290 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3291 error_code = ERROR_CODE_WRITE;
3292 goto exit;
3293 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003294
3295 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3296 (audio_extn_a2dp_is_suspended())) {
juyuchen9baad392018-06-05 19:02:10 +08003297 if (!(out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003298 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3299 ret = -EIO;
3300 goto exit;
3301 }
3302 }
3303 }
3304
Andy Hung572633e2019-02-19 11:58:24 -08003305 const bool was_in_standby = out->standby;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003306 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003307 out->standby = false;
Andy Hung241e36f2019-02-19 12:00:38 -08003308 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
3309
Eric Laurent150dbfe2013-02-27 14:31:02 -08003310 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003311 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07003312
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003313 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003314 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003315 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07003316 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003317 goto exit;
3318 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07003319
vivek mehta40125092017-08-21 18:48:51 -07003320 // after standby always force set last known cal step
3321 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
3322 ALOGD("%s: retry previous failed cal level set", __func__);
3323 send_gain_dep_calibration_l();
3324 pthread_mutex_unlock(&adev->lock);
Andy Hung572633e2019-02-19 11:58:24 -08003325
Andy Hung241e36f2019-02-19 12:00:38 -08003326 // log startup time in ms.
3327 simple_stats_log(
3328 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Andy Hung572633e2019-02-19 11:58:24 -08003329 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003330 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003331
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003332 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003333 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003334 if (out->send_new_metadata) {
3335 ALOGVV("send new gapless metadata");
3336 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3337 out->send_new_metadata = 0;
3338 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003339 unsigned int avail;
3340 struct timespec tstamp;
3341 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
3342 /* Do not limit write size if the available frames count is unknown */
3343 if (ret != 0) {
3344 avail = bytes;
3345 }
3346 if (avail == 0) {
3347 ret = 0;
3348 } else {
Andy Hung572633e2019-02-19 11:58:24 -08003349 // check for compressed format underrun, essentially an empty buffer check
3350 // for a lack of better measurement.
3351 if (!was_in_standby && avail == out->kernel_buffer_size) {
3352 ALOGW("%s: compressed buffer empty (underrun)", __func__);
3353 simple_stats_log(&out->fifo_underruns, 1.); // Note: log one frame for compressed.
3354 }
3355
Eric Laurentb49b3f62016-02-29 17:59:49 -08003356 if (avail > bytes) {
3357 avail = bytes;
3358 }
3359 ret = compress_write(out->compr, buffer, avail);
3360 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
3361 __func__, avail, ret);
3362 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003363
Eric Laurent6e895242013-09-05 16:10:57 -07003364 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003365 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
3366 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003367 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003368 compress_start(out->compr);
3369 out->playback_started = 1;
3370 out->offload_state = OFFLOAD_STATE_PLAYING;
3371 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003372 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07003373 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07003374 } else {
3375 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07003376 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003377 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07003378 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003379 return ret;
3380 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07003381 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003382 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003383 size_t bytes_to_write = bytes;
3384
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003385 if (out->muted)
3386 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07003387 // FIXME: this can be removed once audio flinger mixer supports mono output
Nadav Bar3d72cfc2018-01-07 12:19:24 +02003388 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP || out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003389 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3390 int16_t *src = (int16_t *)buffer;
3391 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003392
Eric Laurentad2dde92017-09-20 18:27:31 -07003393 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
3394 out->format != AUDIO_FORMAT_PCM_16_BIT,
3395 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003396
Eric Laurentad2dde92017-09-20 18:27:31 -07003397 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
3398 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
3399 }
3400 bytes_to_write /= 2;
3401 }
Andy Hung572633e2019-02-19 11:58:24 -08003402
3403 // Note: since out_get_presentation_position() is called alternating with out_write()
3404 // by AudioFlinger, we can check underruns using the prior timestamp read.
3405 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
3406 if (out->last_fifo_valid) {
3407 // compute drain to see if there is an underrun.
3408 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
3409 const int64_t frames_by_time =
3410 (current_ns - out->last_fifo_time_ns) * out->config.rate / NANOS_PER_SECOND;
3411 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
3412
3413 if (underrun > 0) {
3414 simple_stats_log(&out->fifo_underruns, underrun);
3415
3416 ALOGW("%s: underrun(%lld) "
3417 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
3418 __func__,
3419 (long long)out->fifo_underruns.n,
3420 (long long)frames_by_time,
3421 (long long)out->last_fifo_frames_remaining);
3422 }
3423 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
3424 }
Eric Laurentad2dde92017-09-20 18:27:31 -07003425
Glenn Kasten5a59dff2018-02-22 08:05:35 -08003426 long ns = (frames * (int64_t) NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003427 request_out_focus(out, ns);
3428
3429 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08003430 if (use_mmap) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003431 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08003432 } else {
3433 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
3434 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3435 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
3436 size_t frame_size = channel_count * bytes_per_sample;
3437 size_t frame_count = bytes_to_write / frame_size;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003438
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08003439 bool force_haptic_path =
3440 property_get_bool("vendor.audio.test_haptic", false);
3441
3442 // extract Haptics data from Audio buffer
3443 bool alloc_haptic_buffer = false;
3444 int haptic_channel_count = adev->haptics_config.channels;
3445 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
3446 size_t audio_frame_size = frame_size - haptic_frame_size;
3447 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
3448
3449 if (adev->haptic_buffer == NULL) {
3450 alloc_haptic_buffer = true;
3451 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
3452 free(adev->haptic_buffer);
3453 adev->haptic_buffer_size = 0;
3454 alloc_haptic_buffer = true;
3455 }
3456
3457 if (alloc_haptic_buffer) {
3458 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
3459 adev->haptic_buffer_size = total_haptic_buffer_size;
3460 }
3461
3462 size_t src_index = 0, aud_index = 0, hap_index = 0;
3463 uint8_t *audio_buffer = (uint8_t *)buffer;
3464 uint8_t *haptic_buffer = adev->haptic_buffer;
3465
3466 // This is required for testing only. This works for stereo data only.
3467 // One channel is fed to audio stream and other to haptic stream for testing.
3468 if (force_haptic_path) {
3469 audio_frame_size = haptic_frame_size = bytes_per_sample;
3470 }
3471
3472 for (size_t i = 0; i < frame_count; i++) {
3473 for (size_t j = 0; j < audio_frame_size; j++)
3474 audio_buffer[aud_index++] = audio_buffer[src_index++];
3475
3476 for (size_t j = 0; j < haptic_frame_size; j++)
3477 haptic_buffer[hap_index++] = audio_buffer[src_index++];
3478 }
3479
3480 // This is required for testing only.
3481 // Discard haptic channel data.
3482 if (force_haptic_path) {
3483 src_index += haptic_frame_size;
3484 }
3485
3486 // write to audio pipeline
3487 ret = pcm_write(out->pcm,
3488 (void *)audio_buffer,
3489 frame_count * audio_frame_size);
3490
3491 // write to haptics pipeline
3492 if (adev->haptic_pcm)
3493 ret = pcm_write(adev->haptic_pcm,
3494 (void *)adev->haptic_buffer,
3495 frame_count * haptic_frame_size);
3496
3497 } else {
3498 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
3499 }
3500 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003501 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07003502 } else {
3503 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003504 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003505 }
3506
3507exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07003508 // For PCM we always consume the buffer and return #bytes regardless of ret.
3509 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003510 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07003511 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003512 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07003513
Andy Hung7401c7c2016-09-21 12:41:21 -07003514 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07003515 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07003516 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3517 ALOGE_IF(out->pcm != NULL,
3518 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07003519 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003520 // usleep not guaranteed for values over 1 second but we don't limit here.
3521 }
3522 }
Andy Hungda9b56b2016-09-16 20:06:35 -07003523
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003524 pthread_mutex_unlock(&out->lock);
3525
3526 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07003527 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003528 if (sleeptime_us != 0)
3529 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003530 }
3531 return bytes;
3532}
3533
3534static int out_get_render_position(const struct audio_stream_out *stream,
3535 uint32_t *dsp_frames)
3536{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003537 struct stream_out *out = (struct stream_out *)stream;
3538 *dsp_frames = 0;
3539 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07003540 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003541 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003542 unsigned long frames = 0;
3543 // TODO: check return value
3544 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
3545 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003546 ALOGVV("%s rendered frames %d sample_rate %d",
3547 __func__, *dsp_frames, out->sample_rate);
3548 }
3549 pthread_mutex_unlock(&out->lock);
3550 return 0;
3551 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003552 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003553}
3554
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003555static int out_add_audio_effect(const struct audio_stream *stream __unused,
3556 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003557{
3558 return 0;
3559}
3560
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003561static int out_remove_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_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3568 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003569{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003570 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003571}
3572
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003573static int out_get_presentation_position(const struct audio_stream_out *stream,
3574 uint64_t *frames, struct timespec *timestamp)
3575{
3576 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003577 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07003578 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003579
Eric Laurenta1478072015-09-21 17:21:52 -07003580 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003581
Eric Laurent949a0892013-09-20 09:20:13 -07003582 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3583 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003584 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07003585 compress_get_tstamp(out->compr, &dsp_frames,
3586 &out->sample_rate);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003587 // Adjustment accounts for A2DP encoder latency with offload usecases
3588 // Note: Encoder latency is returned in ms.
3589 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3590 unsigned long offset =
3591 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3592 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
3593 }
Eric Laurent949a0892013-09-20 09:20:13 -07003594 ALOGVV("%s rendered frames %ld sample_rate %d",
3595 __func__, dsp_frames, out->sample_rate);
3596 *frames = dsp_frames;
3597 ret = 0;
3598 /* this is the best we can do */
3599 clock_gettime(CLOCK_MONOTONIC, timestamp);
3600 }
3601 } else {
3602 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07003603 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003604 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
Andy Hung572633e2019-02-19 11:58:24 -08003605
3606 // pcm_get_htimestamp() computes the available frames by comparing
3607 // the alsa driver hw_ptr and the appl_ptr levels.
3608 // In underrun, the hw_ptr may keep running and report an excessively
3609 // large number available number.
3610 if (avail > out->kernel_buffer_size) {
3611 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
3612 __func__, avail, out->kernel_buffer_size);
3613 avail = out->kernel_buffer_size;
3614 out->last_fifo_frames_remaining = 0;
3615 } else {
3616 out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
3617 }
3618 out->last_fifo_valid = true;
3619 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
3620
3621 int64_t signed_frames = out->written - out->last_fifo_frames_remaining;
3622
3623 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
3624 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
3625
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003626 // This adjustment accounts for buffering after app processor.
3627 // It is based on estimated DSP latency per use case, rather than exact.
3628 signed_frames -=
3629 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3630
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003631 // Adjustment accounts for A2DP encoder latency with non-offload usecases
3632 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3633 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3634 signed_frames -=
3635 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3636 }
3637
Eric Laurent949a0892013-09-20 09:20:13 -07003638 // It would be unusual for this value to be negative, but check just in case ...
3639 if (signed_frames >= 0) {
3640 *frames = signed_frames;
3641 ret = 0;
3642 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003643 }
3644 }
3645 }
3646
3647 pthread_mutex_unlock(&out->lock);
3648
3649 return ret;
3650}
3651
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003652static int out_set_callback(struct audio_stream_out *stream,
3653 stream_callback_t callback, void *cookie)
3654{
3655 struct stream_out *out = (struct stream_out *)stream;
3656
3657 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003658 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003659 out->offload_callback = callback;
3660 out->offload_cookie = cookie;
3661 pthread_mutex_unlock(&out->lock);
3662 return 0;
3663}
3664
3665static int out_pause(struct audio_stream_out* stream)
3666{
3667 struct stream_out *out = (struct stream_out *)stream;
3668 int status = -ENOSYS;
3669 ALOGV("%s", __func__);
3670 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003671 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003672 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
3673 status = compress_pause(out->compr);
3674 out->offload_state = OFFLOAD_STATE_PAUSED;
3675 }
3676 pthread_mutex_unlock(&out->lock);
3677 }
3678 return status;
3679}
3680
3681static int out_resume(struct audio_stream_out* stream)
3682{
3683 struct stream_out *out = (struct stream_out *)stream;
3684 int status = -ENOSYS;
3685 ALOGV("%s", __func__);
3686 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3687 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07003688 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003689 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
3690 status = compress_resume(out->compr);
3691 out->offload_state = OFFLOAD_STATE_PLAYING;
3692 }
3693 pthread_mutex_unlock(&out->lock);
3694 }
3695 return status;
3696}
3697
3698static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3699{
3700 struct stream_out *out = (struct stream_out *)stream;
3701 int status = -ENOSYS;
3702 ALOGV("%s", __func__);
3703 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003704 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003705 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3706 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3707 else
3708 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3709 pthread_mutex_unlock(&out->lock);
3710 }
3711 return status;
3712}
3713
3714static int out_flush(struct audio_stream_out* stream)
3715{
3716 struct stream_out *out = (struct stream_out *)stream;
3717 ALOGV("%s", __func__);
3718 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003719 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003720 stop_compressed_output_l(out);
3721 pthread_mutex_unlock(&out->lock);
3722 return 0;
3723 }
3724 return -ENOSYS;
3725}
3726
Eric Laurent0e46adf2016-12-16 12:49:24 -08003727static int out_stop(const struct audio_stream_out* stream)
3728{
3729 struct stream_out *out = (struct stream_out *)stream;
3730 struct audio_device *adev = out->dev;
3731 int ret = -ENOSYS;
3732
3733 ALOGV("%s", __func__);
3734 pthread_mutex_lock(&adev->lock);
3735 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3736 out->playback_started && out->pcm != NULL) {
3737 pcm_stop(out->pcm);
3738 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08003739 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003740 }
3741 pthread_mutex_unlock(&adev->lock);
3742 return ret;
3743}
3744
3745static int out_start(const struct audio_stream_out* stream)
3746{
3747 struct stream_out *out = (struct stream_out *)stream;
3748 struct audio_device *adev = out->dev;
3749 int ret = -ENOSYS;
3750
3751 ALOGV("%s", __func__);
3752 pthread_mutex_lock(&adev->lock);
3753 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3754 !out->playback_started && out->pcm != NULL) {
3755 ret = start_output_stream(out);
3756 if (ret == 0) {
3757 out->playback_started = true;
3758 }
3759 }
3760 pthread_mutex_unlock(&adev->lock);
3761 return ret;
3762}
3763
Phil Burkbc991042017-02-24 08:06:44 -08003764/*
3765 * Modify config->period_count based on min_size_frames
3766 */
3767static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
3768{
3769 int periodCountRequested = (min_size_frames + config->period_size - 1)
3770 / config->period_size;
3771 int periodCount = MMAP_PERIOD_COUNT_MIN;
3772
3773 ALOGV("%s original config.period_size = %d config.period_count = %d",
3774 __func__, config->period_size, config->period_count);
3775
3776 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
3777 periodCount *= 2;
3778 }
3779 config->period_count = periodCount;
3780
3781 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
3782}
3783
Eric Laurent0e46adf2016-12-16 12:49:24 -08003784static int out_create_mmap_buffer(const struct audio_stream_out *stream,
3785 int32_t min_size_frames,
3786 struct audio_mmap_buffer_info *info)
3787{
3788 struct stream_out *out = (struct stream_out *)stream;
3789 struct audio_device *adev = out->dev;
3790 int ret = 0;
3791 unsigned int offset1;
3792 unsigned int frames1;
3793 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003794 uint32_t mmap_size;
3795 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003796
3797 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003798 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003799 pthread_mutex_lock(&adev->lock);
3800
3801 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003802 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003803 ret = -EINVAL;
3804 goto exit;
3805 }
3806 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003807 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003808 ret = -ENOSYS;
3809 goto exit;
3810 }
3811 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3812 if (out->pcm_device_id < 0) {
3813 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3814 __func__, out->pcm_device_id, out->usecase);
3815 ret = -EINVAL;
3816 goto exit;
3817 }
Phil Burkbc991042017-02-24 08:06:44 -08003818
3819 adjust_mmap_period_count(&out->config, min_size_frames);
3820
Eric Laurent0e46adf2016-12-16 12:49:24 -08003821 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3822 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3823 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3824 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3825 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3826 step = "open";
3827 ret = -ENODEV;
3828 goto exit;
3829 }
3830 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3831 if (ret < 0) {
3832 step = "begin";
3833 goto exit;
3834 }
3835 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003836 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003837 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003838 ret = platform_get_mmap_data_fd(adev->platform,
3839 out->pcm_device_id, 0 /*playback*/,
3840 &info->shared_memory_fd,
3841 &mmap_size);
3842 if (ret < 0) {
3843 // Fall back to non exclusive mode
3844 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3845 } else {
3846 if (mmap_size < buffer_size) {
3847 step = "mmap";
3848 goto exit;
3849 }
3850 // FIXME: indicate exclusive mode support by returning a negative buffer size
3851 info->buffer_size_frames *= -1;
3852 }
3853 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003854
3855 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3856 if (ret < 0) {
3857 step = "commit";
3858 goto exit;
3859 }
Phil Burkbc991042017-02-24 08:06:44 -08003860
3861 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003862 ret = 0;
3863
3864 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3865 __func__, info->shared_memory_address, info->buffer_size_frames);
3866
3867exit:
3868 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003869 if (out->pcm == NULL) {
3870 ALOGE("%s: %s - %d", __func__, step, ret);
3871 } else {
3872 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003873 pcm_close(out->pcm);
3874 out->pcm = NULL;
3875 }
3876 }
3877 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003878 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003879 return ret;
3880}
3881
3882static int out_get_mmap_position(const struct audio_stream_out *stream,
3883 struct audio_mmap_position *position)
3884{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003885 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003886 struct stream_out *out = (struct stream_out *)stream;
3887 ALOGVV("%s", __func__);
3888 if (position == NULL) {
3889 return -EINVAL;
3890 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003891 lock_output_stream(out);
3892 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3893 out->pcm == NULL) {
3894 ret = -ENOSYS;
3895 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003896 }
3897
3898 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003899 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003900 if (ret < 0) {
3901 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003902 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003903 }
Andy Hungfc044e12017-03-20 09:24:22 -07003904 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003905exit:
3906 pthread_mutex_unlock(&out->lock);
3907 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003908}
3909
3910
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003911/** audio_stream_in implementation **/
3912static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3913{
3914 struct stream_in *in = (struct stream_in *)stream;
3915
3916 return in->config.rate;
3917}
3918
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003919static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003920{
3921 return -ENOSYS;
3922}
3923
3924static size_t in_get_buffer_size(const struct audio_stream *stream)
3925{
3926 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003927 return in->config.period_size * in->af_period_multiplier *
3928 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003929}
3930
3931static uint32_t in_get_channels(const struct audio_stream *stream)
3932{
3933 struct stream_in *in = (struct stream_in *)stream;
3934
3935 return in->channel_mask;
3936}
3937
vivek mehta4ed66e62016-04-15 23:33:34 -07003938static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003939{
vivek mehta4ed66e62016-04-15 23:33:34 -07003940 struct stream_in *in = (struct stream_in *)stream;
3941 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003942}
3943
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003944static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003945{
3946 return -ENOSYS;
3947}
3948
3949static int in_standby(struct audio_stream *stream)
3950{
3951 struct stream_in *in = (struct stream_in *)stream;
3952 struct audio_device *adev = in->dev;
3953 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003954 bool do_stop = true;
3955
Eric Laurent994a6932013-07-17 11:51:42 -07003956 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003957
3958 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003959
3960 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003961 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003962 audio_extn_sound_trigger_stop_lab(in);
3963 in->standby = true;
3964 }
3965
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003966 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003967 if (adev->adm_deregister_stream)
3968 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3969
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003970 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003971 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003972 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003973 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003974 in->capture_started = false;
3975 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003976 if (in->pcm) {
3977 pcm_close(in->pcm);
3978 in->pcm = NULL;
3979 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003980 adev->enable_voicerx = false;
3981 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003982 if (do_stop) {
3983 status = stop_input_stream(in);
3984 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003985 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003986 }
3987 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003988 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003989 return status;
3990}
3991
Andy Hungd13f0d32017-06-12 13:58:37 -07003992static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003993{
Andy Hungd13f0d32017-06-12 13:58:37 -07003994 struct stream_in *in = (struct stream_in *)stream;
3995
3996 // We try to get the lock for consistency,
3997 // but it isn't necessary for these variables.
3998 // If we're not in standby, we may be blocked on a read.
3999 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
4000 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
4001 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
4002 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
4003
Andy Hung241e36f2019-02-19 12:00:38 -08004004 char buffer[256]; // for statistics formatting
4005 if (in->start_latency_ms.n > 0) {
4006 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
4007 dprintf(fd, " Start latency ms: %s\n", buffer);
4008 }
4009
Andy Hungd13f0d32017-06-12 13:58:37 -07004010 if (locked) {
4011 pthread_mutex_unlock(&in->lock);
4012 }
4013
4014 // dump error info
4015 (void)error_log_dump(
4016 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004017 return 0;
4018}
4019
4020static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
4021{
4022 struct stream_in *in = (struct stream_in *)stream;
4023 struct audio_device *adev = in->dev;
4024 struct str_parms *parms;
4025 char *str;
4026 char value[32];
4027 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07004028 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004029
Eric Laurent994a6932013-07-17 11:51:42 -07004030 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004031 parms = str_parms_create_str(kvpairs);
4032
4033 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
4034
Eric Laurenta1478072015-09-21 17:21:52 -07004035 lock_input_stream(in);
4036
Eric Laurent150dbfe2013-02-27 14:31:02 -08004037 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004038 if (ret >= 0) {
4039 val = atoi(value);
4040 /* no audio source uses val == 0 */
4041 if ((in->source != val) && (val != 0)) {
4042 in->source = val;
4043 }
4044 }
4045
4046 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07004047
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004048 if (ret >= 0) {
4049 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07004050 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07004051
4052 // Workaround: If routing to an non existing usb device, fail gracefully
4053 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07004054 int card;
4055 if (audio_is_usb_in_device(val) &&
4056 (card = get_alive_usb_card(parms)) >= 0) {
4057
4058 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07004059 status = -ENOSYS;
4060 } else {
4061
4062 in->device = val;
4063 /* If recording is in progress, change the tx device to new device */
4064 if (!in->standby) {
4065 ALOGV("update input routing change");
4066 // inform adm before actual routing to prevent glitches.
4067 if (adev->adm_on_routing_change) {
4068 adev->adm_on_routing_change(adev->adm_data,
4069 in->capture_handle);
4070 }
4071 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07004072 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004073 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004074 }
4075 }
4076
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004077 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004078 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004079
4080 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07004081 ALOGV("%s: exit: status(%d)", __func__, status);
4082 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004083}
4084
Haynes Mathew George569b7482017-05-08 14:44:27 -07004085static char* in_get_parameters(const struct audio_stream *stream,
4086 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004087{
Haynes Mathew George569b7482017-05-08 14:44:27 -07004088 struct stream_in *in = (struct stream_in *)stream;
4089 struct str_parms *query = str_parms_create_str(keys);
4090 char *str;
4091 struct str_parms *reply = str_parms_create();
4092 bool replied = false;
4093
4094 ALOGV("%s: enter: keys - %s", __func__, keys);
4095 replied |= stream_get_parameter_channels(query, reply,
4096 &in->supported_channel_masks[0]);
4097 replied |= stream_get_parameter_formats(query, reply,
4098 &in->supported_formats[0]);
4099 replied |= stream_get_parameter_rates(query, reply,
4100 &in->supported_sample_rates[0]);
4101 if (replied) {
4102 str = str_parms_to_str(reply);
4103 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07004104 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07004105 }
4106 str_parms_destroy(query);
4107 str_parms_destroy(reply);
4108 ALOGV("%s: exit: returns - %s", __func__, str);
4109 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004110}
4111
Eric Laurent51f3c662018-04-10 18:21:34 -07004112static int in_set_gain(struct audio_stream_in *stream, float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004113{
Eric Laurent51f3c662018-04-10 18:21:34 -07004114 struct stream_in *in = (struct stream_in *)stream;
4115 char mixer_ctl_name[128];
4116 struct mixer_ctl *ctl;
4117 int ctl_value;
4118
4119 ALOGV("%s: gain %f", __func__, gain);
4120
4121 if (stream == NULL)
4122 return -EINVAL;
4123
4124 /* in_set_gain() only used to silence MMAP capture for now */
4125 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
4126 return -ENOSYS;
4127
4128 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
4129
4130 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
4131 if (!ctl) {
4132 ALOGW("%s: Could not get ctl for mixer cmd - %s",
4133 __func__, mixer_ctl_name);
4134 return -ENOSYS;
4135 }
4136
4137 if (gain < RECORD_GAIN_MIN)
4138 gain = RECORD_GAIN_MIN;
4139 else if (gain > RECORD_GAIN_MAX)
4140 gain = RECORD_GAIN_MAX;
4141 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
4142
4143 mixer_ctl_set_value(ctl, 0, ctl_value);
4144 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004145}
4146
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004147static void in_snd_mon_cb(void * stream, struct str_parms * parms)
4148{
4149 if (!stream || !parms)
4150 return;
4151
4152 struct stream_in *in = (struct stream_in *)stream;
4153 struct audio_device *adev = in->dev;
4154
4155 card_status_t status;
4156 int card;
4157 if (parse_snd_card_status(parms, &card, &status) < 0)
4158 return;
4159
4160 pthread_mutex_lock(&adev->lock);
4161 bool valid_cb = (card == adev->snd_card);
4162 pthread_mutex_unlock(&adev->lock);
4163
4164 if (!valid_cb)
4165 return;
4166
4167 lock_input_stream(in);
4168 if (in->card_status != status)
4169 in->card_status = status;
4170 pthread_mutex_unlock(&in->lock);
4171
4172 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
4173 use_case_table[in->usecase],
4174 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4175
4176 // a better solution would be to report error back to AF and let
4177 // it put the stream to standby
4178 if (status == CARD_STATUS_OFFLINE)
4179 in_standby(&in->stream.common);
4180
4181 return;
4182}
4183
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004184static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
4185 size_t bytes)
4186{
4187 struct stream_in *in = (struct stream_in *)stream;
4188 struct audio_device *adev = in->dev;
4189 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07004190 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07004191 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004192
Eric Laurenta1478072015-09-21 17:21:52 -07004193 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07004194 const size_t frame_size = audio_stream_in_frame_size(stream);
4195 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07004196
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004197 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004198 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004199 /* Read from sound trigger HAL */
4200 audio_extn_sound_trigger_read(in, buffer, bytes);
4201 pthread_mutex_unlock(&in->lock);
4202 return bytes;
4203 }
4204
Eric Laurent0e46adf2016-12-16 12:49:24 -08004205 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
4206 ret = -ENOSYS;
4207 goto exit;
4208 }
4209
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004210 if (in->standby) {
Andy Hung241e36f2019-02-19 12:00:38 -08004211 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
4212
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004213 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004214 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004215 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004216 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004217 goto exit;
4218 }
4219 in->standby = 0;
Andy Hung241e36f2019-02-19 12:00:38 -08004220
4221 // log startup time in ms.
4222 simple_stats_log(
4223 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004224 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004225
Andy Hungd13f0d32017-06-12 13:58:37 -07004226 // errors that occur here are read errors.
4227 error_code = ERROR_CODE_READ;
4228
Haynes Mathew George03c40102016-01-29 17:57:48 -08004229 //what's the duration requested by the client?
4230 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
4231 in->config.rate;
4232 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004233
Haynes Mathew George03c40102016-01-29 17:57:48 -08004234 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004235 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08004236 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004237 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07004238 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004239 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004240 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004241 if (ret < 0) {
4242 ALOGE("Failed to read w/err %s", strerror(errno));
4243 ret = -errno;
4244 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004245 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4246 if (bytes % 4 == 0) {
4247 /* data from DSP comes in 24_8 format, convert it to 8_24 */
4248 int_buf_stream = buffer;
4249 for (size_t itt=0; itt < bytes/4 ; itt++) {
4250 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07004251 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004252 } else {
4253 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
4254 ret = -EINVAL;
4255 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07004256 }
4257 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004258 }
4259
Haynes Mathew George03c40102016-01-29 17:57:48 -08004260 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004261
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004262 /*
4263 * Instead of writing zeroes here, we could trust the hardware
4264 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004265 * 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 -08004266 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08004267 if (ret == 0 && adev->mic_muted &&
4268 !voice_is_in_call_rec_stream(in) &&
4269 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004270 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07004271 in->frames_muted += frames;
4272 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004273
4274exit:
4275 pthread_mutex_unlock(&in->lock);
4276
4277 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07004278 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004279 in_standby(&in->stream.common);
4280 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07004281 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08004282 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07004283 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08004284 }
4285 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07004286 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004287 }
4288 return bytes;
4289}
4290
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004291static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004292{
4293 return 0;
4294}
4295
Andy Hung6ebe5962016-01-15 17:46:57 -08004296static int in_get_capture_position(const struct audio_stream_in *stream,
4297 int64_t *frames, int64_t *time)
4298{
4299 if (stream == NULL || frames == NULL || time == NULL) {
4300 return -EINVAL;
4301 }
4302 struct stream_in *in = (struct stream_in *)stream;
4303 int ret = -ENOSYS;
4304
4305 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08004306 // note: ST sessions do not close the alsa pcm driver synchronously
4307 // on standby. Therefore, we may return an error even though the
4308 // pcm stream is still opened.
4309 if (in->standby) {
4310 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
4311 "%s stream in standby but pcm not NULL for non ST session", __func__);
4312 goto exit;
4313 }
Andy Hung6ebe5962016-01-15 17:46:57 -08004314 if (in->pcm) {
4315 struct timespec timestamp;
4316 unsigned int avail;
4317 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
4318 *frames = in->frames_read + avail;
4319 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
4320 ret = 0;
4321 }
4322 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08004323exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08004324 pthread_mutex_unlock(&in->lock);
4325 return ret;
4326}
4327
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004328static int add_remove_audio_effect(const struct audio_stream *stream,
4329 effect_handle_t effect,
4330 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004331{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004332 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004333 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004334 int status = 0;
4335 effect_descriptor_t desc;
4336
4337 status = (*effect)->get_descriptor(effect, &desc);
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004338 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
4339
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004340 if (status != 0)
4341 return status;
4342
Eric Laurenta1478072015-09-21 17:21:52 -07004343 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004344 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07004345 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07004346 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07004347 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004348 in->enable_aec != enable &&
4349 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
4350 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004351 if (!enable)
4352 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07004353 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
4354 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
4355 adev->enable_voicerx = enable;
4356 struct audio_usecase *usecase;
4357 struct listnode *node;
4358 list_for_each(node, &adev->usecase_list) {
4359 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07004360 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07004361 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05004362 }
4363 }
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004364 if (!in->standby
4365 && enable_disable_effect(in->dev, in, EFFECT_AEC, enable) == -ENOSYS)
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004366 select_devices(in->dev, in->usecase);
4367 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07004368 if (in->enable_ns != enable &&
4369 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
4370 in->enable_ns = enable;
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004371 if (!in->standby) {
4372 if (in->source != AUDIO_SOURCE_VOICE_COMMUNICATION
4373 || enable_disable_effect(in->dev, in, EFFECT_NS, enable) == -ENOSYS)
4374 select_devices(in->dev, in->usecase);
4375 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07004376 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004377 pthread_mutex_unlock(&in->dev->lock);
4378 pthread_mutex_unlock(&in->lock);
4379
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004380 return 0;
4381}
4382
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004383static int in_add_audio_effect(const struct audio_stream *stream,
4384 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004385{
Eric Laurent994a6932013-07-17 11:51:42 -07004386 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004387 return add_remove_audio_effect(stream, effect, true);
4388}
4389
4390static int in_remove_audio_effect(const struct audio_stream *stream,
4391 effect_handle_t effect)
4392{
Eric Laurent994a6932013-07-17 11:51:42 -07004393 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004394 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004395}
4396
Eric Laurent0e46adf2016-12-16 12:49:24 -08004397static int in_stop(const struct audio_stream_in* stream)
4398{
4399 struct stream_in *in = (struct stream_in *)stream;
4400 struct audio_device *adev = in->dev;
4401
4402 int ret = -ENOSYS;
4403 ALOGV("%s", __func__);
4404 pthread_mutex_lock(&adev->lock);
4405 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4406 in->capture_started && in->pcm != NULL) {
4407 pcm_stop(in->pcm);
4408 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08004409 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004410 }
4411 pthread_mutex_unlock(&adev->lock);
4412 return ret;
4413}
4414
4415static int in_start(const struct audio_stream_in* stream)
4416{
4417 struct stream_in *in = (struct stream_in *)stream;
4418 struct audio_device *adev = in->dev;
4419 int ret = -ENOSYS;
4420
4421 ALOGV("%s in %p", __func__, in);
4422 pthread_mutex_lock(&adev->lock);
4423 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4424 !in->capture_started && in->pcm != NULL) {
4425 if (!in->capture_started) {
4426 ret = start_input_stream(in);
4427 if (ret == 0) {
4428 in->capture_started = true;
4429 }
4430 }
4431 }
4432 pthread_mutex_unlock(&adev->lock);
4433 return ret;
4434}
4435
Phil Burkc4714fc2019-02-16 22:28:11 -08004436// Read offset for the input positional timestamp from a property.
4437// This is to workaround apparent inaccuracies in the timing info that
4438// are causing glitches.
4439static int64_t in_get_mmap_time_offset() {
4440 // Roughly 100 usec is needed on some devices to cover inaccuracy in DSP.
4441 // This should be set in a property. But I cannot read the property!
4442 // So I am setting the offset here to 101 as a test.
4443 const int32_t kDefaultOffsetMicros = 101; // should be zero if no bug
4444 // FIXME - why is the property not being read?! The default is used.
4445 int32_t mmap_time_offset_micros = property_get_int32(
4446 "persist.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
4447 ALOGI("in_get_mmap_time_offset set to %d micros", mmap_time_offset_micros);
4448 return mmap_time_offset_micros * (int64_t)1000;
4449}
4450
Eric Laurent0e46adf2016-12-16 12:49:24 -08004451static int in_create_mmap_buffer(const struct audio_stream_in *stream,
4452 int32_t min_size_frames,
4453 struct audio_mmap_buffer_info *info)
4454{
4455 struct stream_in *in = (struct stream_in *)stream;
4456 struct audio_device *adev = in->dev;
4457 int ret = 0;
4458 unsigned int offset1;
4459 unsigned int frames1;
4460 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07004461 uint32_t mmap_size;
4462 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004463
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004464 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004465 pthread_mutex_lock(&adev->lock);
4466 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08004467
Eric Laurent0e46adf2016-12-16 12:49:24 -08004468 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004469 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004470 ret = -EINVAL;
4471 goto exit;
4472 }
4473 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08004474 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004475 ALOGV("%s in %p", __func__, in);
4476 ret = -ENOSYS;
4477 goto exit;
4478 }
4479 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
4480 if (in->pcm_device_id < 0) {
4481 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4482 __func__, in->pcm_device_id, in->usecase);
4483 ret = -EINVAL;
4484 goto exit;
4485 }
Phil Burkbc991042017-02-24 08:06:44 -08004486
4487 adjust_mmap_period_count(&in->config, min_size_frames);
4488
Eric Laurent0e46adf2016-12-16 12:49:24 -08004489 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4490 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
4491 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
4492 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
4493 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
4494 step = "open";
4495 ret = -ENODEV;
4496 goto exit;
4497 }
4498
4499 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
4500 if (ret < 0) {
4501 step = "begin";
4502 goto exit;
4503 }
4504 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07004505 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004506 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07004507 ret = platform_get_mmap_data_fd(adev->platform,
4508 in->pcm_device_id, 1 /*capture*/,
4509 &info->shared_memory_fd,
4510 &mmap_size);
4511 if (ret < 0) {
4512 // Fall back to non exclusive mode
4513 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
4514 } else {
4515 if (mmap_size < buffer_size) {
4516 step = "mmap";
4517 goto exit;
4518 }
4519 // FIXME: indicate exclusive mode support by returning a negative buffer size
4520 info->buffer_size_frames *= -1;
4521 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08004522
Haynes Mathew George96483a22017-03-28 14:52:47 -07004523 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004524
4525 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4526 if (ret < 0) {
4527 step = "commit";
4528 goto exit;
4529 }
4530
Phil Burkc4714fc2019-02-16 22:28:11 -08004531 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
4532
Phil Burkbc991042017-02-24 08:06:44 -08004533 in->standby = false;
4534 ret = 0;
4535
Eric Laurent0e46adf2016-12-16 12:49:24 -08004536 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4537 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004538
4539exit:
4540 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004541 if (in->pcm == NULL) {
4542 ALOGE("%s: %s - %d", __func__, step, ret);
4543 } else {
4544 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08004545 pcm_close(in->pcm);
4546 in->pcm = NULL;
4547 }
4548 }
4549 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004550 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004551 return ret;
4552}
4553
4554static int in_get_mmap_position(const struct audio_stream_in *stream,
4555 struct audio_mmap_position *position)
4556{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004557 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004558 struct stream_in *in = (struct stream_in *)stream;
4559 ALOGVV("%s", __func__);
4560 if (position == NULL) {
4561 return -EINVAL;
4562 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004563 lock_input_stream(in);
4564 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
4565 in->pcm == NULL) {
4566 ret = -ENOSYS;
4567 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004568 }
4569 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004570 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004571 if (ret < 0) {
4572 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004573 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004574 }
Andy Hungfc044e12017-03-20 09:24:22 -07004575 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Phil Burkc4714fc2019-02-16 22:28:11 -08004576 position->time_nanoseconds += in->mmap_time_offset_nanos;
4577
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004578exit:
4579 pthread_mutex_unlock(&in->lock);
4580 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004581}
4582
jiabin8962a4d2018-03-19 18:21:24 -07004583static int in_get_active_microphones(const struct audio_stream_in *stream,
4584 struct audio_microphone_characteristic_t *mic_array,
4585 size_t *mic_count) {
4586 struct stream_in *in = (struct stream_in *)stream;
4587 struct audio_device *adev = in->dev;
4588 ALOGVV("%s", __func__);
4589
4590 lock_input_stream(in);
4591 pthread_mutex_lock(&adev->lock);
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004592 int ret = platform_get_active_microphones(adev->platform,
jiabin8962a4d2018-03-19 18:21:24 -07004593 audio_channel_count_from_in_mask(in->channel_mask),
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004594 in->usecase, mic_array, mic_count);
jiabin8962a4d2018-03-19 18:21:24 -07004595 pthread_mutex_unlock(&adev->lock);
4596 pthread_mutex_unlock(&in->lock);
4597
4598 return ret;
4599}
4600
4601static int adev_get_microphones(const struct audio_hw_device *dev,
4602 struct audio_microphone_characteristic_t *mic_array,
4603 size_t *mic_count) {
4604 struct audio_device *adev = (struct audio_device *)dev;
4605 ALOGVV("%s", __func__);
4606
4607 pthread_mutex_lock(&adev->lock);
4608 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
4609 pthread_mutex_unlock(&adev->lock);
4610
4611 return ret;
4612}
Eric Laurent0e46adf2016-12-16 12:49:24 -08004613
Paul McLean57530d52018-12-17 08:24:21 -07004614static int in_set_microphone_direction(const struct audio_stream_in *stream,
4615 audio_microphone_direction_t dir) {
4616 (void)stream;
4617 (void)dir;
4618 ALOGVV("%s", __func__);
4619 return -ENOSYS;
4620}
4621
4622static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
4623 (void)stream;
4624 (void)zoom;
4625 ALOGVV("%s", __func__);
4626 return -ENOSYS;
4627}
4628
juyuchenba338cd2019-01-21 11:57:17 +08004629static void in_update_sink_metadata(struct audio_stream_in *stream,
4630 const struct sink_metadata *sink_metadata) {
4631
4632 if (stream == NULL
4633 || sink_metadata == NULL
4634 || sink_metadata->tracks == NULL) {
4635 return;
4636 }
4637
4638 int error = 0;
4639 struct stream_in *in = (struct stream_in *)stream;
4640 struct audio_device *adev = in->dev;
4641 audio_devices_t device = AUDIO_DEVICE_NONE;
4642
4643 if (sink_metadata->track_count != 0)
4644 device = sink_metadata->tracks->dest_device;
4645
4646 lock_input_stream(in);
4647 pthread_mutex_lock(&adev->lock);
4648 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, device);
4649
4650 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY
4651 && device != AUDIO_DEVICE_NONE
4652 && adev->voice_tx_output != NULL) {
4653 /* Use the rx device from afe-proxy record to route voice call because
4654 there is no routing if tx device is on primary hal and rx device
4655 is on other hal during voice call. */
4656 adev->voice_tx_output->devices = device;
4657
4658 if (!voice_is_call_state_active(adev)) {
4659 if (adev->mode == AUDIO_MODE_IN_CALL) {
4660 adev->current_call_output = adev->voice_tx_output;
4661 error = voice_start_call(adev);
4662 if (error != 0)
4663 ALOGE("%s: start voice call failed %d", __func__, error);
4664 }
4665 } else {
4666 adev->current_call_output = adev->voice_tx_output;
4667 voice_update_devices_for_all_voice_usecases(adev);
4668 }
4669 }
4670
4671 pthread_mutex_unlock(&adev->lock);
4672 pthread_mutex_unlock(&in->lock);
4673}
4674
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004675static int adev_open_output_stream(struct audio_hw_device *dev,
4676 audio_io_handle_t handle,
4677 audio_devices_t devices,
4678 audio_output_flags_t flags,
4679 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07004680 struct audio_stream_out **stream_out,
4681 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004682{
4683 struct audio_device *adev = (struct audio_device *)dev;
4684 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004685 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004686 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
4687 bool is_usb_dev = audio_is_usb_out_device(devices) &&
4688 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08004689 bool force_haptic_path =
4690 property_get_bool("vendor.audio.test_haptic", false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004691
Andy Hungd9653bd2017-08-01 19:31:39 -07004692 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
4693 return -ENOSYS;
4694 }
4695
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004696 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
4697 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08004698
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004699 *stream_out = NULL;
4700 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4701
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004702 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
4703
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004704 if (devices == AUDIO_DEVICE_NONE)
4705 devices = AUDIO_DEVICE_OUT_SPEAKER;
4706
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004707 out->flags = flags;
4708 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004709 out->dev = adev;
Eric Laurentc4aef752013-09-12 17:45:53 -07004710 out->handle = handle;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004711 out->a2dp_compress_mute = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004712
4713 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004714 if ((is_hdmi || is_usb_dev) &&
4715 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
4716 (flags == AUDIO_OUTPUT_FLAG_NONE ||
4717 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Eric Laurentab805ee2018-03-30 12:20:38 -07004718 audio_format_t req_format = config->format;
4719 audio_channel_mask_t req_channel_mask = config->channel_mask;
4720 uint32_t req_sample_rate = config->sample_rate;
4721
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004722 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004723 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004724 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004725 if (config->sample_rate == 0)
4726 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Eric Laurentab805ee2018-03-30 12:20:38 -07004727 if (config->channel_mask == AUDIO_CHANNEL_NONE)
Haynes Mathew George569b7482017-05-08 14:44:27 -07004728 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
4729 if (config->format == AUDIO_FORMAT_DEFAULT)
4730 config->format = AUDIO_FORMAT_PCM_16_BIT;
4731 } else if (is_usb_dev) {
4732 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
4733 &config->format,
4734 &out->supported_formats[0],
4735 MAX_SUPPORTED_FORMATS,
4736 &config->channel_mask,
4737 &out->supported_channel_masks[0],
4738 MAX_SUPPORTED_CHANNEL_MASKS,
4739 &config->sample_rate,
4740 &out->supported_sample_rates[0],
4741 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004742 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004743 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004744 pthread_mutex_unlock(&adev->lock);
Eric Laurentab805ee2018-03-30 12:20:38 -07004745 if (ret != 0) {
4746 // For MMAP NO IRQ, allow conversions in ADSP
4747 if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
4748 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004749
Eric Laurentab805ee2018-03-30 12:20:38 -07004750 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
4751 config->sample_rate = req_sample_rate;
4752 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
4753 config->channel_mask = req_channel_mask;
4754 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
4755 config->format = req_format;
4756 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004757
Haynes Mathew George569b7482017-05-08 14:44:27 -07004758 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004759 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004760 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004761 if (is_hdmi) {
4762 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4763 out->config = pcm_config_hdmi_multi;
4764 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
4765 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4766 out->config = pcm_config_mmap_playback;
4767 out->stream.start = out_start;
4768 out->stream.stop = out_stop;
4769 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4770 out->stream.get_mmap_position = out_get_mmap_position;
4771 } else {
4772 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4773 out->config = pcm_config_hifi;
4774 }
4775
4776 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004777 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004778 if (is_hdmi) {
4779 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
4780 audio_bytes_per_sample(out->format));
4781 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004782 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004783 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07004784 pthread_mutex_lock(&adev->lock);
4785 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4786 pthread_mutex_unlock(&adev->lock);
4787
4788 // reject offload during card offline to allow
4789 // fallback to s/w paths
4790 if (offline) {
4791 ret = -ENODEV;
4792 goto error_open;
4793 }
4794
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004795 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4796 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4797 ALOGE("%s: Unsupported Offload information", __func__);
4798 ret = -EINVAL;
4799 goto error_open;
4800 }
4801 if (!is_supported_format(config->offload_info.format)) {
4802 ALOGE("%s: Unsupported audio format", __func__);
4803 ret = -EINVAL;
4804 goto error_open;
4805 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004806 out->sample_rate = config->offload_info.sample_rate;
4807 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
4808 out->channel_mask = config->offload_info.channel_mask;
4809 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
4810 out->channel_mask = config->channel_mask;
4811 else
4812 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4813
4814 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004815
4816 out->compr_config.codec = (struct snd_codec *)
4817 calloc(1, sizeof(struct snd_codec));
4818
4819 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004820
4821 out->stream.set_callback = out_set_callback;
4822 out->stream.pause = out_pause;
4823 out->stream.resume = out_resume;
4824 out->stream.drain = out_drain;
4825 out->stream.flush = out_flush;
4826
4827 out->compr_config.codec->id =
4828 get_snd_codec_id(config->offload_info.format);
4829 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
4830 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004831 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004832 out->compr_config.codec->bit_rate =
4833 config->offload_info.bit_rate;
4834 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004835 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004836 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
4837
4838 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4839 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004840
4841 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004842 create_offload_callback_thread(out);
4843 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4844 __func__, config->offload_info.version,
4845 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02004846 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4847 switch (config->sample_rate) {
4848 case 0:
4849 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4850 break;
4851 case 8000:
4852 case 16000:
4853 case 48000:
4854 out->sample_rate = config->sample_rate;
4855 break;
4856 default:
4857 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
4858 config->sample_rate);
4859 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4860 ret = -EINVAL;
4861 goto error_open;
4862 }
4863 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4864 switch (config->channel_mask) {
4865 case AUDIO_CHANNEL_NONE:
4866 case AUDIO_CHANNEL_OUT_STEREO:
4867 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4868 break;
4869 default:
4870 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
4871 config->channel_mask);
4872 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4873 ret = -EINVAL;
4874 goto error_open;
4875 }
4876 switch (config->format) {
4877 case AUDIO_FORMAT_DEFAULT:
4878 case AUDIO_FORMAT_PCM_16_BIT:
4879 out->format = AUDIO_FORMAT_PCM_16_BIT;
4880 break;
4881 default:
4882 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
4883 config->format);
4884 config->format = AUDIO_FORMAT_PCM_16_BIT;
4885 ret = -EINVAL;
4886 goto error_open;
4887 }
4888
4889 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004890 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004891 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004892 case 0:
4893 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
4894 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07004895 case 8000:
4896 case 16000:
4897 case 48000:
4898 out->sample_rate = config->sample_rate;
4899 break;
4900 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004901 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
4902 config->sample_rate);
4903 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4904 ret = -EINVAL;
4905 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004906 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004907 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4908 switch (config->channel_mask) {
4909 case AUDIO_CHANNEL_NONE:
4910 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4911 break;
4912 case AUDIO_CHANNEL_OUT_STEREO:
4913 out->channel_mask = config->channel_mask;
4914 break;
4915 default:
4916 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
4917 config->channel_mask);
4918 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4919 ret = -EINVAL;
4920 break;
4921 }
4922 switch (config->format) {
4923 case AUDIO_FORMAT_DEFAULT:
4924 out->format = AUDIO_FORMAT_PCM_16_BIT;
4925 break;
4926 case AUDIO_FORMAT_PCM_16_BIT:
4927 out->format = config->format;
4928 break;
4929 default:
4930 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
4931 config->format);
4932 config->format = AUDIO_FORMAT_PCM_16_BIT;
4933 ret = -EINVAL;
4934 break;
4935 }
4936 if (ret != 0)
4937 goto error_open;
4938
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004939 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4940 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004941 out->config.rate = out->sample_rate;
4942 out->config.channels =
4943 audio_channel_count_from_out_mask(out->channel_mask);
4944 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004945 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004946 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
4947 switch (config->sample_rate) {
4948 case 0:
4949 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4950 break;
4951 case 8000:
4952 case 16000:
4953 case 32000:
4954 case 48000:
4955 out->sample_rate = config->sample_rate;
4956 break;
4957 default:
4958 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
4959 config->sample_rate);
4960 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4961 ret = -EINVAL;
4962 break;
4963 }
Eric Laurentad2dde92017-09-20 18:27:31 -07004964 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004965 switch (config->channel_mask) {
4966 case AUDIO_CHANNEL_NONE:
4967 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4968 break;
4969 case AUDIO_CHANNEL_OUT_STEREO:
4970 out->channel_mask = config->channel_mask;
4971 break;
4972 default:
4973 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
4974 config->channel_mask);
4975 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4976 ret = -EINVAL;
4977 break;
4978 }
4979 switch (config->format) {
4980 case AUDIO_FORMAT_DEFAULT:
4981 out->format = AUDIO_FORMAT_PCM_16_BIT;
4982 break;
4983 case AUDIO_FORMAT_PCM_16_BIT:
4984 out->format = config->format;
4985 break;
4986 default:
4987 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
4988 config->format);
4989 config->format = AUDIO_FORMAT_PCM_16_BIT;
4990 ret = -EINVAL;
4991 break;
4992 }
4993 if (ret != 0)
4994 goto error_open;
4995
vivek mehtaa68fea62017-06-08 19:04:02 -07004996 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07004997 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4998 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004999 out->config.rate = out->sample_rate;
5000 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07005001 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005002 out->sample_rate,
5003 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07005004 out->config.channels,
5005 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005006 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07005007 out->config.period_size = buffer_size / frame_size;
5008 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
5009 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005010 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005011 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07005012 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
5013 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005014 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07005015 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
5016 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005017 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07005018 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005019 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005020 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005021 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08005022 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
5023 out->config = pcm_config_mmap_playback;
5024 out->stream.start = out_start;
5025 out->stream.stop = out_stop;
5026 out->stream.create_mmap_buffer = out_create_mmap_buffer;
5027 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07005028 } else {
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005029 if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
5030 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
5031 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
5032 if (adev->haptic_pcm_device_id < 0) {
5033 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
5034 __func__, adev->haptic_pcm_device_id, out->usecase);
5035 ret = -ENOSYS;
5036 goto error_open;
5037 }
5038 out->config = pcm_config_haptics_audio;
5039 if (force_haptic_path)
5040 adev->haptics_config = pcm_config_haptics_audio;
5041 else
5042 adev->haptics_config = pcm_config_haptics;
5043 } else {
5044 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
5045 out->config = pcm_config_low_latency;
5046 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07005047 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005048
5049 if (config->sample_rate == 0) {
5050 out->sample_rate = out->config.rate;
5051 } else {
5052 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07005053 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005054
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005055 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
5056 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
5057 } else {
5058 out->channel_mask = config->channel_mask;
5059 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005060
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005061 if (config->format == AUDIO_FORMAT_DEFAULT)
5062 out->format = audio_format_from_pcm_format(out->config.format);
5063 else if (!audio_is_linear_pcm(config->format)) {
5064 config->format = AUDIO_FORMAT_PCM_16_BIT;
5065 ret = -EINVAL;
5066 goto error_open;
5067 } else {
5068 out->format = config->format;
5069 }
5070
5071 out->config.rate = out->sample_rate;
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005072
5073 if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
5074 out->config.channels =
5075 audio_channel_count_from_out_mask(out->channel_mask &
5076 ~AUDIO_CHANNEL_HAPTIC_ALL);
5077
5078 if (force_haptic_path) {
5079 out->config.channels = 1;
5080 adev->haptics_config.channels = 1;
5081 } else {
5082 adev->haptics_config.channels =
5083 audio_channel_count_from_out_mask(out->channel_mask &
5084 AUDIO_CHANNEL_HAPTIC_ALL);
5085 }
5086 } else {
5087 out->config.channels =
5088 audio_channel_count_from_out_mask(out->channel_mask);
5089 }
5090
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005091 if (out->format != audio_format_from_pcm_format(out->config.format)) {
5092 out->config.format = pcm_format_from_audio_format(out->format);
5093 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005094 }
Kevin Rocard50eff892017-05-02 16:52:05 -07005095
5096 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
5097 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005098 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07005099 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
5100 __func__, config->sample_rate, config->format, config->channel_mask);
5101 config->sample_rate = out->sample_rate;
5102 config->format = out->format;
5103 config->channel_mask = out->channel_mask;
5104 ret = -EINVAL;
5105 goto error_open;
5106 }
5107
Andy Hung6fcba9c2014-03-18 11:53:32 -07005108 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
5109 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005110
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005111 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005112 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005113 adev->primary_output = out;
5114 else {
5115 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005116 ret = -EEXIST;
5117 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005118 }
5119 }
5120
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005121 /* Check if this usecase is already existing */
5122 pthread_mutex_lock(&adev->lock);
5123 if (get_usecase_from_list(adev, out->usecase) != NULL) {
5124 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005125 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005126 ret = -EEXIST;
5127 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005128 }
5129 pthread_mutex_unlock(&adev->lock);
5130
5131 out->stream.common.get_sample_rate = out_get_sample_rate;
5132 out->stream.common.set_sample_rate = out_set_sample_rate;
5133 out->stream.common.get_buffer_size = out_get_buffer_size;
5134 out->stream.common.get_channels = out_get_channels;
5135 out->stream.common.get_format = out_get_format;
5136 out->stream.common.set_format = out_set_format;
5137 out->stream.common.standby = out_standby;
5138 out->stream.common.dump = out_dump;
5139 out->stream.common.set_parameters = out_set_parameters;
5140 out->stream.common.get_parameters = out_get_parameters;
5141 out->stream.common.add_audio_effect = out_add_audio_effect;
5142 out->stream.common.remove_audio_effect = out_remove_audio_effect;
5143 out->stream.get_latency = out_get_latency;
5144 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07005145#ifdef NO_AUDIO_OUT
5146 out->stream.write = out_write_for_no_output;
5147#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005148 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07005149#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005150 out->stream.get_render_position = out_get_render_position;
5151 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005152 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005153
Eric Laurent0e46adf2016-12-16 12:49:24 -08005154 if (out->realtime)
5155 out->af_period_multiplier = af_period_multiplier;
5156 else
5157 out->af_period_multiplier = 1;
5158
Andy Hung572633e2019-02-19 11:58:24 -08005159 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
5160
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005161 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07005162 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005163 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005164
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005165 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005166 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005167 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
5168
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005169 config->format = out->stream.common.get_format(&out->stream.common);
5170 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
5171 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
5172
Kevin Rocarda325aa22018-04-03 09:15:52 -07005173 register_format(out->format, out->supported_formats);
5174 register_channel_mask(out->channel_mask, out->supported_channel_masks);
5175 register_sample_rate(out->sample_rate, out->supported_sample_rates);
5176
Andy Hunga452b0a2017-03-15 14:51:15 -07005177 out->error_log = error_log_create(
5178 ERROR_LOG_ENTRIES,
5179 1000000000 /* aggregate consecutive identical errors within one second in ns */);
5180
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005181 /*
5182 By locking output stream before registering, we allow the callback
5183 to update stream's state only after stream's initial state is set to
5184 adev state.
5185 */
5186 lock_output_stream(out);
5187 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
5188 pthread_mutex_lock(&adev->lock);
5189 out->card_status = adev->card_status;
5190 pthread_mutex_unlock(&adev->lock);
5191 pthread_mutex_unlock(&out->lock);
5192
vivek mehta4a824772017-06-08 19:05:49 -07005193 stream_app_type_cfg_init(&out->app_type_cfg);
5194
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005195 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005196
Eric Laurent994a6932013-07-17 11:51:42 -07005197 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005198 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005199
5200error_open:
5201 free(out);
5202 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07005203 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005204 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005205}
5206
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005207static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005208 struct audio_stream_out *stream)
5209{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005210 struct stream_out *out = (struct stream_out *)stream;
5211 struct audio_device *adev = out->dev;
5212
Eric Laurent994a6932013-07-17 11:51:42 -07005213 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005214
5215 // must deregister from sndmonitor first to prevent races
5216 // between the callback and close_stream
5217 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005218 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005219 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
5220 destroy_offload_callback_thread(out);
5221
5222 if (out->compr_config.codec != NULL)
5223 free(out->compr_config.codec);
5224 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07005225
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005226 out->a2dp_compress_mute = false;
5227
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07005228 if (adev->voice_tx_output == out)
5229 adev->voice_tx_output = NULL;
5230
Andy Hunga452b0a2017-03-15 14:51:15 -07005231 error_log_destroy(out->error_log);
5232 out->error_log = NULL;
5233
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005234 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005235 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005236 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005237 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07005238 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005239}
5240
5241static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
5242{
5243 struct audio_device *adev = (struct audio_device *)dev;
5244 struct str_parms *parms;
5245 char *str;
5246 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005247 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005248 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07005249 int status = 0;
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005250 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005251
Joe Onorato188b6222016-03-01 11:02:27 -08005252 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005253
5254 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005255
5256 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005257 status = voice_set_parameters(adev, parms);
5258 if (status != 0) {
5259 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005260 }
5261
5262 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
5263 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07005264 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005265 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5266 adev->bluetooth_nrec = true;
5267 else
5268 adev->bluetooth_nrec = false;
5269 }
5270
5271 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
5272 if (ret >= 0) {
5273 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5274 adev->screen_off = false;
5275 else
5276 adev->screen_off = true;
5277 }
5278
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005279 ret = str_parms_get_int(parms, "rotation", &val);
5280 if (ret >= 0) {
5281 bool reverse_speakers = false;
Eric Laurent5f4ca952018-10-19 17:33:43 -07005282 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005283 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005284 // FIXME: note that the code below assumes that the speakers are in the correct placement
5285 // relative to the user when the device is rotated 90deg from its default rotation. This
5286 // assumption is device-specific, not platform-specific like this code.
5287 case 270:
5288 reverse_speakers = true;
Eric Laurent5f4ca952018-10-19 17:33:43 -07005289 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005290 break;
5291 case 0:
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005292 case 180:
Eric Laurent5f4ca952018-10-19 17:33:43 -07005293 camera_rotation = CAMERA_ROTATION_PORTRAIT;
5294 break;
5295 case 90:
5296 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005297 break;
5298 default:
5299 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07005300 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005301 }
Eric Laurent03f09432014-03-25 18:09:11 -07005302 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07005303 // check and set swap
5304 // - check if orientation changed and speaker active
5305 // - set rotation and cache the rotation value
Eric Laurent5f4ca952018-10-19 17:33:43 -07005306 adev->camera_orientation =
5307 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
5308#ifndef MAXXAUDIO_QDSP_ENABLED
vivek mehtae59cfb22017-06-16 15:57:11 -07005309 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Eric Laurent5f4ca952018-10-19 17:33:43 -07005310#endif
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005311 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005312 }
5313
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005314 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
5315 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005316 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005317 }
5318
David Linee3fe402017-03-13 10:00:42 -07005319 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
5320 if (ret >= 0) {
5321 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07005322 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005323 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5324 if (ret >= 0) {
5325 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005326 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005327 }
Eric Laurent99dab492017-06-17 15:19:08 -07005328 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005329 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5330 if (ret >= 0) {
5331 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005332 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005333 }
5334 }
5335 }
5336
5337 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
5338 if (ret >= 0) {
5339 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07005340 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005341 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5342 if (ret >= 0) {
5343 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005344 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005345 }
Eric Laurent99dab492017-06-17 15:19:08 -07005346 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005347 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5348 if (ret >= 0) {
5349 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005350 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005351 }
5352 }
5353 }
5354
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08005355 audio_extn_hfp_set_parameters(adev, parms);
jasmine cha270b7762018-03-30 15:41:33 +08005356 audio_extn_ma_set_parameters(adev, parms);
5357
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005358 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
5359 if (status >= 0 && a2dp_reconfig) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005360 struct audio_usecase *usecase;
5361 struct listnode *node;
5362 list_for_each(node, &adev->usecase_list) {
5363 usecase = node_to_item(node, struct audio_usecase, list);
5364 if ((usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005365 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005366 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
5367
5368 pthread_mutex_unlock(&adev->lock);
5369 lock_output_stream(usecase->stream.out);
5370 pthread_mutex_lock(&adev->lock);
5371 audio_extn_a2dp_set_handoff_mode(true);
5372 // force device switch to reconfigure encoder
5373 select_devices(adev, usecase->id);
5374 audio_extn_a2dp_set_handoff_mode(false);
5375 pthread_mutex_unlock(&usecase->stream.out->lock);
5376 break;
5377 }
5378 }
5379 }
5380
Eric Laurent5f4ca952018-10-19 17:33:43 -07005381 //FIXME: to be replaced by proper video capture properties API
5382 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
5383 if (ret >= 0) {
5384 int camera_facing = CAMERA_FACING_BACK;
5385 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
5386 camera_facing = CAMERA_FACING_FRONT;
5387 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
5388 camera_facing = CAMERA_FACING_BACK;
5389 else {
5390 ALOGW("%s: invalid camera facing value: %s", __func__, value);
5391 goto done;
5392 }
5393 adev->camera_orientation =
5394 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
5395 struct audio_usecase *usecase;
5396 struct listnode *node;
5397 list_for_each(node, &adev->usecase_list) {
5398 usecase = node_to_item(node, struct audio_usecase, list);
5399 struct stream_in *in = usecase->stream.in;
5400 if (usecase->type == PCM_CAPTURE && in != NULL &&
5401 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
5402 select_devices(adev, in->usecase);
5403 }
5404 }
5405 }
5406
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005407done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005408 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005409 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07005410 ALOGV("%s: exit with code(%d)", __func__, status);
5411 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005412}
5413
5414static char* adev_get_parameters(const struct audio_hw_device *dev,
5415 const char *keys)
5416{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005417 struct audio_device *adev = (struct audio_device *)dev;
5418 struct str_parms *reply = str_parms_create();
5419 struct str_parms *query = str_parms_create_str(keys);
5420 char *str;
5421
5422 pthread_mutex_lock(&adev->lock);
5423
5424 voice_get_parameters(adev, query, reply);
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005425 audio_extn_a2dp_get_parameters(query, reply);
5426
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005427 str = str_parms_to_str(reply);
5428 str_parms_destroy(query);
5429 str_parms_destroy(reply);
5430
5431 pthread_mutex_unlock(&adev->lock);
5432 ALOGV("%s: exit: returns - %s", __func__, str);
5433 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005434}
5435
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005436static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005437{
5438 return 0;
5439}
5440
Haynes Mathew George5191a852013-09-11 14:19:36 -07005441static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
5442{
5443 int ret;
5444 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005445
Eric Laurent4cc4ce12014-09-10 13:21:01 -05005446 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
5447
Haynes Mathew George5191a852013-09-11 14:19:36 -07005448 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005449 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07005450 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005451
Haynes Mathew George5191a852013-09-11 14:19:36 -07005452 return ret;
5453}
5454
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005455static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005456{
5457 return -ENOSYS;
5458}
5459
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005460static int adev_get_master_volume(struct audio_hw_device *dev __unused,
5461 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005462{
5463 return -ENOSYS;
5464}
5465
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005466static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005467{
5468 return -ENOSYS;
5469}
5470
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005471static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005472{
5473 return -ENOSYS;
5474}
5475
5476static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
5477{
5478 struct audio_device *adev = (struct audio_device *)dev;
5479
5480 pthread_mutex_lock(&adev->lock);
5481 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07005482 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005483 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07005484 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
5485 voice_is_in_call(adev)) {
5486 voice_stop_call(adev);
5487 adev->current_call_output = NULL;
HW Leef88584d2019-03-18 17:27:18 +08005488
5489 /*
5490 * After stopping the call, it must check if any active capture
5491 * activity device needs to be re-selected.
5492 */
5493 struct audio_usecase *usecase;
5494 struct listnode *node;
5495 list_for_each(node, &adev->usecase_list) {
5496 usecase = node_to_item(node, struct audio_usecase, list);
5497 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL) {
5498 select_devices_with_force_switch(adev, usecase->id, true);
5499 }
5500 }
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07005501 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005502 }
5503 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05005504
5505 audio_extn_extspk_set_mode(adev->extspk, mode);
5506
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005507 return 0;
5508}
5509
5510static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
5511{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005512 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005513 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005514
Eric Laurent2bafff12016-03-17 12:17:23 -07005515 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005516 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005517 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
5518 ret = audio_extn_hfp_set_mic_mute(adev, state);
5519 } else {
5520 ret = voice_set_mic_mute(adev, state);
5521 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07005522 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00005523 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005524
5525 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005526}
5527
5528static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
5529{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005530 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005531 return 0;
5532}
5533
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005534static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005535 const struct audio_config *config)
5536{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07005537 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005538
Eric Laurent74b55762017-07-09 17:04:53 -07005539 /* Don't know if USB HIFI in this context so use true to be conservative */
5540 if (check_input_parameters(config->sample_rate, config->format, channel_count,
5541 true /*is_usb_hifi */) != 0)
5542 return 0;
5543
vivek mehtaa68fea62017-06-08 19:04:02 -07005544 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5545 config->sample_rate, config->format,
5546 channel_count,
5547 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005548}
5549
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005550static bool adev_input_allow_hifi_record(struct audio_device *adev,
5551 audio_devices_t devices,
5552 audio_input_flags_t flags,
5553 audio_source_t source) {
5554 const bool allowed = true;
5555
5556 if (!audio_is_usb_in_device(devices))
5557 return !allowed;
5558
5559 switch (flags) {
5560 case AUDIO_INPUT_FLAG_NONE:
5561 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
5562 break;
5563 default:
5564 return !allowed;
5565 }
5566
5567 switch (source) {
5568 case AUDIO_SOURCE_DEFAULT:
5569 case AUDIO_SOURCE_MIC:
5570 case AUDIO_SOURCE_UNPROCESSED:
5571 break;
5572 default:
5573 return !allowed;
5574 }
5575
5576 switch (adev->mode) {
5577 case 0:
5578 break;
5579 default:
5580 return !allowed;
5581 }
5582
5583 return allowed;
5584}
5585
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005586static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005587 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005588 audio_devices_t devices,
5589 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005590 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07005591 audio_input_flags_t flags,
5592 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05005593 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005594{
5595 struct audio_device *adev = (struct audio_device *)dev;
5596 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005597 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07005598 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005599 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005600 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005601 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
5602 devices,
5603 flags,
5604 source);
Andy Hung88ce1d92018-10-29 18:31:12 -07005605 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
5606 " sample_rate %u, channel_mask %#x, format %#x",
5607 __func__, flags, is_usb_dev, may_use_hifi_record,
5608 config->sample_rate, config->channel_mask, config->format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005609 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005610
Andy Hungd9653bd2017-08-01 19:31:39 -07005611 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
5612 return -ENOSYS;
5613 }
5614
Eric Laurent74b55762017-07-09 17:04:53 -07005615 if (!(is_usb_dev && may_use_hifi_record)) {
5616 if (config->sample_rate == 0)
5617 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
5618 if (config->channel_mask == AUDIO_CHANNEL_NONE)
5619 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5620 if (config->format == AUDIO_FORMAT_DEFAULT)
5621 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005622
Eric Laurent74b55762017-07-09 17:04:53 -07005623 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
5624
5625 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
5626 return -EINVAL;
5627 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005628
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005629 if (audio_extn_tfa_98xx_is_supported() &&
5630 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005631 return -EINVAL;
5632
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005633 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
5634
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005635 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005636 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005637
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005638 in->stream.common.get_sample_rate = in_get_sample_rate;
5639 in->stream.common.set_sample_rate = in_set_sample_rate;
5640 in->stream.common.get_buffer_size = in_get_buffer_size;
5641 in->stream.common.get_channels = in_get_channels;
5642 in->stream.common.get_format = in_get_format;
5643 in->stream.common.set_format = in_set_format;
5644 in->stream.common.standby = in_standby;
5645 in->stream.common.dump = in_dump;
5646 in->stream.common.set_parameters = in_set_parameters;
5647 in->stream.common.get_parameters = in_get_parameters;
5648 in->stream.common.add_audio_effect = in_add_audio_effect;
5649 in->stream.common.remove_audio_effect = in_remove_audio_effect;
5650 in->stream.set_gain = in_set_gain;
5651 in->stream.read = in_read;
5652 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08005653 in->stream.get_capture_position = in_get_capture_position;
jiabin8962a4d2018-03-19 18:21:24 -07005654 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLean57530d52018-12-17 08:24:21 -07005655 in->stream.set_microphone_direction = in_set_microphone_direction;
5656 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchenba338cd2019-01-21 11:57:17 +08005657 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005658
5659 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005660 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005661 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005662 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005663 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005664 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005665
Andy Hung88ce1d92018-10-29 18:31:12 -07005666 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Arun Mirpuriba2749a2018-04-17 14:32:24 -07005667 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
5668 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
5669 /* Force channel config requested to mono if incall
5670 record is being requested for only uplink/downlink */
5671 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
5672 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5673 ret = -EINVAL;
5674 goto err_open;
5675 }
5676 }
5677
Haynes Mathew George569b7482017-05-08 14:44:27 -07005678 if (is_usb_dev && may_use_hifi_record) {
5679 /* HiFi record selects an appropriate format, channel, rate combo
5680 depending on sink capabilities*/
5681 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
5682 &config->format,
5683 &in->supported_formats[0],
5684 MAX_SUPPORTED_FORMATS,
5685 &config->channel_mask,
5686 &in->supported_channel_masks[0],
5687 MAX_SUPPORTED_CHANNEL_MASKS,
5688 &config->sample_rate,
5689 &in->supported_sample_rates[0],
5690 MAX_SUPPORTED_SAMPLE_RATES);
5691 if (ret != 0) {
5692 ret = -EINVAL;
5693 goto err_open;
5694 }
Eric Laurent74b55762017-07-09 17:04:53 -07005695 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005696 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07005697 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07005698 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
5699 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
5700 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5701 bool ret_error = false;
5702 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5703 from HAL is 8_24
5704 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5705 8_24 return error indicating supported format is 8_24
5706 *> In case of any other source requesting 24 bit or float return error
5707 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07005708
vivek mehta57ff9b52016-04-28 14:13:08 -07005709 on error flinger will retry with supported format passed
5710 */
juyuchenbe5c67e2018-08-29 17:19:20 +08005711 if (!is_supported_24bits_audiosource(source)) {
vivek mehta57ff9b52016-04-28 14:13:08 -07005712 config->format = AUDIO_FORMAT_PCM_16_BIT;
5713 ret_error = true;
5714 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
5715 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
5716 ret_error = true;
5717 }
5718
5719 if (ret_error) {
5720 ret = -EINVAL;
5721 goto err_open;
5722 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005723 }
5724
vivek mehta57ff9b52016-04-28 14:13:08 -07005725 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07005726 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07005727
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005728 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005729 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
5730 if (config->sample_rate == 0)
5731 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5732 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5733 config->sample_rate != 8000) {
5734 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5735 ret = -EINVAL;
5736 goto err_open;
5737 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005738
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005739 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5740 config->format = AUDIO_FORMAT_PCM_16_BIT;
5741 ret = -EINVAL;
5742 goto err_open;
5743 }
5744
5745 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5746 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07005747 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005748 } else if (is_usb_dev && may_use_hifi_record) {
5749 in->usecase = USECASE_AUDIO_RECORD_HIFI;
5750 in->config = pcm_config_audio_capture;
5751 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005752 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5753 config->sample_rate,
5754 config->format,
5755 channel_count,
5756 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005757 in->config.period_size = buffer_size / frame_size;
5758 in->config.rate = config->sample_rate;
5759 in->af_period_multiplier = 1;
5760 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005761 } else {
5762 in->usecase = USECASE_AUDIO_RECORD;
5763 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08005764 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005765 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07005766#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005767 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07005768#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08005769 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005770 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08005771 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005772 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005773 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5774 config->sample_rate,
5775 config->format,
5776 channel_count,
5777 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005778 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005779 in->config.rate = config->sample_rate;
5780 in->af_period_multiplier = 1;
5781 } else {
5782 // period size is left untouched for rt mode playback
5783 in->config = pcm_config_audio_capture_rt;
5784 in->af_period_multiplier = af_period_multiplier;
5785 }
5786 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
5787 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005788 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08005789 in->usecase = USECASE_AUDIO_RECORD_MMAP;
5790 in->config = pcm_config_mmap_capture;
5791 in->stream.start = in_start;
5792 in->stream.stop = in_stop;
5793 in->stream.create_mmap_buffer = in_create_mmap_buffer;
5794 in->stream.get_mmap_position = in_get_mmap_position;
5795 in->af_period_multiplier = 1;
5796 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07005797 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07005798 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07005799 (config->sample_rate == 8000 ||
5800 config->sample_rate == 16000 ||
5801 config->sample_rate == 32000 ||
5802 config->sample_rate == 48000) &&
5803 channel_count == 1) {
5804 in->usecase = USECASE_AUDIO_RECORD_VOIP;
5805 in->config = pcm_config_audio_capture;
5806 frame_size = audio_stream_in_frame_size(&in->stream);
5807 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
5808 config->sample_rate,
5809 config->format,
5810 channel_count, false /*is_low_latency*/);
5811 in->config.period_size = buffer_size / frame_size;
5812 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
5813 in->config.rate = config->sample_rate;
5814 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005815 } else {
5816 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005817 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005818 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5819 config->sample_rate,
5820 config->format,
5821 channel_count,
5822 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005823 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005824 in->config.rate = config->sample_rate;
5825 in->af_period_multiplier = 1;
5826 }
5827 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
5828 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005829 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08005830
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005831 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07005832 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005833
Kevin Rocarda325aa22018-04-03 09:15:52 -07005834
5835 register_format(in->format, in->supported_formats);
5836 register_channel_mask(in->channel_mask, in->supported_channel_masks);
5837 register_sample_rate(in->sample_rate, in->supported_sample_rates);
5838
Andy Hungd13f0d32017-06-12 13:58:37 -07005839 in->error_log = error_log_create(
5840 ERROR_LOG_ENTRIES,
5841 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
5842
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005843 /* This stream could be for sound trigger lab,
5844 get sound trigger pcm if present */
5845 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005846
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005847 lock_input_stream(in);
5848 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5849 pthread_mutex_lock(&adev->lock);
5850 in->card_status = adev->card_status;
5851 pthread_mutex_unlock(&adev->lock);
5852 pthread_mutex_unlock(&in->lock);
5853
vivek mehta4a824772017-06-08 19:05:49 -07005854 stream_app_type_cfg_init(&in->app_type_cfg);
5855
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005856 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005857 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005858 return 0;
5859
5860err_open:
5861 free(in);
5862 *stream_in = NULL;
5863 return ret;
5864}
5865
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005866static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005867 struct audio_stream_in *stream)
5868{
Andy Hungd13f0d32017-06-12 13:58:37 -07005869 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005870 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005871
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005872 // must deregister from sndmonitor first to prevent races
5873 // between the callback and close_stream
5874 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005875 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07005876
5877 error_log_destroy(in->error_log);
5878 in->error_log = NULL;
5879
Andy Hung0dbb52b2017-08-09 13:51:38 -07005880 pthread_mutex_destroy(&in->pre_lock);
5881 pthread_mutex_destroy(&in->lock);
5882
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005883 free(stream);
5884
5885 return;
5886}
5887
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005888static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005889{
5890 return 0;
5891}
5892
Andy Hung31aca912014-03-20 17:14:59 -07005893/* verifies input and output devices and their capabilities.
5894 *
5895 * This verification is required when enabling extended bit-depth or
5896 * sampling rates, as not all qcom products support it.
5897 *
5898 * Suitable for calling only on initialization such as adev_open().
5899 * It fills the audio_device use_case_table[] array.
5900 *
5901 * Has a side-effect that it needs to configure audio routing / devices
5902 * in order to power up the devices and read the device parameters.
5903 * It does not acquire any hw device lock. Should restore the devices
5904 * back to "normal state" upon completion.
5905 */
5906static int adev_verify_devices(struct audio_device *adev)
5907{
5908 /* enumeration is a bit difficult because one really wants to pull
5909 * the use_case, device id, etc from the hidden pcm_device_table[].
5910 * In this case there are the following use cases and device ids.
5911 *
5912 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
5913 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005914 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07005915 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
5916 * [USECASE_AUDIO_RECORD] = {0, 0},
5917 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
5918 * [USECASE_VOICE_CALL] = {2, 2},
5919 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005920 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07005921 * USECASE_VOICE_CALL omitted, but possible for either input or output.
5922 */
5923
5924 /* should be the usecases enabled in adev_open_input_stream() */
5925 static const int test_in_usecases[] = {
5926 USECASE_AUDIO_RECORD,
5927 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
5928 };
5929 /* should be the usecases enabled in adev_open_output_stream()*/
5930 static const int test_out_usecases[] = {
5931 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
5932 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
5933 };
5934 static const usecase_type_t usecase_type_by_dir[] = {
5935 PCM_PLAYBACK,
5936 PCM_CAPTURE,
5937 };
5938 static const unsigned flags_by_dir[] = {
5939 PCM_OUT,
5940 PCM_IN,
5941 };
5942
5943 size_t i;
5944 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005945 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07005946 char info[512]; /* for possible debug info */
5947
5948 for (dir = 0; dir < 2; ++dir) {
5949 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
5950 const unsigned flags_dir = flags_by_dir[dir];
5951 const size_t testsize =
5952 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
5953 const int *testcases =
5954 dir ? test_in_usecases : test_out_usecases;
5955 const audio_devices_t audio_device =
5956 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
5957
5958 for (i = 0; i < testsize; ++i) {
5959 const audio_usecase_t audio_usecase = testcases[i];
5960 int device_id;
5961 snd_device_t snd_device;
5962 struct pcm_params **pparams;
5963 struct stream_out out;
5964 struct stream_in in;
5965 struct audio_usecase uc_info;
5966 int retval;
5967
5968 pparams = &adev->use_case_table[audio_usecase];
5969 pcm_params_free(*pparams); /* can accept null input */
5970 *pparams = NULL;
5971
5972 /* find the device ID for the use case (signed, for error) */
5973 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
5974 if (device_id < 0)
5975 continue;
5976
5977 /* prepare structures for device probing */
5978 memset(&uc_info, 0, sizeof(uc_info));
5979 uc_info.id = audio_usecase;
5980 uc_info.type = usecase_type;
5981 if (dir) {
Andy Hung31aca912014-03-20 17:14:59 -07005982 memset(&in, 0, sizeof(in));
5983 in.device = audio_device;
5984 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
5985 uc_info.stream.in = &in;
Andy Hung31aca912014-03-20 17:14:59 -07005986 }
5987 memset(&out, 0, sizeof(out));
5988 out.devices = audio_device; /* only field needed in select_devices */
5989 uc_info.stream.out = &out;
5990 uc_info.devices = audio_device;
5991 uc_info.in_snd_device = SND_DEVICE_NONE;
5992 uc_info.out_snd_device = SND_DEVICE_NONE;
5993 list_add_tail(&adev->usecase_list, &uc_info.list);
5994
5995 /* select device - similar to start_(in/out)put_stream() */
5996 retval = select_devices(adev, audio_usecase);
5997 if (retval >= 0) {
5998 *pparams = pcm_params_get(card_id, device_id, flags_dir);
5999#if LOG_NDEBUG == 0
6000 if (*pparams) {
6001 ALOGV("%s: (%s) card %d device %d", __func__,
6002 dir ? "input" : "output", card_id, device_id);
6003 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07006004 } else {
6005 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
6006 }
6007#endif
6008 }
6009
6010 /* deselect device - similar to stop_(in/out)put_stream() */
6011 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07006012 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07006013 /* 2. Disable the rx device */
6014 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07006015 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07006016 list_remove(&uc_info.list);
6017 }
6018 }
Andy Hung31aca912014-03-20 17:14:59 -07006019 return 0;
6020}
6021
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006022static int adev_close(hw_device_t *device)
6023{
Andy Hung31aca912014-03-20 17:14:59 -07006024 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006025 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006026
6027 if (!adev)
6028 return 0;
6029
6030 pthread_mutex_lock(&adev_init_lock);
6031
6032 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07006033 audio_extn_snd_mon_unregister_listener(adev);
6034 audio_extn_tfa_98xx_deinit();
jasmine cha270b7762018-03-30 15:41:33 +08006035 audio_extn_ma_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07006036 audio_route_free(adev->audio_route);
6037 free(adev->snd_dev_ref_cnt);
6038 platform_deinit(adev->platform);
6039 audio_extn_extspk_deinit(adev->extspk);
6040 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07006041 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07006042 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
6043 pcm_params_free(adev->use_case_table[i]);
6044 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006045 if (adev->adm_deinit)
6046 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07006047 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07006048 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07006049 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07006050
6051 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006052
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006053 return 0;
6054}
6055
Glenn Kasten4f993392014-05-14 07:30:48 -07006056/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
6057 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
6058 * just that it _might_ work.
6059 */
6060static int period_size_is_plausible_for_low_latency(int period_size)
6061{
6062 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07006063 case 48:
6064 case 96:
6065 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07006066 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07006067 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07006068 case 240:
6069 case 320:
6070 case 480:
6071 return 1;
6072 default:
6073 return 0;
6074 }
6075}
6076
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07006077static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
6078{
6079 int card;
6080 card_status_t status;
6081
6082 if (!parms)
6083 return;
6084
6085 if (parse_snd_card_status(parms, &card, &status) < 0)
6086 return;
6087
6088 pthread_mutex_lock(&adev->lock);
6089 bool valid_cb = (card == adev->snd_card);
6090 if (valid_cb) {
6091 if (adev->card_status != status) {
6092 adev->card_status = status;
6093 platform_snd_card_update(adev->platform, status);
6094 }
6095 }
6096 pthread_mutex_unlock(&adev->lock);
6097 return;
6098}
6099
Aniket Kumar Lata26483012018-01-31 20:21:42 -08006100/* out and adev lock held */
6101static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
6102{
6103 struct audio_usecase *uc_info;
6104 float left_p;
6105 float right_p;
6106 audio_devices_t devices;
6107
6108 uc_info = get_usecase_from_list(adev, out->usecase);
6109 if (uc_info == NULL) {
6110 ALOGE("%s: Could not find the usecase (%d) in the list",
6111 __func__, out->usecase);
6112 return -EINVAL;
6113 }
6114
6115 ALOGD("%s: enter: usecase(%d: %s)", __func__,
6116 out->usecase, use_case_table[out->usecase]);
6117
6118 if (restore) {
6119 // restore A2DP device for active usecases and unmute if required
6120 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
6121 !is_a2dp_device(uc_info->out_snd_device)) {
6122 ALOGD("%s: restoring A2DP and unmuting stream", __func__);
6123 select_devices(adev, uc_info->id);
6124 pthread_mutex_lock(&out->compr_mute_lock);
6125 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6126 (out->a2dp_compress_mute)) {
6127 out->a2dp_compress_mute = false;
6128 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
6129 }
6130 pthread_mutex_unlock(&out->compr_mute_lock);
6131 }
6132 } else {
6133 // mute compress stream if suspended
6134 pthread_mutex_lock(&out->compr_mute_lock);
6135 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6136 (!out->a2dp_compress_mute)) {
6137 if (!out->standby) {
6138 ALOGD("%s: selecting speaker and muting stream", __func__);
6139 devices = out->devices;
6140 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
6141 left_p = out->volume_l;
6142 right_p = out->volume_r;
6143 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6144 compress_pause(out->compr);
6145 set_compr_volume(&out->stream, 0.0f, 0.0f);
6146 out->a2dp_compress_mute = true;
6147 select_devices(adev, out->usecase);
6148 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6149 compress_resume(out->compr);
6150 out->devices = devices;
6151 out->volume_l = left_p;
6152 out->volume_r = right_p;
6153 }
6154 }
6155 pthread_mutex_unlock(&out->compr_mute_lock);
6156 }
6157 ALOGV("%s: exit", __func__);
6158 return 0;
6159}
6160
6161int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
6162{
6163 int ret = 0;
6164
6165 lock_output_stream(out);
6166 pthread_mutex_lock(&adev->lock);
6167
6168 ret = check_a2dp_restore_l(adev, out, restore);
6169
6170 pthread_mutex_unlock(&adev->lock);
6171 pthread_mutex_unlock(&out->lock);
6172 return ret;
6173}
6174
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006175static int adev_open(const hw_module_t *module, const char *name,
6176 hw_device_t **device)
6177{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07006178 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006179
Eric Laurent2bafff12016-03-17 12:17:23 -07006180 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006181 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006182 pthread_mutex_lock(&adev_init_lock);
6183 if (audio_device_ref_count != 0) {
6184 *device = &adev->device.common;
6185 audio_device_ref_count++;
6186 ALOGV("%s: returning existing instance of adev", __func__);
6187 ALOGV("%s: exit", __func__);
6188 pthread_mutex_unlock(&adev_init_lock);
6189 return 0;
6190 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006191 adev = calloc(1, sizeof(struct audio_device));
6192
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07006193 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
6194
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006195 adev->device.common.tag = HARDWARE_DEVICE_TAG;
6196 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
6197 adev->device.common.module = (struct hw_module_t *)module;
6198 adev->device.common.close = adev_close;
6199
6200 adev->device.init_check = adev_init_check;
6201 adev->device.set_voice_volume = adev_set_voice_volume;
6202 adev->device.set_master_volume = adev_set_master_volume;
6203 adev->device.get_master_volume = adev_get_master_volume;
6204 adev->device.set_master_mute = adev_set_master_mute;
6205 adev->device.get_master_mute = adev_get_master_mute;
6206 adev->device.set_mode = adev_set_mode;
6207 adev->device.set_mic_mute = adev_set_mic_mute;
6208 adev->device.get_mic_mute = adev_get_mic_mute;
6209 adev->device.set_parameters = adev_set_parameters;
6210 adev->device.get_parameters = adev_get_parameters;
6211 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
6212 adev->device.open_output_stream = adev_open_output_stream;
6213 adev->device.close_output_stream = adev_close_output_stream;
6214 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08006215
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006216 adev->device.close_input_stream = adev_close_input_stream;
6217 adev->device.dump = adev_dump;
jiabin8962a4d2018-03-19 18:21:24 -07006218 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006219
6220 /* Set the default route before the PCM stream is opened */
6221 pthread_mutex_lock(&adev->lock);
6222 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006223 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006224 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08006225 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07006226 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07006227 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07006228 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08006229 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006230 pthread_mutex_unlock(&adev->lock);
6231
6232 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07006233 adev->platform = platform_init(adev);
6234 if (!adev->platform) {
6235 free(adev->snd_dev_ref_cnt);
6236 free(adev);
6237 ALOGE("%s: Failed to init platform data, aborting.", __func__);
6238 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006239 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07006240 return -EINVAL;
6241 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05006242 adev->extspk = audio_extn_extspk_init(adev);
6243
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006244 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
6245 if (adev->visualizer_lib == NULL) {
6246 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
6247 } else {
6248 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
6249 adev->visualizer_start_output =
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07006250 (int (*)(audio_io_handle_t, int, int, int))dlsym(adev->visualizer_lib,
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006251 "visualizer_hal_start_output");
6252 adev->visualizer_stop_output =
6253 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
6254 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07006255 }
6256
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006257 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
6258 if (adev->offload_effects_lib == NULL) {
6259 ALOGW("%s: DLOPEN failed for %s", __func__,
6260 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6261 } else {
6262 ALOGV("%s: DLOPEN successful for %s", __func__,
6263 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6264 adev->offload_effects_start_output =
6265 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
6266 "offload_effects_bundle_hal_start_output");
6267 adev->offload_effects_stop_output =
6268 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
6269 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07006270 }
6271
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006272 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
6273 if (adev->adm_lib == NULL) {
6274 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
6275 } else {
6276 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
6277 adev->adm_init = (adm_init_t)
6278 dlsym(adev->adm_lib, "adm_init");
6279 adev->adm_deinit = (adm_deinit_t)
6280 dlsym(adev->adm_lib, "adm_deinit");
6281 adev->adm_register_input_stream = (adm_register_input_stream_t)
6282 dlsym(adev->adm_lib, "adm_register_input_stream");
6283 adev->adm_register_output_stream = (adm_register_output_stream_t)
6284 dlsym(adev->adm_lib, "adm_register_output_stream");
6285 adev->adm_deregister_stream = (adm_deregister_stream_t)
6286 dlsym(adev->adm_lib, "adm_deregister_stream");
6287 adev->adm_request_focus = (adm_request_focus_t)
6288 dlsym(adev->adm_lib, "adm_request_focus");
6289 adev->adm_abandon_focus = (adm_abandon_focus_t)
6290 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08006291 adev->adm_set_config = (adm_set_config_t)
6292 dlsym(adev->adm_lib, "adm_set_config");
6293 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
6294 dlsym(adev->adm_lib, "adm_request_focus_v2");
6295 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
6296 dlsym(adev->adm_lib, "adm_is_noirq_avail");
6297 adev->adm_on_routing_change = (adm_on_routing_change_t)
6298 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006299 }
6300
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07006301 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05006302 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07006303
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006304 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006305
Andy Hung31aca912014-03-20 17:14:59 -07006306 if (k_enable_extended_precision)
6307 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006308
Glenn Kasten4f993392014-05-14 07:30:48 -07006309 char value[PROPERTY_VALUE_MAX];
6310 int trial;
6311 if (property_get("audio_hal.period_size", value, NULL) > 0) {
6312 trial = atoi(value);
6313 if (period_size_is_plausible_for_low_latency(trial)) {
6314 pcm_config_low_latency.period_size = trial;
6315 pcm_config_low_latency.start_threshold = trial / 4;
6316 pcm_config_low_latency.avail_min = trial / 4;
6317 configured_low_latency_capture_period_size = trial;
6318 }
6319 }
6320 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
6321 trial = atoi(value);
6322 if (period_size_is_plausible_for_low_latency(trial)) {
6323 configured_low_latency_capture_period_size = trial;
6324 }
6325 }
6326
Vignesh Kulothunganb6f0a9c2018-03-22 13:50:22 -07006327 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
6328
Eric Laurent5f4ca952018-10-19 17:33:43 -07006329 adev->camera_orientation = CAMERA_DEFAULT;
6330
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08006331 // commented as full set of app type cfg is sent from platform
6332 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07006333 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08006334
6335 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
6336 af_period_multiplier = atoi(value);
6337 if (af_period_multiplier < 0) {
6338 af_period_multiplier = 2;
6339 } else if (af_period_multiplier > 4) {
6340 af_period_multiplier = 4;
6341 }
6342 ALOGV("new period_multiplier = %d", af_period_multiplier);
6343 }
6344
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08006345 audio_extn_tfa_98xx_init(adev);
jasmine cha270b7762018-03-30 15:41:33 +08006346 audio_extn_ma_init(adev->platform);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08006347
vivek mehta1a9b7c02015-06-25 11:49:38 -07006348 pthread_mutex_unlock(&adev_init_lock);
6349
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006350 if (adev->adm_init)
6351 adev->adm_data = adev->adm_init();
6352
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07006353 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07006354 audio_extn_snd_mon_init();
6355 pthread_mutex_lock(&adev->lock);
6356 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
6357 adev->card_status = CARD_STATUS_ONLINE;
6358 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07006359 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07006360
Eric Laurent2bafff12016-03-17 12:17:23 -07006361 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006362 return 0;
6363}
6364
6365static struct hw_module_methods_t hal_module_methods = {
6366 .open = adev_open,
6367};
6368
6369struct audio_module HAL_MODULE_INFO_SYM = {
6370 .common = {
6371 .tag = HARDWARE_MODULE_TAG,
6372 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
6373 .hal_api_version = HARDWARE_HAL_API_VERSION,
6374 .id = AUDIO_HARDWARE_MODULE_ID,
6375 .name = "QCOM Audio HAL",
6376 .author = "Code Aurora Forum",
6377 .methods = &hal_module_methods,
6378 },
6379};