blob: 24d726f4254d1762ccf0adf8ac60f26167f14311 [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>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080043
Eric Laurentb23d5282013-05-14 15:27:20 -070044#include <hardware/audio_effect.h>
Andy Hung31aca912014-03-20 17:14:59 -070045#include <hardware/audio_alsaops.h>
Suren Baghdasaryan7f924c22018-12-21 15:07:18 -080046#include <processgroup/sched_policy.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070047#include <system/thread_defs.h>
Phil Burkbc991042017-02-24 08:06:44 -080048#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070049#include <audio_effects/effect_aec.h>
50#include <audio_effects/effect_ns.h>
Andy Hungfc044e12017-03-20 09:24:22 -070051#include <audio_utils/clock.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052#include "audio_hw.h"
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -080053#include "audio_extn.h"
Wei Wangf4837d52017-11-21 14:51:20 -080054#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070055#include "platform_api.h"
56#include <platform.h>
Vineeta Srivastava4b89e372014-06-19 14:21:42 -070057#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080058
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070059#include "sound/compress_params.h"
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -080060#include "audio_extn/tfa_98xx.h"
jasmine cha270b7762018-03-30 15:41:33 +080061#include "audio_extn/maxxaudio.h"
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062
Eric Laurent397db572016-05-11 11:31:47 -070063/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
64 * COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
Marco Nelissen32093f52015-04-08 15:14:02 -070065#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070066// 2 buffers causes problems with high bitrate files
67#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070068/* ToDo: Check and update a proper value in msec */
69#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
vivek mehta4a824772017-06-08 19:05:49 -070070/* treat as unsigned Q1.13 */
71#define APP_TYPE_GAIN_DEFAULT 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070072#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
vivek mehta4a824772017-06-08 19:05:49 -070073
74/* treat as unsigned Q1.13 */
vivek mehtaa68fea62017-06-08 19:04:02 -070075#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076
Eric Laurent51f3c662018-04-10 18:21:34 -070077#define RECORD_GAIN_MIN 0.0f
78#define RECORD_GAIN_MAX 1.0f
79#define RECORD_VOLUME_CTL_MAX 0x2000
80
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070081#define PROXY_OPEN_RETRY_COUNT 100
82#define PROXY_OPEN_WAIT_TIME 20
83
vivek mehtadae44712015-07-27 14:13:18 -070084#define MIN_CHANNEL_COUNT 1
85#define DEFAULT_CHANNEL_COUNT 2
86
Jean-Michel Trivic0750692015-10-12 12:12:32 -070087#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
88#define MAX_CHANNEL_COUNT 1
89#else
vivek mehtadae44712015-07-27 14:13:18 -070090#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
91#define XSTR(x) STR(x)
92#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070093#endif
Eric Laurent74b55762017-07-09 17:04:53 -070094#define MAX_HIFI_CHANNEL_COUNT 8
vivek mehtadae44712015-07-27 14:13:18 -070095
Haynes Mathew George03c40102016-01-29 17:57:48 -080096#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
97
Glenn Kasten4f993392014-05-14 07:30:48 -070098static unsigned int configured_low_latency_capture_period_size =
99 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
100
Eric Laurent0e46adf2016-12-16 12:49:24 -0800101
102#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Phil Burkbc991042017-02-24 08:06:44 -0800103#define MMAP_PERIOD_COUNT_MIN 32
104#define MMAP_PERIOD_COUNT_MAX 512
105#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
Eric Laurent0e46adf2016-12-16 12:49:24 -0800106
Andy Hung31aca912014-03-20 17:14:59 -0700107/* This constant enables extended precision handling.
108 * TODO The flag is off until more testing is done.
109 */
110static const bool k_enable_extended_precision = false;
111
Eric Laurentb23d5282013-05-14 15:27:20 -0700112struct pcm_config pcm_config_deep_buffer = {
vivek mehtadae44712015-07-27 14:13:18 -0700113 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700114 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
115 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
116 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
117 .format = PCM_FORMAT_S16_LE,
118 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
119 .stop_threshold = INT_MAX,
120 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
121};
122
123struct pcm_config pcm_config_low_latency = {
vivek mehtadae44712015-07-27 14:13:18 -0700124 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700125 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
126 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
127 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
128 .format = PCM_FORMAT_S16_LE,
129 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
130 .stop_threshold = INT_MAX,
131 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
132};
133
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -0800134struct pcm_config pcm_config_haptics_audio = {
135 .channels = 1,
136 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
137 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
138 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
139 .format = PCM_FORMAT_S16_LE,
140 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
141 .stop_threshold = INT_MAX,
142 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
143};
144
145struct pcm_config pcm_config_haptics = {
146 .channels = 1,
147 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
148 .period_count = 2,
149 .format = PCM_FORMAT_S16_LE,
150 .stop_threshold = INT_MAX,
151 .avail_min = 0,
152};
153
Haynes Mathew George03c40102016-01-29 17:57:48 -0800154static int af_period_multiplier = 4;
155struct pcm_config pcm_config_rt = {
156 .channels = DEFAULT_CHANNEL_COUNT,
157 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
158 .period_size = ULL_PERIOD_SIZE, //1 ms
159 .period_count = 512, //=> buffer size is 512ms
160 .format = PCM_FORMAT_S16_LE,
161 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
162 .stop_threshold = INT_MAX,
163 .silence_threshold = 0,
164 .silence_size = 0,
165 .avail_min = ULL_PERIOD_SIZE, //1 ms
166};
167
Eric Laurentb23d5282013-05-14 15:27:20 -0700168struct pcm_config pcm_config_hdmi_multi = {
169 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
170 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
171 .period_size = HDMI_MULTI_PERIOD_SIZE,
172 .period_count = HDMI_MULTI_PERIOD_COUNT,
173 .format = PCM_FORMAT_S16_LE,
174 .start_threshold = 0,
175 .stop_threshold = INT_MAX,
176 .avail_min = 0,
177};
178
Eric Laurent0e46adf2016-12-16 12:49:24 -0800179struct pcm_config pcm_config_mmap_playback = {
180 .channels = DEFAULT_CHANNEL_COUNT,
181 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
182 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800183 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800184 .format = PCM_FORMAT_S16_LE,
185 .start_threshold = MMAP_PERIOD_SIZE*8,
186 .stop_threshold = INT32_MAX,
187 .silence_threshold = 0,
188 .silence_size = 0,
189 .avail_min = MMAP_PERIOD_SIZE, //1 ms
190};
191
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800192struct pcm_config pcm_config_hifi = {
193 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
194 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
195 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
196 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
197 .format = PCM_FORMAT_S24_3LE,
198 .start_threshold = 0,
199 .stop_threshold = INT_MAX,
200 .avail_min = 0,
201};
202
Eric Laurentb23d5282013-05-14 15:27:20 -0700203struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700204 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700205 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
206 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700207 .stop_threshold = INT_MAX,
208 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700209};
210
Haynes Mathew George03c40102016-01-29 17:57:48 -0800211struct pcm_config pcm_config_audio_capture_rt = {
212 .channels = DEFAULT_CHANNEL_COUNT,
213 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
214 .period_size = ULL_PERIOD_SIZE,
215 .period_count = 512,
216 .format = PCM_FORMAT_S16_LE,
217 .start_threshold = 0,
218 .stop_threshold = INT_MAX,
219 .silence_threshold = 0,
220 .silence_size = 0,
221 .avail_min = ULL_PERIOD_SIZE, //1 ms
222};
223
Eric Laurent0e46adf2016-12-16 12:49:24 -0800224struct pcm_config pcm_config_mmap_capture = {
225 .channels = DEFAULT_CHANNEL_COUNT,
226 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
227 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800228 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800229 .format = PCM_FORMAT_S16_LE,
230 .start_threshold = 0,
231 .stop_threshold = INT_MAX,
232 .silence_threshold = 0,
233 .silence_size = 0,
234 .avail_min = MMAP_PERIOD_SIZE, //1 ms
235};
236
vivek mehtaa68fea62017-06-08 19:04:02 -0700237struct pcm_config pcm_config_voip = {
238 .channels = 1,
239 .period_count = 2,
240 .format = PCM_FORMAT_S16_LE,
241 .stop_threshold = INT_MAX,
242 .avail_min = 0,
243};
244
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700245#define AFE_PROXY_CHANNEL_COUNT 2
246#define AFE_PROXY_SAMPLING_RATE 48000
247
jiabinad481a72018-07-23 12:03:17 -0700248#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 256
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700249#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
250
251struct pcm_config pcm_config_afe_proxy_playback = {
252 .channels = AFE_PROXY_CHANNEL_COUNT,
253 .rate = AFE_PROXY_SAMPLING_RATE,
254 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
255 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
256 .format = PCM_FORMAT_S16_LE,
257 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
258 .stop_threshold = INT_MAX,
259 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
260};
261
jiabinad481a72018-07-23 12:03:17 -0700262#define AFE_PROXY_RECORD_PERIOD_SIZE 256
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700263#define AFE_PROXY_RECORD_PERIOD_COUNT 4
264
265struct pcm_config pcm_config_afe_proxy_record = {
266 .channels = AFE_PROXY_CHANNEL_COUNT,
267 .rate = AFE_PROXY_SAMPLING_RATE,
268 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
269 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
270 .format = PCM_FORMAT_S16_LE,
271 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
jiabin5d0261e2018-05-25 09:43:59 -0700272 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700273 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
274};
275
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700276const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700277 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
278 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -0800279 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800280 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700281 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700282 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700283 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800284 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700285
Eric Laurentb23d5282013-05-14 15:27:20 -0700286 [USECASE_AUDIO_RECORD] = "audio-record",
287 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800288 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George569b7482017-05-08 14:44:27 -0700289 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700290
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800291 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
292 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700293
Eric Laurentb23d5282013-05-14 15:27:20 -0700294 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700295 [USECASE_VOICE2_CALL] = "voice2-call",
296 [USECASE_VOLTE_CALL] = "volte-call",
297 [USECASE_QCHAT_CALL] = "qchat-call",
298 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800299 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
300 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700301
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700302 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
303 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
304
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700305 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
306 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
vivek mehta781065c2017-04-04 12:55:01 -0700307
308 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
309 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
310 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
311
vivek mehtaa68fea62017-06-08 19:04:02 -0700312 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
313 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Nadav Bar3d72cfc2018-01-07 12:19:24 +0200314
315 [USECASE_INCALL_MUSIC_UPLINK] = "incall-music-uplink",
Aniket Kumar Lata99546312018-03-19 21:38:38 -0700316
317 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700318};
319
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800320
321#define STRING_TO_ENUM(string) { #string, string }
322
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800323struct string_to_enum {
324 const char *name;
325 uint32_t value;
326};
327
Haynes Mathew George569b7482017-05-08 14:44:27 -0700328static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800329 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
330 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
331 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Eric Laurent74b55762017-07-09 17:04:53 -0700332 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
Haynes Mathew George569b7482017-05-08 14:44:27 -0700333 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
Eric Laurent74b55762017-07-09 17:04:53 -0700334 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
335 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
336 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
337 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
338 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
339 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
340 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
341 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
342 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800343};
344
Haynes Mathew George5191a852013-09-11 14:19:36 -0700345static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700346static struct audio_device *adev = NULL;
Andy Hung9e737de2017-05-22 10:51:22 -0700347static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700348static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700349//cache last MBDRC cal step level
350static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700351
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800352static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
353static int set_compr_volume(struct audio_stream_out *stream, float left, float right);
354
Haynes Mathew George03c40102016-01-29 17:57:48 -0800355static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
356 int flags __unused)
357{
358 int dir = 0;
359 switch (uc_id) {
360 case USECASE_AUDIO_RECORD_LOW_LATENCY:
361 dir = 1;
362 case USECASE_AUDIO_PLAYBACK_ULL:
363 break;
364 default:
365 return false;
366 }
367
368 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
369 PCM_PLAYBACK : PCM_CAPTURE);
370 if (adev->adm_is_noirq_avail)
371 return adev->adm_is_noirq_avail(adev->adm_data,
372 adev->snd_card, dev_id, dir);
373 return false;
374}
375
376static void register_out_stream(struct stream_out *out)
377{
378 struct audio_device *adev = out->dev;
379 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
380 return;
381
382 if (!adev->adm_register_output_stream)
383 return;
384
385 adev->adm_register_output_stream(adev->adm_data,
386 out->handle,
387 out->flags);
388
389 if (!adev->adm_set_config)
390 return;
391
392 if (out->realtime) {
393 adev->adm_set_config(adev->adm_data,
394 out->handle,
395 out->pcm, &out->config);
396 }
397}
398
399static void register_in_stream(struct stream_in *in)
400{
401 struct audio_device *adev = in->dev;
402 if (!adev->adm_register_input_stream)
403 return;
404
405 adev->adm_register_input_stream(adev->adm_data,
406 in->capture_handle,
407 in->flags);
408
409 if (!adev->adm_set_config)
410 return;
411
412 if (in->realtime) {
413 adev->adm_set_config(adev->adm_data,
414 in->capture_handle,
415 in->pcm,
416 &in->config);
417 }
418}
419
420static void request_out_focus(struct stream_out *out, long ns)
421{
422 struct audio_device *adev = out->dev;
423
Haynes Mathew George03c40102016-01-29 17:57:48 -0800424 if (adev->adm_request_focus_v2) {
425 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
426 } else if (adev->adm_request_focus) {
427 adev->adm_request_focus(adev->adm_data, out->handle);
428 }
429}
430
431static void request_in_focus(struct stream_in *in, long ns)
432{
433 struct audio_device *adev = in->dev;
434
Haynes Mathew George03c40102016-01-29 17:57:48 -0800435 if (adev->adm_request_focus_v2) {
436 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
437 } else if (adev->adm_request_focus) {
438 adev->adm_request_focus(adev->adm_data, in->capture_handle);
439 }
440}
441
442static void release_out_focus(struct stream_out *out, long ns __unused)
443{
444 struct audio_device *adev = out->dev;
445
446 if (adev->adm_abandon_focus)
447 adev->adm_abandon_focus(adev->adm_data, out->handle);
448}
449
450static void release_in_focus(struct stream_in *in, long ns __unused)
451{
452 struct audio_device *adev = in->dev;
453 if (adev->adm_abandon_focus)
454 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
455}
456
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700457static int parse_snd_card_status(struct str_parms * parms, int * card,
458 card_status_t * status)
459{
460 char value[32]={0};
461 char state[32]={0};
462
463 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
464
465 if (ret < 0)
466 return -1;
467
468 // sscanf should be okay as value is of max length 32.
469 // same as sizeof state.
470 if (sscanf(value, "%d,%s", card, state) < 2)
471 return -1;
472
473 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
474 CARD_STATUS_OFFLINE;
475 return 0;
476}
477
vivek mehta40125092017-08-21 18:48:51 -0700478// always call with adev lock held
479void send_gain_dep_calibration_l() {
480 if (last_known_cal_step >= 0)
481 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
482}
483
vivek mehta1a9b7c02015-06-25 11:49:38 -0700484__attribute__ ((visibility ("default")))
485bool audio_hw_send_gain_dep_calibration(int level) {
486 bool ret_val = false;
487 ALOGV("%s: enter ... ", __func__);
488
489 pthread_mutex_lock(&adev_init_lock);
490
491 if (adev != NULL && adev->platform != NULL) {
492 pthread_mutex_lock(&adev->lock);
vivek mehta40125092017-08-21 18:48:51 -0700493 last_known_cal_step = level;
494 send_gain_dep_calibration_l();
vivek mehta1a9b7c02015-06-25 11:49:38 -0700495 pthread_mutex_unlock(&adev->lock);
496 } else {
497 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
498 }
499
500 pthread_mutex_unlock(&adev_init_lock);
501
502 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
503 return ret_val;
504}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700505
jasmine cha270b7762018-03-30 15:41:33 +0800506#ifdef MAXXAUDIO_QDSP_ENABLED
507bool audio_hw_send_ma_parameter(int stream_type, float vol, bool active)
508{
509 bool ret = false;
510 ALOGV("%s: enter ...", __func__);
511
512 pthread_mutex_lock(&adev_init_lock);
513
514 if (adev != NULL && adev->platform != NULL) {
515 pthread_mutex_lock(&adev->lock);
516 ret = audio_extn_ma_set_state(adev, stream_type, vol, active);
517 pthread_mutex_unlock(&adev->lock);
518 }
519
520 pthread_mutex_unlock(&adev_init_lock);
521
522 ALOGV("%s: exit with ret %d", __func__, ret);
523 return ret;
524}
525#else
526#define audio_hw_send_ma_parameter(stream_type, vol, active) (0)
527#endif
528
vivek mehtaa8d7c922016-05-25 14:40:44 -0700529__attribute__ ((visibility ("default")))
530int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
531 int table_size) {
532 int ret_val = 0;
533 ALOGV("%s: enter ... ", __func__);
534
535 pthread_mutex_lock(&adev_init_lock);
536 if (adev == NULL) {
537 ALOGW("%s: adev is NULL .... ", __func__);
538 goto done;
539 }
540
541 pthread_mutex_lock(&adev->lock);
542 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
543 pthread_mutex_unlock(&adev->lock);
544done:
545 pthread_mutex_unlock(&adev_init_lock);
546 ALOGV("%s: exit ... ", __func__);
547 return ret_val;
548}
549
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700550static bool is_supported_format(audio_format_t format)
551{
Eric Laurent8251ac82014-07-23 11:00:25 -0700552 switch (format) {
553 case AUDIO_FORMAT_MP3:
554 case AUDIO_FORMAT_AAC_LC:
555 case AUDIO_FORMAT_AAC_HE_V1:
556 case AUDIO_FORMAT_AAC_HE_V2:
557 return true;
558 default:
559 break;
560 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700561 return false;
562}
563
juyuchenbe5c67e2018-08-29 17:19:20 +0800564static bool is_supported_24bits_audiosource(audio_source_t source)
565{
566 switch (source) {
567 case AUDIO_SOURCE_UNPROCESSED:
568#ifdef ENABLED_24BITS_CAMCORDER
569 case AUDIO_SOURCE_CAMCORDER:
570#endif
571 return true;
572 default:
573 break;
574 }
575 return false;
576}
577
Haynes Mathew George03c40102016-01-29 17:57:48 -0800578static inline bool is_mmap_usecase(audio_usecase_t uc_id)
579{
580 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
581 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
582}
583
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700584static int get_snd_codec_id(audio_format_t format)
585{
586 int id = 0;
587
Eric Laurent8251ac82014-07-23 11:00:25 -0700588 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700589 case AUDIO_FORMAT_MP3:
590 id = SND_AUDIOCODEC_MP3;
591 break;
592 case AUDIO_FORMAT_AAC:
593 id = SND_AUDIOCODEC_AAC;
594 break;
595 default:
596 ALOGE("%s: Unsupported audio format", __func__);
597 }
598
599 return id;
600}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800601
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800602static int audio_ssr_status(struct audio_device *adev)
603{
604 int ret = 0;
605 struct mixer_ctl *ctl;
606 const char *mixer_ctl_name = "Audio SSR Status";
607
608 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
609 ret = mixer_ctl_get_value(ctl, 0);
610 ALOGD("%s: value: %d", __func__, ret);
611 return ret;
612}
613
vivek mehta4a824772017-06-08 19:05:49 -0700614static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
615{
616 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
617}
618
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800619static bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
620{
621 return out_snd_device == SND_DEVICE_OUT_BT_SCO ||
622 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
623 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
624 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
625 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
626 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC;
627
628}
629
630static bool is_a2dp_device(snd_device_t out_snd_device)
631{
632 return out_snd_device == SND_DEVICE_OUT_BT_A2DP;
633}
634
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800635int enable_audio_route(struct audio_device *adev,
636 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800637{
yixuanjiang509f0a72018-09-06 18:37:23 +0800638 snd_device_t snd_device;
Andy Hung11f10e22018-10-19 17:47:12 -0700639 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800640
641 if (usecase == NULL)
642 return -EINVAL;
643
644 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
645
yixuanjiang509f0a72018-09-06 18:37:23 +0800646 if (usecase->type == PCM_CAPTURE)
647 snd_device = usecase->in_snd_device;
648 else
649 snd_device = usecase->out_snd_device;
Yamit Mehtae3b99562016-09-16 22:44:00 +0530650 audio_extn_utils_send_app_type_cfg(adev, usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800651 audio_extn_utils_send_audio_calibration(adev, usecase);
Andy Hung11f10e22018-10-19 17:47:12 -0700652
653 // we shouldn't truncate mixer_path
654 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
655 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
656 // this also appends to mixer_path
yixuanjiang509f0a72018-09-06 18:37:23 +0800657 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Andy Hung11f10e22018-10-19 17:47:12 -0700658
yixuanjiang509f0a72018-09-06 18:37:23 +0800659 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700660 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700661 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800662
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800663 ALOGV("%s: exit", __func__);
664 return 0;
665}
666
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800667int disable_audio_route(struct audio_device *adev,
668 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800669{
yixuanjiang509f0a72018-09-06 18:37:23 +0800670 snd_device_t snd_device;
Andy Hung11f10e22018-10-19 17:47:12 -0700671 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800672
673 if (usecase == NULL)
674 return -EINVAL;
675
676 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
yixuanjiang509f0a72018-09-06 18:37:23 +0800677 if (usecase->type == PCM_CAPTURE)
678 snd_device = usecase->in_snd_device;
679 else
680 snd_device = usecase->out_snd_device;
Andy Hung11f10e22018-10-19 17:47:12 -0700681
682 // we shouldn't truncate mixer_path
683 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
684 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
685 // this also appends to mixer_path
yixuanjiang509f0a72018-09-06 18:37:23 +0800686 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700687 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Andy Hung11f10e22018-10-19 17:47:12 -0700688
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700689 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000690 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800691
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800692 ALOGV("%s: exit", __func__);
693 return 0;
694}
695
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800696int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700697 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800698{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700699 int i, num_devices = 0;
700 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800701 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800702 if (snd_device < SND_DEVICE_MIN ||
703 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800704 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800705 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800706 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700707
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700708 platform_send_audio_calibration(adev->platform, snd_device);
709
vivek mehtade4849c2016-03-03 17:23:38 -0800710 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700711 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700712 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800713 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700714 }
715
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700716 /* due to the possibility of calibration overwrite between listen
717 and audio, notify sound trigger hal before audio calibration is sent */
718 audio_extn_sound_trigger_update_device_status(snd_device,
719 ST_EVENT_SND_DEVICE_BUSY);
720
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700721 if (audio_extn_spkr_prot_is_enabled())
722 audio_extn_spkr_prot_calib_cancel(adev);
723
zhaoyang yin4211fad2015-06-04 21:13:25 +0800724 audio_extn_dsm_feedback_enable(adev, snd_device, true);
725
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700726 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800727 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
juyuchen1d05ba32018-03-31 16:03:51 +0800728 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700729 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
730 audio_extn_spkr_prot_is_enabled()) {
Aniket Kumar Lata9d6679a2018-04-11 18:13:23 -0700731 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800732 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700733 }
734 if (audio_extn_spkr_prot_start_processing(snd_device)) {
735 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800736 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700737 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700738 } else if (platform_can_split_snd_device(snd_device,
739 &num_devices,
740 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700741 for (i = 0; i < num_devices; i++) {
742 enable_snd_device(adev, new_snd_devices[i]);
743 }
vivek mehtab6506412015-08-07 16:55:17 -0700744 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700745 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800746 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
747 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
748 ALOGE(" %s: Invalid sound device returned", __func__);
749 goto on_error;
750 }
Ed Tam70b5c142016-03-21 19:14:29 -0700751
Eric Laurent2e140aa2016-06-30 17:14:46 -0700752 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Aniket Kumar Lataa158e862018-05-11 17:28:40 -0700753
754 if (is_a2dp_device(snd_device) &&
755 (audio_extn_a2dp_start_playback() < 0)) {
756 ALOGE("%s: failed to configure A2DP control path", __func__);
757 goto on_error;
758 }
759
vivek mehtade4849c2016-03-03 17:23:38 -0800760 audio_route_apply_and_update_path(adev->audio_route, device_name);
761 }
762on_success:
763 adev->snd_dev_ref_cnt[snd_device]++;
764 ret_val = 0;
765on_error:
766 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800767}
768
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800769int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700770 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800771{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700772 int i, num_devices = 0;
773 snd_device_t new_snd_devices[2];
774
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800775 if (snd_device < SND_DEVICE_MIN ||
776 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800777 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800778 return -EINVAL;
779 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700780 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
781 ALOGE("%s: device ref cnt is already 0", __func__);
782 return -EINVAL;
783 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800784 audio_extn_tfa_98xx_disable_speaker(snd_device);
785
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700786 adev->snd_dev_ref_cnt[snd_device]--;
787 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800788 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800789
790 if (is_a2dp_device(snd_device))
791 audio_extn_a2dp_stop_playback();
792
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700793 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800794 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700795 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700796 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
797 audio_extn_spkr_prot_is_enabled()) {
798 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700799
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700800 // FIXME b/65363602: bullhead is the only Nexus with audio_extn_spkr_prot_is_enabled()
801 // and does not use speaker swap. As this code causes a problem with device enable ref
802 // counting we remove it for now.
vivek mehtae59cfb22017-06-16 15:57:11 -0700803 // when speaker device is disabled, reset swap.
804 // will be renabled on usecase start
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700805 // platform_set_swap_channels(adev, false);
vivek mehtae59cfb22017-06-16 15:57:11 -0700806
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700807 } else if (platform_can_split_snd_device(snd_device,
808 &num_devices,
809 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700810 for (i = 0; i < num_devices; i++) {
811 disable_snd_device(adev, new_snd_devices[i]);
812 }
vivek mehtab6506412015-08-07 16:55:17 -0700813 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700814 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800815 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
816 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
817 ALOGE(" %s: Invalid sound device returned", __func__);
818 return -EINVAL;
819 }
820
Eric Laurent2e140aa2016-06-30 17:14:46 -0700821 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800822 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700823 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700824 audio_extn_sound_trigger_update_device_status(snd_device,
825 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700826 }
vivek mehtab6506412015-08-07 16:55:17 -0700827
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800828 return 0;
829}
830
Vignesh Kulothungan64698822018-01-23 11:25:18 -0800831#ifdef DYNAMIC_ECNS_ENABLED
832static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
833 struct stream_in *in,
834 struct audio_effect_config effect_config,
835 unsigned int param_value)
836{
837 char mixer_ctl_name[] = "Audio Effect";
838 long set_values[6];
839
840 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
841 if (!ctl) {
842 ALOGE("%s: Could not get mixer ctl - %s",
843 __func__, mixer_ctl_name);
844 return -EINVAL;
845 }
846
847 set_values[0] = 1; //0:Rx 1:Tx
848 set_values[1] = in->app_type_cfg.app_type;
849 set_values[2] = (long)effect_config.module_id;
850 set_values[3] = (long)effect_config.instance_id;
851 set_values[4] = (long)effect_config.param_id;
852 set_values[5] = param_value;
853
854 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
855
856 return 0;
857
858}
859
860static int update_effect_param_ecns(struct audio_usecase *usecase,
861 unsigned int module_id, int effect_type,
862 unsigned int *param_value)
863{
864 int ret = 0;
865 struct audio_effect_config other_effect_config;
866 struct stream_in *in = NULL;
867
868 if (!usecase)
869 return -EINVAL;
870
871 in = usecase->stream.in;
872
873 /* Get the effect config data of the other effect */
874 ret = platform_get_effect_config_data(usecase->in_snd_device,
875 &other_effect_config,
876 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
877 if (ret < 0) {
878 ALOGE("%s Failed to get effect params %d", __func__, ret);
879 return ret;
880 }
881
882 if (module_id == other_effect_config.module_id) {
883 //Same module id for AEC/NS. Values need to be combined
884 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
885 ((effect_type == EFFECT_NS) && (in->enable_aec)))
886 *param_value |= other_effect_config.param_value;
887 }
888
889 return ret;
890}
891
892static int enable_disable_effect(struct audio_device *adev, struct stream_in *in,
893 int effect_type, bool enable)
894{
895 struct audio_effect_config effect_config;
896 struct audio_usecase *usecase = NULL;
897 int ret = 0;
898 unsigned int param_value = 0;
899
900 if (!in) {
901 ALOGE("%s: Invalid input stream", __func__);
902 return -EINVAL;
903 }
904
905 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
906
907 usecase = get_usecase_from_list(adev, in->usecase);
908
909 ret = platform_get_effect_config_data(usecase->in_snd_device,
910 &effect_config, effect_type);
911 if (ret < 0) {
912 ALOGE("%s Failed to get module id %d", __func__, ret);
913 return ret;
914 }
915 ALOGV("%s: module %d app_type %d usecase->id:%d usecase->in_snd_device:%d",
916 __func__, effect_config.module_id, in->app_type_cfg.app_type,
917 usecase->id, usecase->in_snd_device);
918
919 if (enable)
920 param_value = effect_config.param_value;
921
922 /*Special handling for AEC & NS effects Param values need to be
923 updated if module ids are same*/
924
925 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
926 ret = update_effect_param_ecns(usecase, effect_config.module_id,
927 effect_type, &param_value);
928 if (ret < 0)
929 return ret;
930 }
931
932 ret = send_effect_enable_disable_mixer_ctl(adev, in,
933 effect_config, param_value);
934
935 return ret;
936}
937
938static int check_and_enable_effect(struct audio_device *adev)
939{
940 int ret = 0;
941
942 struct listnode *node;
943 struct stream_in *in = NULL;
944
945 list_for_each(node, &adev->usecase_list)
946 {
947 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
948 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL) {
949 in = usecase->stream.in;
950
951 if (in->standby)
952 continue;
953
954 if (in->enable_aec) {
955 ret = enable_disable_effect(adev, in, EFFECT_AEC, true);
956 }
957
958 if (in->enable_ns &&
959 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
960 ret = enable_disable_effect(adev, in, EFFECT_NS, true);
961 }
962 }
963 }
964
965 return ret;
966}
967#else
968#define enable_disable_effect(w, x, y, z) -ENOSYS
969#define check_and_enable_effect(x) -ENOSYS
970#endif
971
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700972/*
973 legend:
974 uc - existing usecase
975 new_uc - new usecase
976 d1, d11, d2 - SND_DEVICE enums
977 a1, a2 - corresponding ANDROID device enums
978 B, B1, B2 - backend strings
979
980case 1
981 uc->dev d1 (a1) B1
982 new_uc->dev d1 (a1), d2 (a2) B1, B2
983
984 resolution: disable and enable uc->dev on d1
985
986case 2
987 uc->dev d1 (a1) B1
988 new_uc->dev d11 (a1) B1
989
990 resolution: need to switch uc since d1 and d11 are related
991 (e.g. speaker and voice-speaker)
992 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
993
994case 3
995 uc->dev d1 (a1) B1
996 new_uc->dev d2 (a2) B2
997
998 resolution: no need to switch uc
999
1000case 4
1001 uc->dev d1 (a1) B
1002 new_uc->dev d2 (a2) B
1003
1004 resolution: disable enable uc-dev on d2 since backends match
1005 we cannot enable two streams on two different devices if they
1006 share the same backend. e.g. if offload is on speaker device using
1007 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1008 using the same backend, offload must also be switched to voice-handset.
1009
1010case 5
1011 uc->dev d1 (a1) B
1012 new_uc->dev d1 (a1), d2 (a2) B
1013
1014 resolution: disable enable uc-dev on d2 since backends match
1015 we cannot enable two streams on two different devices if they
1016 share the same backend.
1017
1018case 6
1019 uc->dev d1 a1 B1
1020 new_uc->dev d2 a1 B2
1021
1022 resolution: no need to switch
1023
1024case 7
1025
1026 uc->dev d1 (a1), d2 (a2) B1, B2
1027 new_uc->dev d1 B1
1028
1029 resolution: no need to switch
1030
1031*/
1032static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
1033 struct audio_usecase *new_uc,
1034 snd_device_t new_snd_device)
1035{
1036 audio_devices_t a1 = uc->stream.out->devices;
1037 audio_devices_t a2 = new_uc->stream.out->devices;
1038
1039 snd_device_t d1 = uc->out_snd_device;
1040 snd_device_t d2 = new_snd_device;
1041
1042 // Treat as a special case when a1 and a2 are not disjoint
1043 if ((a1 != a2) && (a1 & a2)) {
1044 snd_device_t d3[2];
1045 int num_devices = 0;
1046 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
1047 &num_devices,
1048 d3);
1049 if (ret < 0) {
1050 if (ret != -ENOSYS) {
1051 ALOGW("%s failed to split snd_device %d",
1052 __func__,
1053 popcount(a1) > 1 ? d1 : d2);
1054 }
1055 goto end;
1056 }
1057
1058 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1059 // But if it does happen, we need to give priority to d2 if
1060 // the combo devices active on the existing usecase share a backend.
1061 // This is because we cannot have a usecase active on a combo device
1062 // and a new usecase requests one device in this combo pair.
1063 if (platform_check_backends_match(d3[0], d3[1])) {
1064 return d2; // case 5
1065 } else {
1066 return d1; // case 1
1067 }
1068 } else {
1069 if (platform_check_backends_match(d1, d2)) {
1070 return d2; // case 2, 4
1071 } else {
1072 return d1; // case 6, 3
1073 }
1074 }
1075
1076end:
1077 return d2; // return whatever was calculated before.
1078}
1079
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001080static void check_and_route_playback_usecases(struct audio_device *adev,
1081 struct audio_usecase *uc_info,
1082 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001083{
1084 struct listnode *node;
1085 struct audio_usecase *usecase;
1086 bool switch_device[AUDIO_USECASE_MAX];
1087 int i, num_uc_to_switch = 0;
1088
Haynes Mathew George137a2ee2017-05-23 17:03:35 -07001089 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
1090 uc_info,
1091 snd_device);
David Linee3fe402017-03-13 10:00:42 -07001092
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001093 /* For a2dp device reconfigure all active sessions
1094 * with new AFE encoder format based on a2dp state
1095 */
1096 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Aniket Kumar Lata9723a962018-05-16 17:41:55 -07001097 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1098 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001099 audio_extn_a2dp_is_force_device_switch()) {
1100 force_routing = true;
1101 }
1102
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001103 /*
1104 * This function is to make sure that all the usecases that are active on
1105 * the hardware codec backend are always routed to any one device that is
1106 * handled by the hardware codec.
1107 * For example, if low-latency and deep-buffer usecases are currently active
1108 * on speaker and out_set_parameters(headset) is received on low-latency
1109 * output, then we have to make sure deep-buffer is also switched to headset,
1110 * because of the limitation that both the devices cannot be enabled
1111 * at the same time as they share the same backend.
1112 */
1113 /* Disable all the usecases on the shared backend other than the
1114 specified usecase */
1115 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1116 switch_device[i] = false;
1117
1118 list_for_each(node, &adev->usecase_list) {
1119 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -07001120 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
1121 continue;
1122
1123 if (force_routing ||
1124 (usecase->out_snd_device != snd_device &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -07001125 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
1126 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -07001127 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001128 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1129 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -07001130 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001131 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001132 switch_device[usecase->id] = true;
1133 num_uc_to_switch++;
1134 }
1135 }
1136
1137 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001138 list_for_each(node, &adev->usecase_list) {
1139 usecase = node_to_item(node, struct audio_usecase, list);
1140 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001141 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +09001142 }
1143 }
1144
Haynes Mathew George2d809e02016-09-22 17:38:16 -07001145 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +09001146 list_for_each(node, &adev->usecase_list) {
1147 usecase = node_to_item(node, struct audio_usecase, list);
1148 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -07001149 d_device = derive_playback_snd_device(usecase, uc_info,
1150 snd_device);
1151 enable_snd_device(adev, d_device);
1152 /* Update the out_snd_device before enabling the audio route */
1153 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001154 }
1155 }
1156
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001157 /* Re-route all the usecases on the shared backend other than the
1158 specified usecase to new snd devices */
1159 list_for_each(node, &adev->usecase_list) {
1160 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001161 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001162 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001163 }
1164 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001165 }
1166}
1167
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001168static void check_and_route_capture_usecases(struct audio_device *adev,
1169 struct audio_usecase *uc_info,
1170 snd_device_t snd_device)
1171{
1172 struct listnode *node;
1173 struct audio_usecase *usecase;
1174 bool switch_device[AUDIO_USECASE_MAX];
1175 int i, num_uc_to_switch = 0;
1176
vivek mehta4ed66e62016-04-15 23:33:34 -07001177 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
1178
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001179 /*
1180 * This function is to make sure that all the active capture usecases
1181 * are always routed to the same input sound device.
1182 * For example, if audio-record and voice-call usecases are currently
1183 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1184 * is received for voice call then we have to make sure that audio-record
1185 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1186 * because of the limitation that two devices cannot be enabled
1187 * at the same time if they share the same backend.
1188 */
1189 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1190 switch_device[i] = false;
1191
1192 list_for_each(node, &adev->usecase_list) {
1193 usecase = node_to_item(node, struct audio_usecase, list);
1194 if (usecase->type != PCM_PLAYBACK &&
1195 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -07001196 usecase->in_snd_device != snd_device &&
Carter Hsu0a1160c2018-10-04 09:24:36 +08001197 ((uc_info->type == VOICE_CALL &&
1198 usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL) ||
1199 platform_check_backends_match(snd_device,\
1200 usecase->in_snd_device)) &&
Anish Kumarff864712015-06-03 13:35:11 -07001201 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001202 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1203 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001204 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001205 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001206 switch_device[usecase->id] = true;
1207 num_uc_to_switch++;
1208 }
1209 }
1210
1211 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001212 list_for_each(node, &adev->usecase_list) {
1213 usecase = node_to_item(node, struct audio_usecase, list);
1214 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001215 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001216 }
1217 }
1218
1219 list_for_each(node, &adev->usecase_list) {
1220 usecase = node_to_item(node, struct audio_usecase, list);
1221 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001222 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001223 }
1224 }
1225
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001226 /* Re-route all the usecases on the shared backend other than the
1227 specified usecase to new snd devices */
1228 list_for_each(node, &adev->usecase_list) {
1229 usecase = node_to_item(node, struct audio_usecase, list);
1230 /* Update the in_snd_device only before enabling the audio route */
1231 if (switch_device[usecase->id] ) {
1232 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001233 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001234 }
1235 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001236 }
1237}
1238
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001239/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001240static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001241{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001242 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001243 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001244
1245 switch (channels) {
1246 /*
1247 * Do not handle stereo output in Multi-channel cases
1248 * Stereo case is handled in normal playback path
1249 */
1250 case 6:
1251 ALOGV("%s: HDMI supports 5.1", __func__);
1252 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1253 break;
1254 case 8:
1255 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
1256 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1257 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
1258 break;
1259 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001260 ALOGE("HDMI does not support multi channel playback");
1261 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001262 break;
1263 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001264 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001265}
1266
Andy Hung18859412017-08-09 11:47:21 -07001267static ssize_t read_usb_sup_sample_rates(bool is_playback,
1268 uint32_t *supported_sample_rates,
1269 uint32_t max_rates)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001270{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001271 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1272 supported_sample_rates,
1273 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001274#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001275 for (ssize_t i=0; i<count; i++) {
1276 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1277 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001278 }
1279#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001280 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001281}
1282
Haynes Mathew George569b7482017-05-08 14:44:27 -07001283static int read_usb_sup_channel_masks(bool is_playback,
1284 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001285 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001286{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001287 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001288 int channel_count;
1289 uint32_t num_masks = 0;
1290 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1291 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001292 }
Eric Laurent74b55762017-07-09 17:04:53 -07001293 if (is_playback) {
Andy Hung6c1afb12017-12-22 11:34:41 -08001294 // start from 2 channels as framework currently doesn't support mono.
1295 // TODO: consider only supporting channel index masks beyond stereo here.
1296 for (channel_count = FCC_2;
1297 channel_count <= channels && num_masks < max_masks;
1298 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001299 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1300 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001301 for (channel_count = FCC_2;
1302 channel_count <= channels && num_masks < max_masks;
1303 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001304 supported_channel_masks[num_masks++] =
1305 audio_channel_mask_for_index_assignment_from_count(channel_count);
1306 }
1307 } else {
1308 // For capture we report all supported channel masks from 1 channel up.
1309 channel_count = MIN_CHANNEL_COUNT;
1310 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1311 // indexed mask
1312 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
Andy Hung88ce1d92018-10-29 18:31:12 -07001313 const audio_channel_mask_t mask =
Eric Laurent74b55762017-07-09 17:04:53 -07001314 audio_channel_in_mask_from_count(channel_count);
Andy Hung88ce1d92018-10-29 18:31:12 -07001315 supported_channel_masks[num_masks++] = mask;
1316 const audio_channel_mask_t index_mask =
1317 audio_channel_mask_for_index_assignment_from_count(channel_count);
1318 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
1319 supported_channel_masks[num_masks++] = index_mask;
1320 }
Eric Laurent74b55762017-07-09 17:04:53 -07001321 }
1322 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001323#ifdef NDEBUG
1324 for (size_t i = 0; i < num_masks; ++i) {
1325 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1326 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
1327 }
1328#endif
Eric Laurent74b55762017-07-09 17:04:53 -07001329 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001330}
1331
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001332static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001333 audio_format_t *supported_formats,
1334 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001335{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001336 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001337 switch (bitwidth) {
1338 case 24:
1339 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001340 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001341 break;
1342 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001343 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001344 break;
1345 case 16:
1346 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001347 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001348 break;
1349 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001350 ALOGV("%s: %s supported format %d", __func__,
1351 is_playback ? "P" : "C", bitwidth);
1352 return 1;
1353}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001354
Haynes Mathew George569b7482017-05-08 14:44:27 -07001355static int read_usb_sup_params_and_compare(bool is_playback,
1356 audio_format_t *format,
1357 audio_format_t *supported_formats,
1358 uint32_t max_formats,
1359 audio_channel_mask_t *mask,
1360 audio_channel_mask_t *supported_channel_masks,
1361 uint32_t max_masks,
1362 uint32_t *rate,
1363 uint32_t *supported_sample_rates,
1364 uint32_t max_rates) {
1365 int ret = 0;
1366 int num_formats;
1367 int num_masks;
1368 int num_rates;
1369 int i;
1370
1371 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1372 max_formats);
1373 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1374 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001375
Haynes Mathew George569b7482017-05-08 14:44:27 -07001376 num_rates = read_usb_sup_sample_rates(is_playback,
1377 supported_sample_rates, max_rates);
1378
1379#define LUT(table, len, what, dflt) \
1380 for (i=0; i<len && (table[i] != what); i++); \
1381 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1382
1383 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1384 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1385 LUT(supported_sample_rates, num_rates, *rate, 0);
1386
1387#undef LUT
1388 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001389}
1390
Andy Hungd9653bd2017-08-01 19:31:39 -07001391static bool is_usb_ready(struct audio_device *adev, bool is_playback)
1392{
1393 // Check if usb is ready.
1394 // The usb device may have been removed quickly after insertion and hence
1395 // no longer available. This will show up as empty channel masks, or rates.
1396
1397 pthread_mutex_lock(&adev->lock);
1398 uint32_t supported_sample_rate;
1399
1400 // we consider usb ready if we can fetch at least one sample rate.
1401 const bool ready = read_usb_sup_sample_rates(
1402 is_playback, &supported_sample_rate, 1 /* max_rates */) > 0;
1403 pthread_mutex_unlock(&adev->lock);
1404 return ready;
1405}
1406
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001407static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1408{
1409 struct audio_usecase *usecase;
1410 struct listnode *node;
1411
1412 list_for_each(node, &adev->usecase_list) {
1413 usecase = node_to_item(node, struct audio_usecase, list);
1414 if (usecase->type == VOICE_CALL) {
1415 ALOGV("%s: usecase id %d", __func__, usecase->id);
1416 return usecase->id;
1417 }
1418 }
1419 return USECASE_INVALID;
1420}
1421
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001422struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1423 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001424{
1425 struct audio_usecase *usecase;
1426 struct listnode *node;
1427
1428 list_for_each(node, &adev->usecase_list) {
1429 usecase = node_to_item(node, struct audio_usecase, list);
1430 if (usecase->id == uc_id)
1431 return usecase;
1432 }
1433 return NULL;
1434}
1435
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001436static bool force_device_switch(struct audio_usecase *usecase)
1437{
1438 if (usecase->stream.out == NULL) {
1439 ALOGE("%s: stream.out is NULL", __func__);
1440 return false;
1441 }
1442
1443 // Force all A2DP output devices to reconfigure for proper AFE encode format
1444 // Also handle a case where in earlier A2DP start failed as A2DP stream was
1445 // in suspended state, hence try to trigger a retry when we again get a routing request.
1446 if ((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
1447 audio_extn_a2dp_is_force_device_switch()) {
1448 ALOGD("%s: Force A2DP device switch to update new encoder config", __func__);
1449 return true;
1450 }
1451
1452 return false;
1453}
1454
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001455struct stream_in *adev_get_active_input(const struct audio_device *adev)
1456{
1457 struct listnode *node;
1458 struct stream_in *last_active_in = NULL;
1459
1460 /* Get last added active input.
1461 * TODO: We may use a priority mechanism to pick highest priority active source */
1462 list_for_each(node, &adev->usecase_list)
1463 {
1464 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
1465 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL) {
1466 last_active_in = usecase->stream.in;
1467 }
1468 }
1469
1470 return last_active_in;
1471}
1472
1473struct stream_in *get_voice_communication_input(const struct audio_device *adev)
1474{
1475 struct listnode *node;
1476
1477 /* First check active inputs with voice communication source and then
1478 * any input if audio mode is in communication */
1479 list_for_each(node, &adev->usecase_list)
1480 {
1481 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
1482 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
1483 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1484 return usecase->stream.in;
1485 }
1486 }
1487 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
1488 return adev_get_active_input(adev);
1489 }
1490 return NULL;
1491}
1492
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001493int select_devices(struct audio_device *adev,
1494 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001495{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001496 snd_device_t out_snd_device = SND_DEVICE_NONE;
1497 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001498 struct audio_usecase *usecase = NULL;
1499 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001500 struct audio_usecase *hfp_usecase = NULL;
1501 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001502 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001503 int status = 0;
Eric Laurentf4520b02017-09-20 18:31:58 -07001504 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1505 USECASE_AUDIO_PLAYBACK_VOIP);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001506
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001507 usecase = get_usecase_from_list(adev, uc_id);
1508 if (usecase == NULL) {
1509 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1510 return -EINVAL;
1511 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001512
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001513 if ((usecase->type == VOICE_CALL) ||
1514 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001515 out_snd_device = platform_get_output_snd_device(adev->platform,
1516 usecase->stream.out->devices);
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001517 in_snd_device = platform_get_input_snd_device(adev->platform,
1518 NULL,
1519 usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001520 usecase->devices = usecase->stream.out->devices;
1521 } else {
1522 /*
1523 * If the voice call is active, use the sound devices of voice call usecase
1524 * so that it would not result any device switch. All the usecases will
1525 * be switched to new device when select_devices() is called for voice call
1526 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001527 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001528 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001529 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001530 vc_usecase = get_usecase_from_list(adev,
1531 get_voice_usecase_id_from_list(adev));
1532 if ((vc_usecase != NULL) &&
1533 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
juyuchend194b432018-11-16 14:15:16 +08001534 (vc_usecase->devices == AUDIO_DEVICE_OUT_HEARING_AID) ||
1535 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001536 in_snd_device = vc_usecase->in_snd_device;
1537 out_snd_device = vc_usecase->out_snd_device;
1538 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001539 } else if (audio_extn_hfp_is_active(adev)) {
1540 hfp_ucid = audio_extn_hfp_get_usecase();
1541 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1542 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1543 in_snd_device = hfp_usecase->in_snd_device;
1544 out_snd_device = hfp_usecase->out_snd_device;
1545 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001546 }
1547 if (usecase->type == PCM_PLAYBACK) {
1548 usecase->devices = usecase->stream.out->devices;
1549 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001550 if (out_snd_device == SND_DEVICE_NONE) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001551 struct stream_out *voip_out = adev->primary_output;
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001552 struct stream_in *voip_in = get_voice_communication_input(adev);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001553
Eric Laurentb23d5282013-05-14 15:27:20 -07001554 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001555 usecase->stream.out->devices);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001556
1557 if (voip_usecase)
1558 voip_out = voip_usecase->stream.out;
1559
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001560 if (usecase->stream.out == voip_out && voip_in != NULL) {
1561 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001562 }
1563 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001564 } else if (usecase->type == PCM_CAPTURE) {
1565 usecase->devices = usecase->stream.in->device;
1566 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001567 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001568 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001569 struct stream_in *voip_in = get_voice_communication_input(adev);
1570
1571 if (voip_in != NULL) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001572
1573 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1574 USECASE_AUDIO_PLAYBACK_VOIP);
1575
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001576 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001577 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1578 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001579 } else if (voip_usecase) {
1580 out_device = voip_usecase->stream.out->devices;
juyuchend194b432018-11-16 14:15:16 +08001581 } else if (adev->primary_output &&
1582 !adev->primary_output->standby) {
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001583 out_device = adev->primary_output->devices;
juyuchend194b432018-11-16 14:15:16 +08001584 } else {
1585 /* forcing speaker o/p device to get matching i/p pair
1586 in case o/p is not routed from same primary HAL */
1587 out_device = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001588 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001589 }
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001590 in_snd_device = platform_get_input_snd_device(adev->platform,
1591 usecase->stream.in,
1592 out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001593 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001594 }
1595 }
1596
1597 if (out_snd_device == usecase->out_snd_device &&
1598 in_snd_device == usecase->in_snd_device) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001599 if (!force_device_switch(usecase))
1600 return 0;
1601 }
1602
1603 if (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready()) {
1604 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1605 return 0;
1606 }
1607
Aniket Kumar Lata9723a962018-05-16 17:41:55 -07001608 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
1609 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001610 (!audio_extn_a2dp_is_ready())) {
1611 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
juyuchen9baad392018-06-05 19:02:10 +08001612 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
1613 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
1614 else
1615 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001616 }
1617
juyuchen66c4ecf2018-08-06 15:39:34 +08001618 if (usecase->id == USECASE_INCALL_MUSIC_UPLINK) {
1619 out_snd_device = SND_DEVICE_OUT_VOICE_MUSIC_TX;
1620 }
1621
Eric Laurent2bafff12016-03-17 12:17:23 -07001622 if (out_snd_device != SND_DEVICE_NONE &&
1623 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1624 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1625 __func__,
1626 use_case_table[uc_id],
1627 adev->last_logged_snd_device[uc_id][0],
1628 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1629 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1630 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1631 -1,
1632 out_snd_device,
1633 platform_get_snd_device_name(out_snd_device),
1634 platform_get_snd_device_acdb_id(out_snd_device));
1635 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1636 }
1637 if (in_snd_device != SND_DEVICE_NONE &&
1638 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1639 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1640 __func__,
1641 use_case_table[uc_id],
1642 adev->last_logged_snd_device[uc_id][1],
1643 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1644 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1645 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1646 -1,
1647 in_snd_device,
1648 platform_get_snd_device_name(in_snd_device),
1649 platform_get_snd_device_acdb_id(in_snd_device));
1650 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1651 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001652
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001653 /*
1654 * Limitation: While in call, to do a device switch we need to disable
1655 * and enable both RX and TX devices though one of them is same as current
1656 * device.
1657 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001658 if ((usecase->type == VOICE_CALL) &&
1659 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1660 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001661 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001662 /* Disable sidetone only if voice call already exists */
1663 if (voice_is_call_state_active(adev))
1664 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001665 }
1666
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001667 /* Disable current sound devices */
1668 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001669 disable_audio_route(adev, usecase);
1670 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001671 }
1672
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001673 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001674 disable_audio_route(adev, usecase);
1675 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001676 }
1677
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001678 /* Applicable only on the targets that has external modem.
1679 * New device information should be sent to modem before enabling
1680 * the devices to reduce in-call device switch time.
1681 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001682 if ((usecase->type == VOICE_CALL) &&
1683 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1684 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001685 status = platform_switch_voice_call_enable_device_config(adev->platform,
1686 out_snd_device,
1687 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001688 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001689
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001690 /* Enable new sound devices */
1691 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001692 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001693 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) ||
1694 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001695 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001696 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001697 }
1698
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001699 if (in_snd_device != SND_DEVICE_NONE) {
1700 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001701 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001702 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001703
Eric Laurentb23d5282013-05-14 15:27:20 -07001704 if (usecase->type == VOICE_CALL)
1705 status = platform_switch_voice_call_device_post(adev->platform,
1706 out_snd_device,
1707 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001708
sangwoo170731f2013-06-08 15:36:36 +09001709 usecase->in_snd_device = in_snd_device;
1710 usecase->out_snd_device = out_snd_device;
1711
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001712 audio_extn_tfa_98xx_set_mode();
1713
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001714 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001715
Jasmine Cha70771b62018-05-15 15:02:43 +08001716 audio_extn_ma_set_device(usecase);
jasmine cha270b7762018-03-30 15:41:33 +08001717
Vignesh Kulothungan64698822018-01-23 11:25:18 -08001718 /* If input stream is already running the effect needs to be
1719 applied on the new input device that's being enabled here. */
1720 if (in_snd_device != SND_DEVICE_NONE)
1721 check_and_enable_effect(adev);
1722
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001723 /* Applicable only on the targets that has external modem.
1724 * Enable device command should be sent to modem only after
1725 * enabling voice call mixer controls
1726 */
vivek mehta765eb642015-08-07 19:46:06 -07001727 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001728 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1729 out_snd_device,
1730 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001731 /* Enable sidetone only if voice call already exists */
1732 if (voice_is_call_state_active(adev))
1733 voice_set_sidetone(adev, out_snd_device, true);
1734 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001735
Yung Ti Sue9d64f92018-06-22 17:38:47 +08001736 if (usecase->type != PCM_CAPTURE && voip_usecase) {
Eric Laurentf4520b02017-09-20 18:31:58 -07001737 struct stream_out *voip_out = voip_usecase->stream.out;
1738 audio_extn_utils_send_app_type_gain(adev,
1739 voip_out->app_type_cfg.app_type,
1740 &voip_out->app_type_cfg.gain[0]);
1741 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001742 return status;
1743}
1744
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001745static int stop_input_stream(struct stream_in *in)
1746{
1747 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001748 struct audio_usecase *uc_info;
1749 struct audio_device *adev = in->dev;
1750
Eric Laurent994a6932013-07-17 11:51:42 -07001751 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001752 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001753
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001754 uc_info = get_usecase_from_list(adev, in->usecase);
1755 if (uc_info == NULL) {
1756 ALOGE("%s: Could not find the usecase (%d) in the list",
1757 __func__, in->usecase);
1758 return -EINVAL;
1759 }
1760
vivek mehta781065c2017-04-04 12:55:01 -07001761 /* Close in-call recording streams */
1762 voice_check_and_stop_incall_rec_usecase(adev, in);
1763
Eric Laurent150dbfe2013-02-27 14:31:02 -08001764 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001765 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001766
1767 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001768 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001769
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001770 list_remove(&uc_info->list);
1771 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001772
Eric Laurent994a6932013-07-17 11:51:42 -07001773 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001774 return ret;
1775}
1776
1777int start_input_stream(struct stream_in *in)
1778{
1779 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001780 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001781 struct audio_usecase *uc_info;
1782 struct audio_device *adev = in->dev;
1783
Eric Laurent994a6932013-07-17 11:51:42 -07001784 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001785
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001786 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1787 return -EIO;
1788
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001789 if (in->card_status == CARD_STATUS_OFFLINE ||
1790 adev->card_status == CARD_STATUS_OFFLINE) {
1791 ALOGW("in->card_status or adev->card_status offline, try again");
1792 ret = -EAGAIN;
1793 goto error_config;
1794 }
1795
vivek mehta781065c2017-04-04 12:55:01 -07001796 /* Check if source matches incall recording usecase criteria */
1797 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1798 if (ret)
1799 goto error_config;
1800 else
1801 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1802
Eric Laurentb23d5282013-05-14 15:27:20 -07001803 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001804 if (in->pcm_device_id < 0) {
1805 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1806 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001807 ret = -EINVAL;
1808 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001809 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001810
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001811 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1812 uc_info->id = in->usecase;
1813 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001814 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001815 uc_info->devices = in->device;
1816 uc_info->in_snd_device = SND_DEVICE_NONE;
1817 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001818
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001819 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001820
Wei Wangf4837d52017-11-21 14:51:20 -08001821 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001822 audio_extn_perf_lock_acquire();
1823
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001824 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001825
Eric Laurent0e46adf2016-12-16 12:49:24 -08001826 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001827 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001828 ALOGE("%s: pcm stream not ready", __func__);
1829 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001830 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001831 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001832 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001833 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1834 goto error_open;
1835 }
1836 } else {
1837 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1838 unsigned int pcm_open_retry_count = 0;
1839
1840 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1841 flags |= PCM_MMAP | PCM_NOIRQ;
1842 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1843 } else if (in->realtime) {
1844 flags |= PCM_MMAP | PCM_NOIRQ;
1845 }
1846
1847 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1848 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1849
1850 while (1) {
1851 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1852 flags, &in->config);
1853 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1854 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1855 if (in->pcm != NULL) {
1856 pcm_close(in->pcm);
1857 in->pcm = NULL;
1858 }
1859 if (pcm_open_retry_count-- == 0) {
1860 ret = -EIO;
1861 goto error_open;
1862 }
1863 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1864 continue;
1865 }
1866 break;
1867 }
1868
1869 ALOGV("%s: pcm_prepare", __func__);
1870 ret = pcm_prepare(in->pcm);
1871 if (ret < 0) {
1872 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001873 pcm_close(in->pcm);
1874 in->pcm = NULL;
1875 goto error_open;
1876 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001877 if (in->realtime) {
1878 ret = pcm_start(in->pcm);
1879 if (ret < 0) {
1880 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1881 pcm_close(in->pcm);
1882 in->pcm = NULL;
1883 goto error_open;
1884 }
1885 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001886 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001887 register_in_stream(in);
Vignesh Kulothungan64698822018-01-23 11:25:18 -08001888 check_and_enable_effect(adev);
Wei Wangf4837d52017-11-21 14:51:20 -08001889 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001890 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001891 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001892
Eric Laurent0e46adf2016-12-16 12:49:24 -08001893 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001894
1895error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001896 stop_input_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001897 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001898 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001899
1900error_config:
Eric Laurent2bafff12016-03-17 12:17:23 -07001901 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001902 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001903}
1904
Eric Laurenta1478072015-09-21 17:21:52 -07001905void lock_input_stream(struct stream_in *in)
1906{
1907 pthread_mutex_lock(&in->pre_lock);
1908 pthread_mutex_lock(&in->lock);
1909 pthread_mutex_unlock(&in->pre_lock);
1910}
1911
1912void lock_output_stream(struct stream_out *out)
1913{
1914 pthread_mutex_lock(&out->pre_lock);
1915 pthread_mutex_lock(&out->lock);
1916 pthread_mutex_unlock(&out->pre_lock);
1917}
1918
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001919/* must be called with out->lock locked */
1920static int send_offload_cmd_l(struct stream_out* out, int command)
1921{
1922 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1923
1924 ALOGVV("%s %d", __func__, command);
1925
1926 cmd->cmd = command;
1927 list_add_tail(&out->offload_cmd_list, &cmd->node);
1928 pthread_cond_signal(&out->offload_cond);
1929 return 0;
1930}
1931
1932/* must be called iwth out->lock locked */
1933static void stop_compressed_output_l(struct stream_out *out)
1934{
1935 out->offload_state = OFFLOAD_STATE_IDLE;
1936 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001937 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001938 if (out->compr != NULL) {
1939 compress_stop(out->compr);
1940 while (out->offload_thread_blocked) {
1941 pthread_cond_wait(&out->cond, &out->lock);
1942 }
1943 }
1944}
1945
1946static void *offload_thread_loop(void *context)
1947{
1948 struct stream_out *out = (struct stream_out *) context;
1949 struct listnode *item;
1950
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001951 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1952 set_sched_policy(0, SP_FOREGROUND);
1953 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1954
1955 ALOGV("%s", __func__);
juyuchenb0f5bfd2018-12-12 17:58:09 +08001956
Eric Laurenta1478072015-09-21 17:21:52 -07001957 lock_output_stream(out);
juyuchenb0f5bfd2018-12-12 17:58:09 +08001958 out->offload_state = OFFLOAD_STATE_IDLE;
1959 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001960 for (;;) {
1961 struct offload_cmd *cmd = NULL;
1962 stream_callback_event_t event;
1963 bool send_callback = false;
1964
1965 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1966 __func__, list_empty(&out->offload_cmd_list),
1967 out->offload_state);
1968 if (list_empty(&out->offload_cmd_list)) {
1969 ALOGV("%s SLEEPING", __func__);
1970 pthread_cond_wait(&out->offload_cond, &out->lock);
1971 ALOGV("%s RUNNING", __func__);
1972 continue;
1973 }
1974
1975 item = list_head(&out->offload_cmd_list);
1976 cmd = node_to_item(item, struct offload_cmd, node);
1977 list_remove(item);
1978
1979 ALOGVV("%s STATE %d CMD %d out->compr %p",
1980 __func__, out->offload_state, cmd->cmd, out->compr);
1981
1982 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1983 free(cmd);
1984 break;
1985 }
1986
1987 if (out->compr == NULL) {
1988 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001989 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001990 pthread_cond_signal(&out->cond);
1991 continue;
1992 }
1993 out->offload_thread_blocked = true;
1994 pthread_mutex_unlock(&out->lock);
1995 send_callback = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001996 switch (cmd->cmd) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001997 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1998 compress_wait(out->compr, -1);
1999 send_callback = true;
2000 event = STREAM_CBK_EVENT_WRITE_READY;
2001 break;
2002 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002003 compress_next_track(out->compr);
2004 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002005 send_callback = true;
2006 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08002007 /* Resend the metadata for next iteration */
2008 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002009 break;
2010 case OFFLOAD_CMD_DRAIN:
2011 compress_drain(out->compr);
2012 send_callback = true;
2013 event = STREAM_CBK_EVENT_DRAIN_READY;
2014 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002015 case OFFLOAD_CMD_ERROR:
2016 send_callback = true;
2017 event = STREAM_CBK_EVENT_ERROR;
2018 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002019 default:
2020 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2021 break;
2022 }
Eric Laurenta1478072015-09-21 17:21:52 -07002023 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002024 out->offload_thread_blocked = false;
2025 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07002026 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08002027 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002028 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002029 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002030 free(cmd);
2031 }
2032
2033 pthread_cond_signal(&out->cond);
2034 while (!list_empty(&out->offload_cmd_list)) {
2035 item = list_head(&out->offload_cmd_list);
2036 list_remove(item);
2037 free(node_to_item(item, struct offload_cmd, node));
2038 }
2039 pthread_mutex_unlock(&out->lock);
2040
2041 return NULL;
2042}
2043
2044static int create_offload_callback_thread(struct stream_out *out)
2045{
2046 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2047 list_init(&out->offload_cmd_list);
2048 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2049 offload_thread_loop, out);
2050 return 0;
2051}
2052
2053static int destroy_offload_callback_thread(struct stream_out *out)
2054{
Eric Laurenta1478072015-09-21 17:21:52 -07002055 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002056 stop_compressed_output_l(out);
2057 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2058
2059 pthread_mutex_unlock(&out->lock);
2060 pthread_join(out->offload_thread, (void **) NULL);
2061 pthread_cond_destroy(&out->offload_cond);
2062
2063 return 0;
2064}
2065
Eric Laurent07eeafd2013-10-06 12:52:49 -07002066static bool allow_hdmi_channel_config(struct audio_device *adev)
2067{
2068 struct listnode *node;
2069 struct audio_usecase *usecase;
2070 bool ret = true;
2071
2072 list_for_each(node, &adev->usecase_list) {
2073 usecase = node_to_item(node, struct audio_usecase, list);
2074 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2075 /*
2076 * If voice call is already existing, do not proceed further to avoid
2077 * disabling/enabling both RX and TX devices, CSD calls, etc.
2078 * Once the voice call done, the HDMI channels can be configured to
2079 * max channels of remaining use cases.
2080 */
2081 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08002082 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07002083 __func__);
2084 ret = false;
2085 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002086 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
2087 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07002088 "no change in HDMI channels", __func__);
2089 ret = false;
2090 break;
2091 }
2092 }
2093 }
2094 return ret;
2095}
2096
2097static int check_and_set_hdmi_channels(struct audio_device *adev,
2098 unsigned int channels)
2099{
2100 struct listnode *node;
2101 struct audio_usecase *usecase;
2102
2103 /* Check if change in HDMI channel config is allowed */
2104 if (!allow_hdmi_channel_config(adev))
2105 return 0;
2106
2107 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08002108 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002109 return 0;
2110 }
2111
2112 platform_set_hdmi_channels(adev->platform, channels);
2113 adev->cur_hdmi_channels = channels;
2114
2115 /*
2116 * Deroute all the playback streams routed to HDMI so that
2117 * the back end is deactivated. Note that backend will not
2118 * be deactivated if any one stream is connected to it.
2119 */
2120 list_for_each(node, &adev->usecase_list) {
2121 usecase = node_to_item(node, struct audio_usecase, list);
2122 if (usecase->type == PCM_PLAYBACK &&
2123 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002124 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002125 }
2126 }
2127
2128 /*
2129 * Enable all the streams disabled above. Now the HDMI backend
2130 * will be activated with new channel configuration
2131 */
2132 list_for_each(node, &adev->usecase_list) {
2133 usecase = node_to_item(node, struct audio_usecase, list);
2134 if (usecase->type == PCM_PLAYBACK &&
2135 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002136 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002137 }
2138 }
2139
2140 return 0;
2141}
2142
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002143static int check_and_set_usb_service_interval(struct audio_device *adev,
2144 struct audio_usecase *uc_info,
2145 bool min)
2146{
2147 struct listnode *node;
2148 struct audio_usecase *usecase;
2149 bool switch_usecases = false;
2150 bool reconfig = false;
2151
2152 if ((uc_info->id != USECASE_AUDIO_PLAYBACK_MMAP) &&
2153 (uc_info->id != USECASE_AUDIO_PLAYBACK_ULL))
2154 return -1;
2155
2156 /* set if the valid usecase do not already exist */
2157 list_for_each(node, &adev->usecase_list) {
2158 usecase = node_to_item(node, struct audio_usecase, list);
2159 if (usecase->type == PCM_PLAYBACK &&
2160 (audio_is_usb_out_device(usecase->devices & AUDIO_DEVICE_OUT_ALL_USB))) {
2161 switch (usecase->id) {
2162 case USECASE_AUDIO_PLAYBACK_MMAP:
2163 case USECASE_AUDIO_PLAYBACK_ULL:
2164 // cannot reconfig while mmap/ull is present.
2165 return -1;
2166 default:
2167 switch_usecases = true;
2168 break;
2169 }
2170 }
2171 if (switch_usecases)
2172 break;
2173 }
2174 /*
2175 * client can try to set service interval in start_output_stream
2176 * to min or to 0 (i.e reset) in stop_output_stream .
2177 */
2178 unsigned long service_interval =
2179 audio_extn_usb_find_service_interval(min, true /*playback*/);
2180 int ret = platform_set_usb_service_interval(adev->platform,
2181 true /*playback*/,
2182 service_interval,
2183 &reconfig);
2184 /* no change or not supported or no active usecases */
2185 if (ret || !reconfig || !switch_usecases)
2186 return -1;
2187 return 0;
2188#undef VALID_USECASE
2189}
2190
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002191static int stop_output_stream(struct stream_out *out)
2192{
2193 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002194 struct audio_usecase *uc_info;
2195 struct audio_device *adev = out->dev;
HW Lee88512e92018-06-12 15:26:09 +08002196 bool has_voip_usecase =
2197 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002198
Eric Laurent994a6932013-07-17 11:51:42 -07002199 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002200 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002201 uc_info = get_usecase_from_list(adev, out->usecase);
2202 if (uc_info == NULL) {
2203 ALOGE("%s: Could not find the usecase (%d) in the list",
2204 __func__, out->usecase);
2205 return -EINVAL;
2206 }
2207
Haynes Mathew George41f86652014-06-17 14:22:15 -07002208 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2209 if (adev->visualizer_stop_output != NULL)
2210 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
2211 if (adev->offload_effects_stop_output != NULL)
2212 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002213 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2214 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2215 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07002216 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002217
Arun Mirpuri0cc2f312018-05-29 17:26:07 -07002218 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
2219 voice_set_device_mute_flag(adev, false);
2220
Eric Laurent150dbfe2013-02-27 14:31:02 -08002221 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002222 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002223
2224 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002225 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002226
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002227 list_remove(&uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002228
Eric Laurent0499d4f2014-08-25 22:39:29 -05002229 audio_extn_extspk_update(adev->extspk);
2230
Eric Laurent07eeafd2013-10-06 12:52:49 -07002231 /* Must be called after removing the usecase from list */
2232 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2233 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
HW Lee88512e92018-06-12 15:26:09 +08002234 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002235 ret = check_and_set_usb_service_interval(adev, uc_info, false /*min*/);
2236 if (ret == 0) {
2237 /* default service interval was successfully updated,
2238 reopen USB backend with new service interval */
2239 check_and_route_playback_usecases(adev, uc_info, uc_info->out_snd_device);
2240 }
2241 ret = 0;
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07002242 }
juyuchend194b432018-11-16 14:15:16 +08002243 /* 1) media + voip output routing to handset must route media back to
2244 speaker when voip stops.
2245 2) trigger voip input to reroute when voip output changes to
2246 hearing aid. */
HW Lee88512e92018-06-12 15:26:09 +08002247 if (has_voip_usecase ||
2248 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
2249 struct listnode *node;
2250 struct audio_usecase *usecase;
2251 list_for_each(node, &adev->usecase_list) {
2252 usecase = node_to_item(node, struct audio_usecase, list);
juyuchend194b432018-11-16 14:15:16 +08002253 if ((usecase->type == PCM_CAPTURE &&
2254 usecase->id != USECASE_AUDIO_RECORD_VOIP)
2255 || usecase == uc_info)
HW Lee88512e92018-06-12 15:26:09 +08002256 continue;
2257
2258 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
2259 __func__, usecase->id, use_case_table[usecase->id],
2260 out->usecase, use_case_table[out->usecase]);
2261 select_devices(adev, usecase->id);
2262 }
2263 }
2264
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002265 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07002266 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002267 return ret;
2268}
2269
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002270struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
2271 unsigned int flags, unsigned int pcm_open_retry_count,
2272 struct pcm_config *config)
2273{
2274 struct pcm* pcm = NULL;
2275
2276 while (1) {
2277 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
2278 if (pcm == NULL || !pcm_is_ready(pcm)) {
2279 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
2280 if (pcm != NULL) {
2281 pcm_close(pcm);
2282 pcm = NULL;
2283 }
2284 if (pcm_open_retry_count-- == 0)
2285 return NULL;
2286
2287 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2288 continue;
2289 }
2290 break;
2291 }
2292
2293 if (pcm_is_ready(pcm)) {
2294 int ret = pcm_prepare(pcm);
2295 if (ret < 0) {
2296 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2297 pcm_close(pcm);
2298 pcm = NULL;
2299 }
2300 }
2301
2302 return pcm;
2303}
2304
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002305int start_output_stream(struct stream_out *out)
2306{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002307 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002308 struct audio_usecase *uc_info;
2309 struct audio_device *adev = out->dev;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002310 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002311
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002312 ALOGV("%s: enter: usecase(%d: %s) %s devices(%#x)",
2313 __func__, out->usecase, use_case_table[out->usecase],
2314 out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS ? "(with haptics)" : "",
2315 out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002316
2317 if (out->card_status == CARD_STATUS_OFFLINE ||
2318 adev->card_status == CARD_STATUS_OFFLINE) {
2319 ALOGW("out->card_status or adev->card_status offline, try again");
2320 ret = -EAGAIN;
2321 goto error_config;
2322 }
2323
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002324 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2325 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002326 if (out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002327 a2dp_combo = true;
2328 } else {
2329 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2330 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2331 ret = -EAGAIN;
2332 goto error_config;
2333 }
2334 }
2335 }
2336 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002337 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002338 if (out->pcm_device_id < 0) {
2339 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2340 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002341 ret = -EINVAL;
2342 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002343 }
2344
2345 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
2346 uc_info->id = out->usecase;
2347 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002348 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002349 uc_info->devices = out->devices;
2350 uc_info->in_snd_device = SND_DEVICE_NONE;
2351 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002352
Eric Laurent07eeafd2013-10-06 12:52:49 -07002353 /* This must be called before adding this usecase to the list */
2354 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2355 check_and_set_hdmi_channels(adev, out->config.channels);
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002356 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
2357 check_and_set_usb_service_interval(adev, uc_info, true /*min*/);
2358 /* USB backend is not reopened immediately.
2359 This is eventually done as part of select_devices */
2360 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002361
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002362 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002363
Wei Wangf4837d52017-11-21 14:51:20 -08002364 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002365 audio_extn_perf_lock_acquire();
2366
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002367 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2368 (!audio_extn_a2dp_is_ready())) {
2369 if (!a2dp_combo) {
2370 check_a2dp_restore_l(adev, out, false);
2371 } else {
2372 audio_devices_t dev = out->devices;
juyuchen9baad392018-06-05 19:02:10 +08002373 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2374 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2375 else
2376 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002377 select_devices(adev, out->usecase);
2378 out->devices = dev;
2379 }
2380 } else {
2381 select_devices(adev, out->usecase);
2382 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002383
Eric Laurent0499d4f2014-08-25 22:39:29 -05002384 audio_extn_extspk_update(adev->extspk);
2385
Arun Mirpuri0cc2f312018-05-29 17:26:07 -07002386 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
2387 voice_set_device_mute_flag(adev, true);
2388
Andy Hung31aca912014-03-20 17:14:59 -07002389 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002390 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002391 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2392 out->pcm = NULL;
2393 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
2394 COMPRESS_IN, &out->compr_config);
2395 if (out->compr && !is_compress_ready(out->compr)) {
2396 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2397 compress_close(out->compr);
2398 out->compr = NULL;
2399 ret = -EIO;
2400 goto error_open;
2401 }
2402 if (out->offload_callback)
2403 compress_nonblock(out->compr, out->non_blocking);
2404
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07002405 if (adev->visualizer_start_output != NULL) {
2406 int capture_device_id =
2407 platform_get_pcm_device_id(USECASE_AUDIO_RECORD_AFE_PROXY,
2408 PCM_CAPTURE);
2409 adev->visualizer_start_output(out->handle, out->pcm_device_id,
2410 adev->snd_card, capture_device_id);
2411 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002412 if (adev->offload_effects_start_output != NULL)
2413 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
2414 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002415 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002416 ALOGE("%s: pcm stream not ready", __func__);
2417 goto error_open;
2418 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002419 ret = pcm_start(out->pcm);
2420 if (ret < 0) {
2421 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2422 goto error_open;
2423 }
2424 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07002425 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002426 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002427
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002428 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2429 flags |= PCM_MMAP | PCM_NOIRQ;
2430 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002431 } else if (out->realtime) {
2432 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07002433 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002434
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002435 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
2436 flags, pcm_open_retry_count,
2437 &(out->config));
2438 if (out->pcm == NULL) {
2439 ret = -EIO;
2440 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002441 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002442
2443 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
2444 if (adev->haptic_pcm != NULL) {
2445 pcm_close(adev->haptic_pcm);
2446 adev->haptic_pcm = NULL;
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002447 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002448 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
2449 adev->haptic_pcm_device_id,
2450 flags, pcm_open_retry_count,
2451 &(adev->haptics_config));
2452 // failure to open haptics pcm shouldnt stop audio,
2453 // so do not close audio pcm in case of error
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002454 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002455
Eric Laurent0e46adf2016-12-16 12:49:24 -08002456 if (out->realtime) {
2457 ret = pcm_start(out->pcm);
2458 if (ret < 0) {
2459 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
2460 pcm_close(out->pcm);
2461 out->pcm = NULL;
2462 goto error_open;
2463 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002464 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002465 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002466
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002467 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08002468 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002469 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002470 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07002471
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002472 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2473 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2474 audio_low_latency_hint_start();
2475 }
2476
vivek mehtae59cfb22017-06-16 15:57:11 -07002477 // consider a scenario where on pause lower layers are tear down.
2478 // so on resume, swap mixer control need to be sent only when
2479 // backend is active, hence rather than sending from enable device
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002480 // sending it from start of stream
vivek mehtae59cfb22017-06-16 15:57:11 -07002481
2482 platform_set_swap_channels(adev, true);
2483
Eric Laurent994a6932013-07-17 11:51:42 -07002484 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002485 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002486error_open:
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002487 if (adev->haptic_pcm) {
2488 pcm_close(adev->haptic_pcm);
2489 adev->haptic_pcm = NULL;
2490 }
Wei Wangf4837d52017-11-21 14:51:20 -08002491 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002492 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002493 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002494error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002495 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002496}
2497
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002498static int check_input_parameters(uint32_t sample_rate,
2499 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07002500 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002501{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002502 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2503 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002504 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2505 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002506 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2507 return -EINVAL;
2508 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002509
Eric Laurent74b55762017-07-09 17:04:53 -07002510 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2511 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002512 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002513 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002514 return -EINVAL;
2515 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002516
2517 switch (sample_rate) {
2518 case 8000:
2519 case 11025:
2520 case 12000:
2521 case 16000:
2522 case 22050:
2523 case 24000:
2524 case 32000:
2525 case 44100:
2526 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002527 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002528 break;
2529 default:
vivek mehtadae44712015-07-27 14:13:18 -07002530 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002531 return -EINVAL;
2532 }
2533
2534 return 0;
2535}
2536
Kevin Rocarda325aa22018-04-03 09:15:52 -07002537/** Add a value in a list if not already present.
2538 * @return true if value was successfully inserted or already present,
2539 * false if the list is full and does not contain the value.
2540 */
2541static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
2542 for (size_t i = 0; i < list_length; i++) {
2543 if (list[i] == value) return true; // value is already present
2544 if (list[i] == 0) { // no values in this slot
2545 list[i] = value;
2546 return true; // value inserted
2547 }
2548 }
2549 return false; // could not insert value
2550}
2551
2552/** Add channel_mask in supported_channel_masks if not already present.
2553 * @return true if channel_mask was successfully inserted or already present,
2554 * false if supported_channel_masks is full and does not contain channel_mask.
2555 */
2556static void register_channel_mask(audio_channel_mask_t channel_mask,
2557 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
2558 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
2559 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
2560}
2561
2562/** Add format in supported_formats if not already present.
2563 * @return true if format was successfully inserted or already present,
2564 * false if supported_formats is full and does not contain format.
2565 */
2566static void register_format(audio_format_t format,
2567 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
2568 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
2569 "%s: stream can not declare supporting its format %x", __func__, format);
2570}
2571/** Add sample_rate in supported_sample_rates if not already present.
2572 * @return true if sample_rate was successfully inserted or already present,
2573 * false if supported_sample_rates is full and does not contain sample_rate.
2574 */
2575static void register_sample_rate(uint32_t sample_rate,
2576 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
2577 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
2578 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
2579}
2580
vivek mehtaa68fea62017-06-08 19:04:02 -07002581static size_t get_stream_buffer_size(size_t duration_ms,
2582 uint32_t sample_rate,
2583 audio_format_t format,
2584 int channel_count,
2585 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002586{
2587 size_t size = 0;
2588
vivek mehtaa68fea62017-06-08 19:04:02 -07002589 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002590 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002591 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002592
2593 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002594
Glenn Kasten4f993392014-05-14 07:30:48 -07002595 /* make sure the size is multiple of 32 bytes
2596 * At 48 kHz mono 16-bit PCM:
2597 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2598 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2599 */
2600 size += 0x1f;
2601 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002602
2603 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002604}
2605
2606static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2607{
2608 struct stream_out *out = (struct stream_out *)stream;
2609
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002610 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002611}
2612
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002613static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002614{
2615 return -ENOSYS;
2616}
2617
2618static size_t out_get_buffer_size(const struct audio_stream *stream)
2619{
2620 struct stream_out *out = (struct stream_out *)stream;
2621
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002622 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2623 return out->compr_config.fragment_size;
2624 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002625 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002626 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002627}
2628
2629static uint32_t out_get_channels(const struct audio_stream *stream)
2630{
2631 struct stream_out *out = (struct stream_out *)stream;
2632
2633 return out->channel_mask;
2634}
2635
2636static audio_format_t out_get_format(const struct audio_stream *stream)
2637{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002638 struct stream_out *out = (struct stream_out *)stream;
2639
2640 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002641}
2642
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002643static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002644{
2645 return -ENOSYS;
2646}
2647
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002648/* must be called with out->lock locked */
2649static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002650{
2651 struct stream_out *out = (struct stream_out *)stream;
2652 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002653 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002654
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002655 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002656 if (adev->adm_deregister_stream)
2657 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002658 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002659 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002660 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2661 if (out->pcm) {
2662 pcm_close(out->pcm);
2663 out->pcm = NULL;
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002664
2665 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
2666 if (adev->haptic_pcm) {
2667 pcm_close(adev->haptic_pcm);
2668 adev->haptic_pcm = NULL;
2669 }
2670
2671 if (adev->haptic_buffer != NULL) {
2672 free(adev->haptic_buffer);
2673 adev->haptic_buffer = NULL;
2674 adev->haptic_buffer_size = 0;
2675 }
2676 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002677 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002678 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002679 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002680 out->playback_started = false;
2681 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002682 } else {
2683 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002684 out->gapless_mdata.encoder_delay = 0;
2685 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002686 if (out->compr != NULL) {
2687 compress_close(out->compr);
2688 out->compr = NULL;
2689 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002690 }
Phil Burkbc991042017-02-24 08:06:44 -08002691 if (do_stop) {
2692 stop_output_stream(out);
2693 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002694 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002695 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002696 return 0;
2697}
2698
2699static int out_standby(struct audio_stream *stream)
2700{
2701 struct stream_out *out = (struct stream_out *)stream;
2702
2703 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2704 out->usecase, use_case_table[out->usecase]);
2705
2706 lock_output_stream(out);
2707 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002708 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002709 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002710 return 0;
2711}
2712
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002713static int out_on_error(struct audio_stream *stream)
2714{
2715 struct stream_out *out = (struct stream_out *)stream;
2716 struct audio_device *adev = out->dev;
2717 bool do_standby = false;
2718
2719 lock_output_stream(out);
2720 if (!out->standby) {
2721 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2722 stop_compressed_output_l(out);
2723 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2724 } else
2725 do_standby = true;
2726 }
2727 pthread_mutex_unlock(&out->lock);
2728
2729 if (do_standby)
2730 return out_standby(&out->stream.common);
2731
2732 return 0;
2733}
2734
Andy Hung7401c7c2016-09-21 12:41:21 -07002735static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002736{
Andy Hung7401c7c2016-09-21 12:41:21 -07002737 struct stream_out *out = (struct stream_out *)stream;
2738
2739 // We try to get the lock for consistency,
2740 // but it isn't necessary for these variables.
2741 // If we're not in standby, we may be blocked on a write.
2742 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2743 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2744 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2745
2746 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002747 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002748 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002749
2750 // dump error info
2751 (void)error_log_dump(
2752 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002753
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002754 return 0;
2755}
2756
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002757static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2758{
2759 int ret = 0;
2760 char value[32];
2761 struct compr_gapless_mdata tmp_mdata;
2762
2763 if (!out || !parms) {
2764 return -EINVAL;
2765 }
2766
2767 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2768 if (ret >= 0) {
2769 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2770 } else {
2771 return -EINVAL;
2772 }
2773
2774 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2775 if (ret >= 0) {
2776 tmp_mdata.encoder_padding = atoi(value);
2777 } else {
2778 return -EINVAL;
2779 }
2780
2781 out->gapless_mdata = tmp_mdata;
2782 out->send_new_metadata = 1;
2783 ALOGV("%s new encoder delay %u and padding %u", __func__,
2784 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2785
2786 return 0;
2787}
2788
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002789static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2790{
2791 return out == adev->primary_output || out == adev->voice_tx_output;
2792}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002793
Kevin Rocard1e02c882017-08-09 15:26:07 -07002794static int get_alive_usb_card(struct str_parms* parms) {
2795 int card;
2796 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2797 !audio_extn_usb_alive(card)) {
2798 return card;
2799 }
2800 return -ENODEV;
2801}
2802
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002803static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2804{
2805 struct stream_out *out = (struct stream_out *)stream;
2806 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002807 struct audio_usecase *usecase;
2808 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002809 struct str_parms *parms;
2810 char value[32];
2811 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002812 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002813 int status = 0;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002814 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002815
Eric Laurent2e140aa2016-06-30 17:14:46 -07002816 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002817 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002818 parms = str_parms_create_str(kvpairs);
2819 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2820 if (ret >= 0) {
2821 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002822
Eric Laurenta1478072015-09-21 17:21:52 -07002823 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002824
2825 // The usb driver needs to be closed after usb device disconnection
2826 // otherwise audio is no longer played on the new usb devices.
2827 // By forcing the stream in standby, the usb stack refcount drops to 0
2828 // and the driver is closed.
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002829 if (val == AUDIO_DEVICE_NONE &&
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002830 audio_is_usb_out_device(out->devices)) {
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002831 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2832 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2833 out_standby_l(&out->stream.common);
2834 }
2835 val = AUDIO_DEVICE_OUT_SPEAKER;
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002836 }
2837
Eric Laurent150dbfe2013-02-27 14:31:02 -08002838 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002839
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002840 /*
2841 * When HDMI cable is unplugged the music playback is paused and
2842 * the policy manager sends routing=0. But the audioflinger
2843 * continues to write data until standby time (3sec).
2844 * As the HDMI core is turned off, the write gets blocked.
2845 * Avoid this by routing audio to speaker until standby.
2846 */
2847 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2848 val == AUDIO_DEVICE_NONE) {
2849 val = AUDIO_DEVICE_OUT_SPEAKER;
2850 }
2851
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002852 /*
2853 * When A2DP is disconnected the
2854 * music playback is paused and the policy manager sends routing=0
2855 * But the audioflingercontinues to write data until standby time
2856 * (3sec). As BT is turned off, the write gets blocked.
2857 * Avoid this by routing audio to speaker until standby.
2858 */
2859 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2860 (val == AUDIO_DEVICE_NONE) &&
2861 !audio_extn_a2dp_is_ready()) {
2862 val = AUDIO_DEVICE_OUT_SPEAKER;
2863 }
2864
2865 /* To avoid a2dp to sco overlapping / BT device improper state
2866 * check with BT lib about a2dp streaming support before routing
2867 */
2868 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2869 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002870 if (val & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002871 //combo usecase just by pass a2dp
2872 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2873 bypass_a2dp = true;
2874 } else {
2875 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2876 /* update device to a2dp and don't route as BT returned error
2877 * However it is still possible a2dp routing called because
2878 * of current active device disconnection (like wired headset)
2879 */
2880 out->devices = val;
2881 pthread_mutex_unlock(&out->lock);
2882 pthread_mutex_unlock(&adev->lock);
2883 status = -ENOSYS;
2884 goto routing_fail;
2885 }
2886 }
2887 }
2888
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002889 audio_devices_t new_dev = val;
2890
2891 // Workaround: If routing to an non existing usb device, fail gracefully
2892 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002893 int card;
2894 if (audio_is_usb_out_device(new_dev) &&
2895 (card = get_alive_usb_card(parms)) >= 0) {
2896
2897 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002898 pthread_mutex_unlock(&adev->lock);
2899 pthread_mutex_unlock(&out->lock);
2900 status = -ENOSYS;
2901 goto routing_fail;
2902 }
2903
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002904 /*
2905 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002906 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002907 * the select_devices(). But how do we undo this?
2908 *
2909 * For example, music playback is active on headset (deep-buffer usecase)
2910 * and if we go to ringtones and select a ringtone, low-latency usecase
2911 * will be started on headset+speaker. As we can't enable headset+speaker
2912 * and headset devices at the same time, select_devices() switches the music
2913 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2914 * So when the ringtone playback is completed, how do we undo the same?
2915 *
2916 * We are relying on the out_set_parameters() call on deep-buffer output,
2917 * once the ringtone playback is ended.
2918 * NOTE: We should not check if the current devices are same as new devices.
2919 * Because select_devices() must be called to switch back the music
2920 * playback to headset.
2921 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002922 if (new_dev != AUDIO_DEVICE_NONE) {
2923 bool same_dev = out->devices == new_dev;
2924 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002925
Eric Laurenta7657192014-10-09 21:09:33 -07002926 if (output_drives_call(adev, out)) {
Vignesh Kulothungana5c9da12017-11-10 11:41:24 -08002927 if (!voice_is_call_state_active(adev)) {
Eric Laurenta7657192014-10-09 21:09:33 -07002928 if (adev->mode == AUDIO_MODE_IN_CALL) {
2929 adev->current_call_output = out;
2930 ret = voice_start_call(adev);
2931 }
2932 } else {
2933 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002934 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002935 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002936 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002937
2938 if (!out->standby) {
2939 if (!same_dev) {
2940 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002941 // inform adm before actual routing to prevent glitches.
2942 if (adev->adm_on_routing_change) {
2943 adev->adm_on_routing_change(adev->adm_data,
2944 out->handle);
2945 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002946 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002947 if (!bypass_a2dp) {
2948 select_devices(adev, out->usecase);
2949 } else {
juyuchen9baad392018-06-05 19:02:10 +08002950 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2951 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2952 else
2953 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002954 select_devices(adev, out->usecase);
2955 out->devices = new_dev;
2956 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002957 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002958
2959 // on device switch force swap, lower functions will make sure
2960 // to check if swap is allowed or not.
2961
2962 if (!same_dev)
2963 platform_set_swap_channels(adev, true);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002964
2965 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2966 out->a2dp_compress_mute &&
2967 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
2968 pthread_mutex_lock(&out->compr_mute_lock);
2969 out->a2dp_compress_mute = false;
2970 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
2971 pthread_mutex_unlock(&out->compr_mute_lock);
2972 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002973 }
2974
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002975 }
2976
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002977 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002978 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002979
2980 /*handles device and call state changes*/
2981 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002982 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002983 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002984
2985 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2986 parse_compress_metadata(out, parms);
2987 }
2988
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002989 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002990 ALOGV("%s: exit: code(%d)", __func__, status);
2991 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002992}
2993
Haynes Mathew George569b7482017-05-08 14:44:27 -07002994static bool stream_get_parameter_channels(struct str_parms *query,
2995 struct str_parms *reply,
2996 audio_channel_mask_t *supported_channel_masks) {
2997 int ret = -1;
Andy Hung64fdb452018-09-07 11:25:33 -07002998 char value[ARRAY_SIZE(channels_name_to_enum_table) * 32 /* max channel name size */];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002999 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003000 size_t i, j;
3001
3002 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
3003 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003004 value[0] = '\0';
3005 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003006 while (supported_channel_masks[i] != 0) {
3007 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
3008 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003009 if (!first) {
3010 strcat(value, "|");
3011 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003012 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003013 first = false;
3014 break;
3015 }
3016 }
3017 i++;
3018 }
3019 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003020 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003021 return ret >= 0;
3022}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003023
Haynes Mathew George569b7482017-05-08 14:44:27 -07003024static bool stream_get_parameter_formats(struct str_parms *query,
3025 struct str_parms *reply,
3026 audio_format_t *supported_formats) {
3027 int ret = -1;
3028 char value[256];
3029 int i;
3030
3031 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
3032 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003033 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07003034 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003035 case AUDIO_FORMAT_PCM_16_BIT:
3036 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
3037 break;
3038 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
3039 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
3040 break;
3041 case AUDIO_FORMAT_PCM_32_BIT:
3042 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
3043 break;
3044 default:
3045 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07003046 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003047 break;
3048 }
3049 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003050 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003051 return ret >= 0;
3052}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003053
Haynes Mathew George569b7482017-05-08 14:44:27 -07003054static bool stream_get_parameter_rates(struct str_parms *query,
3055 struct str_parms *reply,
3056 uint32_t *supported_sample_rates) {
3057
3058 int i;
3059 char value[256];
3060 int ret = -1;
3061 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
3062 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003063 value[0] = '\0';
3064 i=0;
3065 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003066 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003067 int avail = sizeof(value) - cursor;
3068 ret = snprintf(value + cursor, avail, "%s%d",
3069 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07003070 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003071 if (ret < 0 || ret >= avail) {
3072 // if cursor is at the last element of the array
3073 // overwrite with \0 is duplicate work as
3074 // snprintf already put a \0 in place.
3075 // else
3076 // we had space to write the '|' at value[cursor]
3077 // (which will be overwritten) or no space to fill
3078 // the first element (=> cursor == 0)
3079 value[cursor] = '\0';
3080 break;
3081 }
3082 cursor += ret;
3083 ++i;
3084 }
3085 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
3086 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003087 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003088 return ret >= 0;
3089}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003090
Haynes Mathew George569b7482017-05-08 14:44:27 -07003091static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
3092{
3093 struct stream_out *out = (struct stream_out *)stream;
3094 struct str_parms *query = str_parms_create_str(keys);
3095 char *str;
3096 struct str_parms *reply = str_parms_create();
3097 bool replied = false;
3098 ALOGV("%s: enter: keys - %s", __func__, keys);
3099
3100 replied |= stream_get_parameter_channels(query, reply,
3101 &out->supported_channel_masks[0]);
3102 replied |= stream_get_parameter_formats(query, reply,
3103 &out->supported_formats[0]);
3104 replied |= stream_get_parameter_rates(query, reply,
3105 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003106 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003107 str = str_parms_to_str(reply);
3108 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07003109 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003110 }
3111 str_parms_destroy(query);
3112 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07003113 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003114 return str;
3115}
3116
3117static uint32_t out_get_latency(const struct audio_stream_out *stream)
3118{
Haynes Mathew George03c40102016-01-29 17:57:48 -08003119 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003120 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003121 uint32_t latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003122
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003123 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3124 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003125 else if ((out->realtime) ||
3126 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003127 // since the buffer won't be filled up faster than realtime,
3128 // return a smaller number
3129 period_ms = (out->af_period_multiplier * out->config.period_size *
3130 1000) / (out->config.rate);
3131 hw_delay = platform_render_latency(out->usecase)/1000;
3132 return period_ms + hw_delay;
3133 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003134
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003135 latency = (out->config.period_count * out->config.period_size * 1000) /
3136 (out->config.rate);
3137
3138 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
3139 latency += audio_extn_a2dp_get_encoder_latency();
3140
3141 return latency;
3142}
3143
3144static int set_compr_volume(struct audio_stream_out *stream, float left,
3145 float right)
3146{
3147 struct stream_out *out = (struct stream_out *)stream;
3148 int volume[2];
3149 char mixer_ctl_name[128];
3150 struct audio_device *adev = out->dev;
3151 struct mixer_ctl *ctl;
3152 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
3153 PCM_PLAYBACK);
3154
3155 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3156 "Compress Playback %d Volume", pcm_device_id);
3157 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3158 if (!ctl) {
3159 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3160 __func__, mixer_ctl_name);
3161 return -EINVAL;
3162 }
3163 ALOGV("%s: ctl for mixer cmd - %s, left %f, right %f",
3164 __func__, mixer_ctl_name, left, right);
3165 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3166 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3167 mixer_ctl_set_array(ctl, volume, sizeof(volume) / sizeof(volume[0]));
3168
3169 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003170}
3171
3172static int out_set_volume(struct audio_stream_out *stream, float left,
3173 float right)
3174{
Eric Laurenta9024de2013-04-04 09:19:12 -07003175 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003176 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003177
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003178 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07003179 /* only take left channel into account: the API is for stereo anyway */
3180 out->muted = (left == 0.0f);
3181 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003182 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003183 pthread_mutex_lock(&out->compr_mute_lock);
3184 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
3185 if (!out->a2dp_compress_mute)
3186 ret = set_compr_volume(stream, left, right);
3187 out->volume_l = left;
3188 out->volume_r = right;
3189 pthread_mutex_unlock(&out->compr_mute_lock);
3190 return ret;
vivek mehtaa68fea62017-06-08 19:04:02 -07003191 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07003192 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
3193 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
3194 if (!out->standby) {
3195 // if in standby, cached volume will be sent after stream is opened
3196 audio_extn_utils_send_app_type_gain(out->dev,
3197 out->app_type_cfg.app_type,
3198 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07003199 }
vivek mehtaa68fea62017-06-08 19:04:02 -07003200 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07003201 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003202
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003203 return -ENOSYS;
3204}
3205
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003206// note: this call is safe only if the stream_cb is
3207// removed first in close_output_stream (as is done now).
3208static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3209{
3210 if (!stream || !parms)
3211 return;
3212
3213 struct stream_out *out = (struct stream_out *)stream;
3214 struct audio_device *adev = out->dev;
3215
3216 card_status_t status;
3217 int card;
3218 if (parse_snd_card_status(parms, &card, &status) < 0)
3219 return;
3220
3221 pthread_mutex_lock(&adev->lock);
3222 bool valid_cb = (card == adev->snd_card);
3223 pthread_mutex_unlock(&adev->lock);
3224
3225 if (!valid_cb)
3226 return;
3227
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003228 lock_output_stream(out);
3229 if (out->card_status != status)
3230 out->card_status = status;
3231 pthread_mutex_unlock(&out->lock);
3232
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07003233 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
3234 use_case_table[out->usecase],
3235 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3236
3237 if (status == CARD_STATUS_OFFLINE)
3238 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003239
3240 return;
3241}
3242
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003243#ifdef NO_AUDIO_OUT
3244static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05003245 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003246{
3247 struct stream_out *out = (struct stream_out *)stream;
3248
3249 /* No Output device supported other than BT for playback.
3250 * Sleep for the amount of buffer duration
3251 */
Eric Laurenta1478072015-09-21 17:21:52 -07003252 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05003253 usleep(bytes * 1000000 / audio_stream_out_frame_size(
3254 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003255 out_get_sample_rate(&out->stream.common));
3256 pthread_mutex_unlock(&out->lock);
3257 return bytes;
3258}
3259#endif
3260
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003261static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3262 size_t bytes)
3263{
3264 struct stream_out *out = (struct stream_out *)stream;
3265 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07003266 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07003267 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003268
Eric Laurenta1478072015-09-21 17:21:52 -07003269 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07003270 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07003271 const size_t frame_size = audio_stream_out_frame_size(stream);
3272 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07003273
Eric Laurent0e46adf2016-12-16 12:49:24 -08003274 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3275 error_code = ERROR_CODE_WRITE;
3276 goto exit;
3277 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003278
3279 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3280 (audio_extn_a2dp_is_suspended())) {
juyuchen9baad392018-06-05 19:02:10 +08003281 if (!(out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003282 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3283 ret = -EIO;
3284 goto exit;
3285 }
3286 }
3287 }
3288
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003289 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003290 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003291 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003292 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07003293
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003294 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003295 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003296 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07003297 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003298 goto exit;
3299 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07003300
vivek mehta40125092017-08-21 18:48:51 -07003301 // after standby always force set last known cal step
3302 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
3303 ALOGD("%s: retry previous failed cal level set", __func__);
3304 send_gain_dep_calibration_l();
3305 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003306 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003307
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003308 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003309 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003310 if (out->send_new_metadata) {
3311 ALOGVV("send new gapless metadata");
3312 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3313 out->send_new_metadata = 0;
3314 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003315 unsigned int avail;
3316 struct timespec tstamp;
3317 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
3318 /* Do not limit write size if the available frames count is unknown */
3319 if (ret != 0) {
3320 avail = bytes;
3321 }
3322 if (avail == 0) {
3323 ret = 0;
3324 } else {
3325 if (avail > bytes) {
3326 avail = bytes;
3327 }
3328 ret = compress_write(out->compr, buffer, avail);
3329 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
3330 __func__, avail, ret);
3331 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003332
Eric Laurent6e895242013-09-05 16:10:57 -07003333 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003334 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
3335 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003336 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003337 compress_start(out->compr);
3338 out->playback_started = 1;
3339 out->offload_state = OFFLOAD_STATE_PLAYING;
3340 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003341 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07003342 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07003343 } else {
3344 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07003345 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003346 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07003347 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003348 return ret;
3349 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07003350 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003351 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003352 size_t bytes_to_write = bytes;
3353
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003354 if (out->muted)
3355 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07003356 // FIXME: this can be removed once audio flinger mixer supports mono output
Nadav Bar3d72cfc2018-01-07 12:19:24 +02003357 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP || out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003358 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3359 int16_t *src = (int16_t *)buffer;
3360 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003361
Eric Laurentad2dde92017-09-20 18:27:31 -07003362 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
3363 out->format != AUDIO_FORMAT_PCM_16_BIT,
3364 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003365
Eric Laurentad2dde92017-09-20 18:27:31 -07003366 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
3367 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
3368 }
3369 bytes_to_write /= 2;
3370 }
3371 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes_to_write);
3372
Glenn Kasten5a59dff2018-02-22 08:05:35 -08003373 long ns = (frames * (int64_t) NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003374 request_out_focus(out, ns);
3375
3376 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08003377 if (use_mmap) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003378 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08003379 } else {
3380 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
3381 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3382 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
3383 size_t frame_size = channel_count * bytes_per_sample;
3384 size_t frame_count = bytes_to_write / frame_size;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003385
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08003386 bool force_haptic_path =
3387 property_get_bool("vendor.audio.test_haptic", false);
3388
3389 // extract Haptics data from Audio buffer
3390 bool alloc_haptic_buffer = false;
3391 int haptic_channel_count = adev->haptics_config.channels;
3392 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
3393 size_t audio_frame_size = frame_size - haptic_frame_size;
3394 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
3395
3396 if (adev->haptic_buffer == NULL) {
3397 alloc_haptic_buffer = true;
3398 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
3399 free(adev->haptic_buffer);
3400 adev->haptic_buffer_size = 0;
3401 alloc_haptic_buffer = true;
3402 }
3403
3404 if (alloc_haptic_buffer) {
3405 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
3406 adev->haptic_buffer_size = total_haptic_buffer_size;
3407 }
3408
3409 size_t src_index = 0, aud_index = 0, hap_index = 0;
3410 uint8_t *audio_buffer = (uint8_t *)buffer;
3411 uint8_t *haptic_buffer = adev->haptic_buffer;
3412
3413 // This is required for testing only. This works for stereo data only.
3414 // One channel is fed to audio stream and other to haptic stream for testing.
3415 if (force_haptic_path) {
3416 audio_frame_size = haptic_frame_size = bytes_per_sample;
3417 }
3418
3419 for (size_t i = 0; i < frame_count; i++) {
3420 for (size_t j = 0; j < audio_frame_size; j++)
3421 audio_buffer[aud_index++] = audio_buffer[src_index++];
3422
3423 for (size_t j = 0; j < haptic_frame_size; j++)
3424 haptic_buffer[hap_index++] = audio_buffer[src_index++];
3425 }
3426
3427 // This is required for testing only.
3428 // Discard haptic channel data.
3429 if (force_haptic_path) {
3430 src_index += haptic_frame_size;
3431 }
3432
3433 // write to audio pipeline
3434 ret = pcm_write(out->pcm,
3435 (void *)audio_buffer,
3436 frame_count * audio_frame_size);
3437
3438 // write to haptics pipeline
3439 if (adev->haptic_pcm)
3440 ret = pcm_write(adev->haptic_pcm,
3441 (void *)adev->haptic_buffer,
3442 frame_count * haptic_frame_size);
3443
3444 } else {
3445 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
3446 }
3447 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003448 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07003449 } else {
3450 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003451 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003452 }
3453
3454exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07003455 // For PCM we always consume the buffer and return #bytes regardless of ret.
3456 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003457 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07003458 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003459 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07003460
Andy Hung7401c7c2016-09-21 12:41:21 -07003461 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07003462 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07003463 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3464 ALOGE_IF(out->pcm != NULL,
3465 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07003466 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003467 // usleep not guaranteed for values over 1 second but we don't limit here.
3468 }
3469 }
Andy Hungda9b56b2016-09-16 20:06:35 -07003470
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003471 pthread_mutex_unlock(&out->lock);
3472
3473 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07003474 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003475 if (sleeptime_us != 0)
3476 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003477 }
3478 return bytes;
3479}
3480
3481static int out_get_render_position(const struct audio_stream_out *stream,
3482 uint32_t *dsp_frames)
3483{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003484 struct stream_out *out = (struct stream_out *)stream;
3485 *dsp_frames = 0;
3486 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07003487 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003488 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003489 unsigned long frames = 0;
3490 // TODO: check return value
3491 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
3492 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003493 ALOGVV("%s rendered frames %d sample_rate %d",
3494 __func__, *dsp_frames, out->sample_rate);
3495 }
3496 pthread_mutex_unlock(&out->lock);
3497 return 0;
3498 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003499 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003500}
3501
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003502static int out_add_audio_effect(const struct audio_stream *stream __unused,
3503 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003504{
3505 return 0;
3506}
3507
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003508static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3509 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003510{
3511 return 0;
3512}
3513
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003514static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3515 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003516{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003517 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003518}
3519
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003520static int out_get_presentation_position(const struct audio_stream_out *stream,
3521 uint64_t *frames, struct timespec *timestamp)
3522{
3523 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003524 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07003525 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003526
Eric Laurenta1478072015-09-21 17:21:52 -07003527 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003528
Eric Laurent949a0892013-09-20 09:20:13 -07003529 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3530 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003531 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07003532 compress_get_tstamp(out->compr, &dsp_frames,
3533 &out->sample_rate);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003534 // Adjustment accounts for A2DP encoder latency with offload usecases
3535 // Note: Encoder latency is returned in ms.
3536 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3537 unsigned long offset =
3538 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3539 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
3540 }
Eric Laurent949a0892013-09-20 09:20:13 -07003541 ALOGVV("%s rendered frames %ld sample_rate %d",
3542 __func__, dsp_frames, out->sample_rate);
3543 *frames = dsp_frames;
3544 ret = 0;
3545 /* this is the best we can do */
3546 clock_gettime(CLOCK_MONOTONIC, timestamp);
3547 }
3548 } else {
3549 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07003550 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003551 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3552 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003553 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003554 // This adjustment accounts for buffering after app processor.
3555 // It is based on estimated DSP latency per use case, rather than exact.
3556 signed_frames -=
3557 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3558
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003559 // Adjustment accounts for A2DP encoder latency with non-offload usecases
3560 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3561 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3562 signed_frames -=
3563 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3564 }
3565
Eric Laurent949a0892013-09-20 09:20:13 -07003566 // It would be unusual for this value to be negative, but check just in case ...
3567 if (signed_frames >= 0) {
3568 *frames = signed_frames;
3569 ret = 0;
3570 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003571 }
3572 }
3573 }
3574
3575 pthread_mutex_unlock(&out->lock);
3576
3577 return ret;
3578}
3579
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003580static int out_set_callback(struct audio_stream_out *stream,
3581 stream_callback_t callback, void *cookie)
3582{
3583 struct stream_out *out = (struct stream_out *)stream;
3584
3585 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003586 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003587 out->offload_callback = callback;
3588 out->offload_cookie = cookie;
3589 pthread_mutex_unlock(&out->lock);
3590 return 0;
3591}
3592
3593static int out_pause(struct audio_stream_out* stream)
3594{
3595 struct stream_out *out = (struct stream_out *)stream;
3596 int status = -ENOSYS;
3597 ALOGV("%s", __func__);
3598 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003599 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003600 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
3601 status = compress_pause(out->compr);
3602 out->offload_state = OFFLOAD_STATE_PAUSED;
3603 }
3604 pthread_mutex_unlock(&out->lock);
3605 }
3606 return status;
3607}
3608
3609static int out_resume(struct audio_stream_out* stream)
3610{
3611 struct stream_out *out = (struct stream_out *)stream;
3612 int status = -ENOSYS;
3613 ALOGV("%s", __func__);
3614 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3615 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07003616 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003617 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
3618 status = compress_resume(out->compr);
3619 out->offload_state = OFFLOAD_STATE_PLAYING;
3620 }
3621 pthread_mutex_unlock(&out->lock);
3622 }
3623 return status;
3624}
3625
3626static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3627{
3628 struct stream_out *out = (struct stream_out *)stream;
3629 int status = -ENOSYS;
3630 ALOGV("%s", __func__);
3631 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003632 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003633 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3634 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3635 else
3636 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3637 pthread_mutex_unlock(&out->lock);
3638 }
3639 return status;
3640}
3641
3642static int out_flush(struct audio_stream_out* stream)
3643{
3644 struct stream_out *out = (struct stream_out *)stream;
3645 ALOGV("%s", __func__);
3646 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003647 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003648 stop_compressed_output_l(out);
3649 pthread_mutex_unlock(&out->lock);
3650 return 0;
3651 }
3652 return -ENOSYS;
3653}
3654
Eric Laurent0e46adf2016-12-16 12:49:24 -08003655static int out_stop(const struct audio_stream_out* stream)
3656{
3657 struct stream_out *out = (struct stream_out *)stream;
3658 struct audio_device *adev = out->dev;
3659 int ret = -ENOSYS;
3660
3661 ALOGV("%s", __func__);
3662 pthread_mutex_lock(&adev->lock);
3663 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3664 out->playback_started && out->pcm != NULL) {
3665 pcm_stop(out->pcm);
3666 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08003667 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003668 }
3669 pthread_mutex_unlock(&adev->lock);
3670 return ret;
3671}
3672
3673static int out_start(const struct audio_stream_out* stream)
3674{
3675 struct stream_out *out = (struct stream_out *)stream;
3676 struct audio_device *adev = out->dev;
3677 int ret = -ENOSYS;
3678
3679 ALOGV("%s", __func__);
3680 pthread_mutex_lock(&adev->lock);
3681 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3682 !out->playback_started && out->pcm != NULL) {
3683 ret = start_output_stream(out);
3684 if (ret == 0) {
3685 out->playback_started = true;
3686 }
3687 }
3688 pthread_mutex_unlock(&adev->lock);
3689 return ret;
3690}
3691
Phil Burkbc991042017-02-24 08:06:44 -08003692/*
3693 * Modify config->period_count based on min_size_frames
3694 */
3695static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
3696{
3697 int periodCountRequested = (min_size_frames + config->period_size - 1)
3698 / config->period_size;
3699 int periodCount = MMAP_PERIOD_COUNT_MIN;
3700
3701 ALOGV("%s original config.period_size = %d config.period_count = %d",
3702 __func__, config->period_size, config->period_count);
3703
3704 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
3705 periodCount *= 2;
3706 }
3707 config->period_count = periodCount;
3708
3709 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
3710}
3711
Eric Laurent0e46adf2016-12-16 12:49:24 -08003712static int out_create_mmap_buffer(const struct audio_stream_out *stream,
3713 int32_t min_size_frames,
3714 struct audio_mmap_buffer_info *info)
3715{
3716 struct stream_out *out = (struct stream_out *)stream;
3717 struct audio_device *adev = out->dev;
3718 int ret = 0;
3719 unsigned int offset1;
3720 unsigned int frames1;
3721 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003722 uint32_t mmap_size;
3723 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003724
3725 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003726 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003727 pthread_mutex_lock(&adev->lock);
3728
3729 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003730 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003731 ret = -EINVAL;
3732 goto exit;
3733 }
3734 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003735 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003736 ret = -ENOSYS;
3737 goto exit;
3738 }
3739 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3740 if (out->pcm_device_id < 0) {
3741 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3742 __func__, out->pcm_device_id, out->usecase);
3743 ret = -EINVAL;
3744 goto exit;
3745 }
Phil Burkbc991042017-02-24 08:06:44 -08003746
3747 adjust_mmap_period_count(&out->config, min_size_frames);
3748
Eric Laurent0e46adf2016-12-16 12:49:24 -08003749 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3750 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3751 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3752 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3753 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3754 step = "open";
3755 ret = -ENODEV;
3756 goto exit;
3757 }
3758 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3759 if (ret < 0) {
3760 step = "begin";
3761 goto exit;
3762 }
3763 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003764 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003765 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003766 ret = platform_get_mmap_data_fd(adev->platform,
3767 out->pcm_device_id, 0 /*playback*/,
3768 &info->shared_memory_fd,
3769 &mmap_size);
3770 if (ret < 0) {
3771 // Fall back to non exclusive mode
3772 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3773 } else {
3774 if (mmap_size < buffer_size) {
3775 step = "mmap";
3776 goto exit;
3777 }
3778 // FIXME: indicate exclusive mode support by returning a negative buffer size
3779 info->buffer_size_frames *= -1;
3780 }
3781 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003782
3783 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3784 if (ret < 0) {
3785 step = "commit";
3786 goto exit;
3787 }
Phil Burkbc991042017-02-24 08:06:44 -08003788
3789 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003790 ret = 0;
3791
3792 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3793 __func__, info->shared_memory_address, info->buffer_size_frames);
3794
3795exit:
3796 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003797 if (out->pcm == NULL) {
3798 ALOGE("%s: %s - %d", __func__, step, ret);
3799 } else {
3800 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003801 pcm_close(out->pcm);
3802 out->pcm = NULL;
3803 }
3804 }
3805 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003806 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003807 return ret;
3808}
3809
3810static int out_get_mmap_position(const struct audio_stream_out *stream,
3811 struct audio_mmap_position *position)
3812{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003813 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003814 struct stream_out *out = (struct stream_out *)stream;
3815 ALOGVV("%s", __func__);
3816 if (position == NULL) {
3817 return -EINVAL;
3818 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003819 lock_output_stream(out);
3820 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3821 out->pcm == NULL) {
3822 ret = -ENOSYS;
3823 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003824 }
3825
3826 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003827 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003828 if (ret < 0) {
3829 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003830 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003831 }
Andy Hungfc044e12017-03-20 09:24:22 -07003832 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003833exit:
3834 pthread_mutex_unlock(&out->lock);
3835 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003836}
3837
3838
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003839/** audio_stream_in implementation **/
3840static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3841{
3842 struct stream_in *in = (struct stream_in *)stream;
3843
3844 return in->config.rate;
3845}
3846
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003847static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003848{
3849 return -ENOSYS;
3850}
3851
3852static size_t in_get_buffer_size(const struct audio_stream *stream)
3853{
3854 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003855 return in->config.period_size * in->af_period_multiplier *
3856 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003857}
3858
3859static uint32_t in_get_channels(const struct audio_stream *stream)
3860{
3861 struct stream_in *in = (struct stream_in *)stream;
3862
3863 return in->channel_mask;
3864}
3865
vivek mehta4ed66e62016-04-15 23:33:34 -07003866static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003867{
vivek mehta4ed66e62016-04-15 23:33:34 -07003868 struct stream_in *in = (struct stream_in *)stream;
3869 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003870}
3871
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003872static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003873{
3874 return -ENOSYS;
3875}
3876
3877static int in_standby(struct audio_stream *stream)
3878{
3879 struct stream_in *in = (struct stream_in *)stream;
3880 struct audio_device *adev = in->dev;
3881 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003882 bool do_stop = true;
3883
Eric Laurent994a6932013-07-17 11:51:42 -07003884 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003885
3886 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003887
3888 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003889 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003890 audio_extn_sound_trigger_stop_lab(in);
3891 in->standby = true;
3892 }
3893
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003894 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003895 if (adev->adm_deregister_stream)
3896 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3897
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003898 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003899 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003900 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003901 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003902 in->capture_started = false;
3903 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003904 if (in->pcm) {
3905 pcm_close(in->pcm);
3906 in->pcm = NULL;
3907 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003908 adev->enable_voicerx = false;
3909 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003910 if (do_stop) {
3911 status = stop_input_stream(in);
3912 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003913 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003914 }
3915 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003916 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003917 return status;
3918}
3919
Andy Hungd13f0d32017-06-12 13:58:37 -07003920static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003921{
Andy Hungd13f0d32017-06-12 13:58:37 -07003922 struct stream_in *in = (struct stream_in *)stream;
3923
3924 // We try to get the lock for consistency,
3925 // but it isn't necessary for these variables.
3926 // If we're not in standby, we may be blocked on a read.
3927 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3928 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3929 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3930 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3931
3932 if (locked) {
3933 pthread_mutex_unlock(&in->lock);
3934 }
3935
3936 // dump error info
3937 (void)error_log_dump(
3938 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003939 return 0;
3940}
3941
3942static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3943{
3944 struct stream_in *in = (struct stream_in *)stream;
3945 struct audio_device *adev = in->dev;
3946 struct str_parms *parms;
3947 char *str;
3948 char value[32];
3949 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003950 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003951
Eric Laurent994a6932013-07-17 11:51:42 -07003952 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003953 parms = str_parms_create_str(kvpairs);
3954
3955 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3956
Eric Laurenta1478072015-09-21 17:21:52 -07003957 lock_input_stream(in);
3958
Eric Laurent150dbfe2013-02-27 14:31:02 -08003959 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003960 if (ret >= 0) {
3961 val = atoi(value);
3962 /* no audio source uses val == 0 */
3963 if ((in->source != val) && (val != 0)) {
3964 in->source = val;
3965 }
3966 }
3967
3968 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003969
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003970 if (ret >= 0) {
3971 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003972 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003973
3974 // Workaround: If routing to an non existing usb device, fail gracefully
3975 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003976 int card;
3977 if (audio_is_usb_in_device(val) &&
3978 (card = get_alive_usb_card(parms)) >= 0) {
3979
3980 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003981 status = -ENOSYS;
3982 } else {
3983
3984 in->device = val;
3985 /* If recording is in progress, change the tx device to new device */
3986 if (!in->standby) {
3987 ALOGV("update input routing change");
3988 // inform adm before actual routing to prevent glitches.
3989 if (adev->adm_on_routing_change) {
3990 adev->adm_on_routing_change(adev->adm_data,
3991 in->capture_handle);
3992 }
3993 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003994 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003995 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003996 }
3997 }
3998
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003999 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004000 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004001
4002 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07004003 ALOGV("%s: exit: status(%d)", __func__, status);
4004 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004005}
4006
Haynes Mathew George569b7482017-05-08 14:44:27 -07004007static char* in_get_parameters(const struct audio_stream *stream,
4008 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004009{
Haynes Mathew George569b7482017-05-08 14:44:27 -07004010 struct stream_in *in = (struct stream_in *)stream;
4011 struct str_parms *query = str_parms_create_str(keys);
4012 char *str;
4013 struct str_parms *reply = str_parms_create();
4014 bool replied = false;
4015
4016 ALOGV("%s: enter: keys - %s", __func__, keys);
4017 replied |= stream_get_parameter_channels(query, reply,
4018 &in->supported_channel_masks[0]);
4019 replied |= stream_get_parameter_formats(query, reply,
4020 &in->supported_formats[0]);
4021 replied |= stream_get_parameter_rates(query, reply,
4022 &in->supported_sample_rates[0]);
4023 if (replied) {
4024 str = str_parms_to_str(reply);
4025 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07004026 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07004027 }
4028 str_parms_destroy(query);
4029 str_parms_destroy(reply);
4030 ALOGV("%s: exit: returns - %s", __func__, str);
4031 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004032}
4033
Eric Laurent51f3c662018-04-10 18:21:34 -07004034static int in_set_gain(struct audio_stream_in *stream, float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004035{
Eric Laurent51f3c662018-04-10 18:21:34 -07004036 struct stream_in *in = (struct stream_in *)stream;
4037 char mixer_ctl_name[128];
4038 struct mixer_ctl *ctl;
4039 int ctl_value;
4040
4041 ALOGV("%s: gain %f", __func__, gain);
4042
4043 if (stream == NULL)
4044 return -EINVAL;
4045
4046 /* in_set_gain() only used to silence MMAP capture for now */
4047 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
4048 return -ENOSYS;
4049
4050 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
4051
4052 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
4053 if (!ctl) {
4054 ALOGW("%s: Could not get ctl for mixer cmd - %s",
4055 __func__, mixer_ctl_name);
4056 return -ENOSYS;
4057 }
4058
4059 if (gain < RECORD_GAIN_MIN)
4060 gain = RECORD_GAIN_MIN;
4061 else if (gain > RECORD_GAIN_MAX)
4062 gain = RECORD_GAIN_MAX;
4063 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
4064
4065 mixer_ctl_set_value(ctl, 0, ctl_value);
4066 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004067}
4068
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004069static void in_snd_mon_cb(void * stream, struct str_parms * parms)
4070{
4071 if (!stream || !parms)
4072 return;
4073
4074 struct stream_in *in = (struct stream_in *)stream;
4075 struct audio_device *adev = in->dev;
4076
4077 card_status_t status;
4078 int card;
4079 if (parse_snd_card_status(parms, &card, &status) < 0)
4080 return;
4081
4082 pthread_mutex_lock(&adev->lock);
4083 bool valid_cb = (card == adev->snd_card);
4084 pthread_mutex_unlock(&adev->lock);
4085
4086 if (!valid_cb)
4087 return;
4088
4089 lock_input_stream(in);
4090 if (in->card_status != status)
4091 in->card_status = status;
4092 pthread_mutex_unlock(&in->lock);
4093
4094 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
4095 use_case_table[in->usecase],
4096 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4097
4098 // a better solution would be to report error back to AF and let
4099 // it put the stream to standby
4100 if (status == CARD_STATUS_OFFLINE)
4101 in_standby(&in->stream.common);
4102
4103 return;
4104}
4105
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004106static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
4107 size_t bytes)
4108{
4109 struct stream_in *in = (struct stream_in *)stream;
4110 struct audio_device *adev = in->dev;
4111 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07004112 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07004113 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004114
Eric Laurenta1478072015-09-21 17:21:52 -07004115 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07004116 const size_t frame_size = audio_stream_in_frame_size(stream);
4117 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07004118
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004119 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004120 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004121 /* Read from sound trigger HAL */
4122 audio_extn_sound_trigger_read(in, buffer, bytes);
4123 pthread_mutex_unlock(&in->lock);
4124 return bytes;
4125 }
4126
Eric Laurent0e46adf2016-12-16 12:49:24 -08004127 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
4128 ret = -ENOSYS;
4129 goto exit;
4130 }
4131
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004132 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004133 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004134 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004135 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004136 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004137 goto exit;
4138 }
4139 in->standby = 0;
4140 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004141
Andy Hungd13f0d32017-06-12 13:58:37 -07004142 // errors that occur here are read errors.
4143 error_code = ERROR_CODE_READ;
4144
Haynes Mathew George03c40102016-01-29 17:57:48 -08004145 //what's the duration requested by the client?
4146 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
4147 in->config.rate;
4148 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004149
Haynes Mathew George03c40102016-01-29 17:57:48 -08004150 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004151 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08004152 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004153 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07004154 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004155 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004156 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004157 if (ret < 0) {
4158 ALOGE("Failed to read w/err %s", strerror(errno));
4159 ret = -errno;
4160 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004161 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4162 if (bytes % 4 == 0) {
4163 /* data from DSP comes in 24_8 format, convert it to 8_24 */
4164 int_buf_stream = buffer;
4165 for (size_t itt=0; itt < bytes/4 ; itt++) {
4166 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07004167 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004168 } else {
4169 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
4170 ret = -EINVAL;
4171 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07004172 }
4173 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004174 }
4175
Haynes Mathew George03c40102016-01-29 17:57:48 -08004176 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004177
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004178 /*
4179 * Instead of writing zeroes here, we could trust the hardware
4180 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004181 * 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 -08004182 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08004183 if (ret == 0 && adev->mic_muted &&
4184 !voice_is_in_call_rec_stream(in) &&
4185 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004186 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07004187 in->frames_muted += frames;
4188 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004189
4190exit:
4191 pthread_mutex_unlock(&in->lock);
4192
4193 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07004194 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004195 in_standby(&in->stream.common);
4196 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07004197 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08004198 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07004199 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08004200 }
4201 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07004202 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004203 }
4204 return bytes;
4205}
4206
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004207static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004208{
4209 return 0;
4210}
4211
Andy Hung6ebe5962016-01-15 17:46:57 -08004212static int in_get_capture_position(const struct audio_stream_in *stream,
4213 int64_t *frames, int64_t *time)
4214{
4215 if (stream == NULL || frames == NULL || time == NULL) {
4216 return -EINVAL;
4217 }
4218 struct stream_in *in = (struct stream_in *)stream;
4219 int ret = -ENOSYS;
4220
4221 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08004222 // note: ST sessions do not close the alsa pcm driver synchronously
4223 // on standby. Therefore, we may return an error even though the
4224 // pcm stream is still opened.
4225 if (in->standby) {
4226 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
4227 "%s stream in standby but pcm not NULL for non ST session", __func__);
4228 goto exit;
4229 }
Andy Hung6ebe5962016-01-15 17:46:57 -08004230 if (in->pcm) {
4231 struct timespec timestamp;
4232 unsigned int avail;
4233 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
4234 *frames = in->frames_read + avail;
4235 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
4236 ret = 0;
4237 }
4238 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08004239exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08004240 pthread_mutex_unlock(&in->lock);
4241 return ret;
4242}
4243
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004244static int add_remove_audio_effect(const struct audio_stream *stream,
4245 effect_handle_t effect,
4246 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004247{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004248 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004249 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004250 int status = 0;
4251 effect_descriptor_t desc;
4252
4253 status = (*effect)->get_descriptor(effect, &desc);
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004254 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
4255
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004256 if (status != 0)
4257 return status;
4258
Eric Laurenta1478072015-09-21 17:21:52 -07004259 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004260 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07004261 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07004262 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07004263 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004264 in->enable_aec != enable &&
4265 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
4266 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004267 if (!enable)
4268 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07004269 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
4270 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
4271 adev->enable_voicerx = enable;
4272 struct audio_usecase *usecase;
4273 struct listnode *node;
4274 list_for_each(node, &adev->usecase_list) {
4275 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07004276 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07004277 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05004278 }
4279 }
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004280 if (!in->standby
4281 && enable_disable_effect(in->dev, in, EFFECT_AEC, enable) == -ENOSYS)
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004282 select_devices(in->dev, in->usecase);
4283 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07004284 if (in->enable_ns != enable &&
4285 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
4286 in->enable_ns = enable;
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004287 if (!in->standby) {
4288 if (in->source != AUDIO_SOURCE_VOICE_COMMUNICATION
4289 || enable_disable_effect(in->dev, in, EFFECT_NS, enable) == -ENOSYS)
4290 select_devices(in->dev, in->usecase);
4291 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07004292 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004293 pthread_mutex_unlock(&in->dev->lock);
4294 pthread_mutex_unlock(&in->lock);
4295
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004296 return 0;
4297}
4298
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004299static int in_add_audio_effect(const struct audio_stream *stream,
4300 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004301{
Eric Laurent994a6932013-07-17 11:51:42 -07004302 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004303 return add_remove_audio_effect(stream, effect, true);
4304}
4305
4306static int in_remove_audio_effect(const struct audio_stream *stream,
4307 effect_handle_t effect)
4308{
Eric Laurent994a6932013-07-17 11:51:42 -07004309 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004310 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004311}
4312
Eric Laurent0e46adf2016-12-16 12:49:24 -08004313static int in_stop(const struct audio_stream_in* stream)
4314{
4315 struct stream_in *in = (struct stream_in *)stream;
4316 struct audio_device *adev = in->dev;
4317
4318 int ret = -ENOSYS;
4319 ALOGV("%s", __func__);
4320 pthread_mutex_lock(&adev->lock);
4321 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4322 in->capture_started && in->pcm != NULL) {
4323 pcm_stop(in->pcm);
4324 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08004325 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004326 }
4327 pthread_mutex_unlock(&adev->lock);
4328 return ret;
4329}
4330
4331static int in_start(const struct audio_stream_in* stream)
4332{
4333 struct stream_in *in = (struct stream_in *)stream;
4334 struct audio_device *adev = in->dev;
4335 int ret = -ENOSYS;
4336
4337 ALOGV("%s in %p", __func__, in);
4338 pthread_mutex_lock(&adev->lock);
4339 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4340 !in->capture_started && in->pcm != NULL) {
4341 if (!in->capture_started) {
4342 ret = start_input_stream(in);
4343 if (ret == 0) {
4344 in->capture_started = true;
4345 }
4346 }
4347 }
4348 pthread_mutex_unlock(&adev->lock);
4349 return ret;
4350}
4351
4352static int in_create_mmap_buffer(const struct audio_stream_in *stream,
4353 int32_t min_size_frames,
4354 struct audio_mmap_buffer_info *info)
4355{
4356 struct stream_in *in = (struct stream_in *)stream;
4357 struct audio_device *adev = in->dev;
4358 int ret = 0;
4359 unsigned int offset1;
4360 unsigned int frames1;
4361 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07004362 uint32_t mmap_size;
4363 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004364
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004365 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004366 pthread_mutex_lock(&adev->lock);
4367 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08004368
Eric Laurent0e46adf2016-12-16 12:49:24 -08004369 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004370 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004371 ret = -EINVAL;
4372 goto exit;
4373 }
4374 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08004375 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004376 ALOGV("%s in %p", __func__, in);
4377 ret = -ENOSYS;
4378 goto exit;
4379 }
4380 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
4381 if (in->pcm_device_id < 0) {
4382 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4383 __func__, in->pcm_device_id, in->usecase);
4384 ret = -EINVAL;
4385 goto exit;
4386 }
Phil Burkbc991042017-02-24 08:06:44 -08004387
4388 adjust_mmap_period_count(&in->config, min_size_frames);
4389
Eric Laurent0e46adf2016-12-16 12:49:24 -08004390 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4391 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
4392 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
4393 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
4394 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
4395 step = "open";
4396 ret = -ENODEV;
4397 goto exit;
4398 }
4399
4400 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
4401 if (ret < 0) {
4402 step = "begin";
4403 goto exit;
4404 }
4405 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07004406 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004407 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07004408 ret = platform_get_mmap_data_fd(adev->platform,
4409 in->pcm_device_id, 1 /*capture*/,
4410 &info->shared_memory_fd,
4411 &mmap_size);
4412 if (ret < 0) {
4413 // Fall back to non exclusive mode
4414 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
4415 } else {
4416 if (mmap_size < buffer_size) {
4417 step = "mmap";
4418 goto exit;
4419 }
4420 // FIXME: indicate exclusive mode support by returning a negative buffer size
4421 info->buffer_size_frames *= -1;
4422 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08004423
Haynes Mathew George96483a22017-03-28 14:52:47 -07004424 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004425
4426 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4427 if (ret < 0) {
4428 step = "commit";
4429 goto exit;
4430 }
4431
Phil Burkbc991042017-02-24 08:06:44 -08004432 in->standby = false;
4433 ret = 0;
4434
Eric Laurent0e46adf2016-12-16 12:49:24 -08004435 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4436 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004437
4438exit:
4439 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004440 if (in->pcm == NULL) {
4441 ALOGE("%s: %s - %d", __func__, step, ret);
4442 } else {
4443 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08004444 pcm_close(in->pcm);
4445 in->pcm = NULL;
4446 }
4447 }
4448 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004449 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004450 return ret;
4451}
4452
4453static int in_get_mmap_position(const struct audio_stream_in *stream,
4454 struct audio_mmap_position *position)
4455{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004456 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004457 struct stream_in *in = (struct stream_in *)stream;
4458 ALOGVV("%s", __func__);
4459 if (position == NULL) {
4460 return -EINVAL;
4461 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004462 lock_input_stream(in);
4463 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
4464 in->pcm == NULL) {
4465 ret = -ENOSYS;
4466 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004467 }
4468 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004469 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004470 if (ret < 0) {
4471 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004472 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004473 }
Andy Hungfc044e12017-03-20 09:24:22 -07004474 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004475exit:
4476 pthread_mutex_unlock(&in->lock);
4477 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004478}
4479
jiabin8962a4d2018-03-19 18:21:24 -07004480static int in_get_active_microphones(const struct audio_stream_in *stream,
4481 struct audio_microphone_characteristic_t *mic_array,
4482 size_t *mic_count) {
4483 struct stream_in *in = (struct stream_in *)stream;
4484 struct audio_device *adev = in->dev;
4485 ALOGVV("%s", __func__);
4486
4487 lock_input_stream(in);
4488 pthread_mutex_lock(&adev->lock);
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004489 int ret = platform_get_active_microphones(adev->platform,
jiabin8962a4d2018-03-19 18:21:24 -07004490 audio_channel_count_from_in_mask(in->channel_mask),
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004491 in->usecase, mic_array, mic_count);
jiabin8962a4d2018-03-19 18:21:24 -07004492 pthread_mutex_unlock(&adev->lock);
4493 pthread_mutex_unlock(&in->lock);
4494
4495 return ret;
4496}
4497
4498static int adev_get_microphones(const struct audio_hw_device *dev,
4499 struct audio_microphone_characteristic_t *mic_array,
4500 size_t *mic_count) {
4501 struct audio_device *adev = (struct audio_device *)dev;
4502 ALOGVV("%s", __func__);
4503
4504 pthread_mutex_lock(&adev->lock);
4505 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
4506 pthread_mutex_unlock(&adev->lock);
4507
4508 return ret;
4509}
Eric Laurent0e46adf2016-12-16 12:49:24 -08004510
Paul McLean57530d52018-12-17 08:24:21 -07004511static int in_set_microphone_direction(const struct audio_stream_in *stream,
4512 audio_microphone_direction_t dir) {
4513 (void)stream;
4514 (void)dir;
4515 ALOGVV("%s", __func__);
4516 return -ENOSYS;
4517}
4518
4519static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
4520 (void)stream;
4521 (void)zoom;
4522 ALOGVV("%s", __func__);
4523 return -ENOSYS;
4524}
4525
juyuchenba338cd2019-01-21 11:57:17 +08004526static void in_update_sink_metadata(struct audio_stream_in *stream,
4527 const struct sink_metadata *sink_metadata) {
4528
4529 if (stream == NULL
4530 || sink_metadata == NULL
4531 || sink_metadata->tracks == NULL) {
4532 return;
4533 }
4534
4535 int error = 0;
4536 struct stream_in *in = (struct stream_in *)stream;
4537 struct audio_device *adev = in->dev;
4538 audio_devices_t device = AUDIO_DEVICE_NONE;
4539
4540 if (sink_metadata->track_count != 0)
4541 device = sink_metadata->tracks->dest_device;
4542
4543 lock_input_stream(in);
4544 pthread_mutex_lock(&adev->lock);
4545 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, device);
4546
4547 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY
4548 && device != AUDIO_DEVICE_NONE
4549 && adev->voice_tx_output != NULL) {
4550 /* Use the rx device from afe-proxy record to route voice call because
4551 there is no routing if tx device is on primary hal and rx device
4552 is on other hal during voice call. */
4553 adev->voice_tx_output->devices = device;
4554
4555 if (!voice_is_call_state_active(adev)) {
4556 if (adev->mode == AUDIO_MODE_IN_CALL) {
4557 adev->current_call_output = adev->voice_tx_output;
4558 error = voice_start_call(adev);
4559 if (error != 0)
4560 ALOGE("%s: start voice call failed %d", __func__, error);
4561 }
4562 } else {
4563 adev->current_call_output = adev->voice_tx_output;
4564 voice_update_devices_for_all_voice_usecases(adev);
4565 }
4566 }
4567
4568 pthread_mutex_unlock(&adev->lock);
4569 pthread_mutex_unlock(&in->lock);
4570}
4571
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004572static int adev_open_output_stream(struct audio_hw_device *dev,
4573 audio_io_handle_t handle,
4574 audio_devices_t devices,
4575 audio_output_flags_t flags,
4576 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07004577 struct audio_stream_out **stream_out,
4578 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004579{
4580 struct audio_device *adev = (struct audio_device *)dev;
4581 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004582 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004583 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
4584 bool is_usb_dev = audio_is_usb_out_device(devices) &&
4585 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08004586 bool force_haptic_path =
4587 property_get_bool("vendor.audio.test_haptic", false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004588
Andy Hungd9653bd2017-08-01 19:31:39 -07004589 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
4590 return -ENOSYS;
4591 }
4592
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004593 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
4594 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08004595
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004596 *stream_out = NULL;
4597 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4598
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004599 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
4600
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004601 if (devices == AUDIO_DEVICE_NONE)
4602 devices = AUDIO_DEVICE_OUT_SPEAKER;
4603
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004604 out->flags = flags;
4605 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004606 out->dev = adev;
Eric Laurentc4aef752013-09-12 17:45:53 -07004607 out->handle = handle;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004608 out->a2dp_compress_mute = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004609
4610 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004611 if ((is_hdmi || is_usb_dev) &&
4612 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
4613 (flags == AUDIO_OUTPUT_FLAG_NONE ||
4614 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Eric Laurentab805ee2018-03-30 12:20:38 -07004615 audio_format_t req_format = config->format;
4616 audio_channel_mask_t req_channel_mask = config->channel_mask;
4617 uint32_t req_sample_rate = config->sample_rate;
4618
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004619 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004620 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004621 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004622 if (config->sample_rate == 0)
4623 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Eric Laurentab805ee2018-03-30 12:20:38 -07004624 if (config->channel_mask == AUDIO_CHANNEL_NONE)
Haynes Mathew George569b7482017-05-08 14:44:27 -07004625 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
4626 if (config->format == AUDIO_FORMAT_DEFAULT)
4627 config->format = AUDIO_FORMAT_PCM_16_BIT;
4628 } else if (is_usb_dev) {
4629 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
4630 &config->format,
4631 &out->supported_formats[0],
4632 MAX_SUPPORTED_FORMATS,
4633 &config->channel_mask,
4634 &out->supported_channel_masks[0],
4635 MAX_SUPPORTED_CHANNEL_MASKS,
4636 &config->sample_rate,
4637 &out->supported_sample_rates[0],
4638 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004639 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004640 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004641 pthread_mutex_unlock(&adev->lock);
Eric Laurentab805ee2018-03-30 12:20:38 -07004642 if (ret != 0) {
4643 // For MMAP NO IRQ, allow conversions in ADSP
4644 if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
4645 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004646
Eric Laurentab805ee2018-03-30 12:20:38 -07004647 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
4648 config->sample_rate = req_sample_rate;
4649 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
4650 config->channel_mask = req_channel_mask;
4651 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
4652 config->format = req_format;
4653 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004654
Haynes Mathew George569b7482017-05-08 14:44:27 -07004655 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004656 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004657 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004658 if (is_hdmi) {
4659 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4660 out->config = pcm_config_hdmi_multi;
4661 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
4662 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4663 out->config = pcm_config_mmap_playback;
4664 out->stream.start = out_start;
4665 out->stream.stop = out_stop;
4666 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4667 out->stream.get_mmap_position = out_get_mmap_position;
4668 } else {
4669 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4670 out->config = pcm_config_hifi;
4671 }
4672
4673 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004674 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004675 if (is_hdmi) {
4676 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
4677 audio_bytes_per_sample(out->format));
4678 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004679 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004680 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07004681 pthread_mutex_lock(&adev->lock);
4682 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4683 pthread_mutex_unlock(&adev->lock);
4684
4685 // reject offload during card offline to allow
4686 // fallback to s/w paths
4687 if (offline) {
4688 ret = -ENODEV;
4689 goto error_open;
4690 }
4691
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004692 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4693 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4694 ALOGE("%s: Unsupported Offload information", __func__);
4695 ret = -EINVAL;
4696 goto error_open;
4697 }
4698 if (!is_supported_format(config->offload_info.format)) {
4699 ALOGE("%s: Unsupported audio format", __func__);
4700 ret = -EINVAL;
4701 goto error_open;
4702 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004703 out->sample_rate = config->offload_info.sample_rate;
4704 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
4705 out->channel_mask = config->offload_info.channel_mask;
4706 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
4707 out->channel_mask = config->channel_mask;
4708 else
4709 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4710
4711 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004712
4713 out->compr_config.codec = (struct snd_codec *)
4714 calloc(1, sizeof(struct snd_codec));
4715
4716 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004717
4718 out->stream.set_callback = out_set_callback;
4719 out->stream.pause = out_pause;
4720 out->stream.resume = out_resume;
4721 out->stream.drain = out_drain;
4722 out->stream.flush = out_flush;
4723
4724 out->compr_config.codec->id =
4725 get_snd_codec_id(config->offload_info.format);
4726 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
4727 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004728 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004729 out->compr_config.codec->bit_rate =
4730 config->offload_info.bit_rate;
4731 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004732 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004733 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
4734
4735 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4736 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004737
4738 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004739 create_offload_callback_thread(out);
4740 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4741 __func__, config->offload_info.version,
4742 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02004743 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4744 switch (config->sample_rate) {
4745 case 0:
4746 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4747 break;
4748 case 8000:
4749 case 16000:
4750 case 48000:
4751 out->sample_rate = config->sample_rate;
4752 break;
4753 default:
4754 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
4755 config->sample_rate);
4756 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4757 ret = -EINVAL;
4758 goto error_open;
4759 }
4760 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4761 switch (config->channel_mask) {
4762 case AUDIO_CHANNEL_NONE:
4763 case AUDIO_CHANNEL_OUT_STEREO:
4764 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4765 break;
4766 default:
4767 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
4768 config->channel_mask);
4769 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4770 ret = -EINVAL;
4771 goto error_open;
4772 }
4773 switch (config->format) {
4774 case AUDIO_FORMAT_DEFAULT:
4775 case AUDIO_FORMAT_PCM_16_BIT:
4776 out->format = AUDIO_FORMAT_PCM_16_BIT;
4777 break;
4778 default:
4779 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
4780 config->format);
4781 config->format = AUDIO_FORMAT_PCM_16_BIT;
4782 ret = -EINVAL;
4783 goto error_open;
4784 }
4785
4786 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004787 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004788 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004789 case 0:
4790 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
4791 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07004792 case 8000:
4793 case 16000:
4794 case 48000:
4795 out->sample_rate = config->sample_rate;
4796 break;
4797 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004798 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
4799 config->sample_rate);
4800 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4801 ret = -EINVAL;
4802 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004803 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004804 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4805 switch (config->channel_mask) {
4806 case AUDIO_CHANNEL_NONE:
4807 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4808 break;
4809 case AUDIO_CHANNEL_OUT_STEREO:
4810 out->channel_mask = config->channel_mask;
4811 break;
4812 default:
4813 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
4814 config->channel_mask);
4815 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4816 ret = -EINVAL;
4817 break;
4818 }
4819 switch (config->format) {
4820 case AUDIO_FORMAT_DEFAULT:
4821 out->format = AUDIO_FORMAT_PCM_16_BIT;
4822 break;
4823 case AUDIO_FORMAT_PCM_16_BIT:
4824 out->format = config->format;
4825 break;
4826 default:
4827 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
4828 config->format);
4829 config->format = AUDIO_FORMAT_PCM_16_BIT;
4830 ret = -EINVAL;
4831 break;
4832 }
4833 if (ret != 0)
4834 goto error_open;
4835
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004836 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4837 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004838 out->config.rate = out->sample_rate;
4839 out->config.channels =
4840 audio_channel_count_from_out_mask(out->channel_mask);
4841 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004842 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004843 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
4844 switch (config->sample_rate) {
4845 case 0:
4846 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4847 break;
4848 case 8000:
4849 case 16000:
4850 case 32000:
4851 case 48000:
4852 out->sample_rate = config->sample_rate;
4853 break;
4854 default:
4855 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
4856 config->sample_rate);
4857 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4858 ret = -EINVAL;
4859 break;
4860 }
Eric Laurentad2dde92017-09-20 18:27:31 -07004861 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004862 switch (config->channel_mask) {
4863 case AUDIO_CHANNEL_NONE:
4864 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4865 break;
4866 case AUDIO_CHANNEL_OUT_STEREO:
4867 out->channel_mask = config->channel_mask;
4868 break;
4869 default:
4870 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
4871 config->channel_mask);
4872 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4873 ret = -EINVAL;
4874 break;
4875 }
4876 switch (config->format) {
4877 case AUDIO_FORMAT_DEFAULT:
4878 out->format = AUDIO_FORMAT_PCM_16_BIT;
4879 break;
4880 case AUDIO_FORMAT_PCM_16_BIT:
4881 out->format = config->format;
4882 break;
4883 default:
4884 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
4885 config->format);
4886 config->format = AUDIO_FORMAT_PCM_16_BIT;
4887 ret = -EINVAL;
4888 break;
4889 }
4890 if (ret != 0)
4891 goto error_open;
4892
vivek mehtaa68fea62017-06-08 19:04:02 -07004893 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07004894 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4895 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004896 out->config.rate = out->sample_rate;
4897 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07004898 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004899 out->sample_rate,
4900 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07004901 out->config.channels,
4902 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004903 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07004904 out->config.period_size = buffer_size / frame_size;
4905 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
4906 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004907 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004908 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07004909 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4910 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004911 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07004912 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
4913 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004914 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07004915 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004916 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004917 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004918 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004919 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4920 out->config = pcm_config_mmap_playback;
4921 out->stream.start = out_start;
4922 out->stream.stop = out_stop;
4923 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4924 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004925 } else {
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08004926 if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
4927 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
4928 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
4929 if (adev->haptic_pcm_device_id < 0) {
4930 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
4931 __func__, adev->haptic_pcm_device_id, out->usecase);
4932 ret = -ENOSYS;
4933 goto error_open;
4934 }
4935 out->config = pcm_config_haptics_audio;
4936 if (force_haptic_path)
4937 adev->haptics_config = pcm_config_haptics_audio;
4938 else
4939 adev->haptics_config = pcm_config_haptics;
4940 } else {
4941 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4942 out->config = pcm_config_low_latency;
4943 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07004944 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004945
4946 if (config->sample_rate == 0) {
4947 out->sample_rate = out->config.rate;
4948 } else {
4949 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004950 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08004951
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004952 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
4953 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
4954 } else {
4955 out->channel_mask = config->channel_mask;
4956 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08004957
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004958 if (config->format == AUDIO_FORMAT_DEFAULT)
4959 out->format = audio_format_from_pcm_format(out->config.format);
4960 else if (!audio_is_linear_pcm(config->format)) {
4961 config->format = AUDIO_FORMAT_PCM_16_BIT;
4962 ret = -EINVAL;
4963 goto error_open;
4964 } else {
4965 out->format = config->format;
4966 }
4967
4968 out->config.rate = out->sample_rate;
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08004969
4970 if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
4971 out->config.channels =
4972 audio_channel_count_from_out_mask(out->channel_mask &
4973 ~AUDIO_CHANNEL_HAPTIC_ALL);
4974
4975 if (force_haptic_path) {
4976 out->config.channels = 1;
4977 adev->haptics_config.channels = 1;
4978 } else {
4979 adev->haptics_config.channels =
4980 audio_channel_count_from_out_mask(out->channel_mask &
4981 AUDIO_CHANNEL_HAPTIC_ALL);
4982 }
4983 } else {
4984 out->config.channels =
4985 audio_channel_count_from_out_mask(out->channel_mask);
4986 }
4987
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004988 if (out->format != audio_format_from_pcm_format(out->config.format)) {
4989 out->config.format = pcm_format_from_audio_format(out->format);
4990 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004991 }
Kevin Rocard50eff892017-05-02 16:52:05 -07004992
4993 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
4994 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004995 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004996 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
4997 __func__, config->sample_rate, config->format, config->channel_mask);
4998 config->sample_rate = out->sample_rate;
4999 config->format = out->format;
5000 config->channel_mask = out->channel_mask;
5001 ret = -EINVAL;
5002 goto error_open;
5003 }
5004
Andy Hung6fcba9c2014-03-18 11:53:32 -07005005 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
5006 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005007
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005008 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005009 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005010 adev->primary_output = out;
5011 else {
5012 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005013 ret = -EEXIST;
5014 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005015 }
5016 }
5017
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005018 /* Check if this usecase is already existing */
5019 pthread_mutex_lock(&adev->lock);
5020 if (get_usecase_from_list(adev, out->usecase) != NULL) {
5021 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005022 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005023 ret = -EEXIST;
5024 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005025 }
5026 pthread_mutex_unlock(&adev->lock);
5027
5028 out->stream.common.get_sample_rate = out_get_sample_rate;
5029 out->stream.common.set_sample_rate = out_set_sample_rate;
5030 out->stream.common.get_buffer_size = out_get_buffer_size;
5031 out->stream.common.get_channels = out_get_channels;
5032 out->stream.common.get_format = out_get_format;
5033 out->stream.common.set_format = out_set_format;
5034 out->stream.common.standby = out_standby;
5035 out->stream.common.dump = out_dump;
5036 out->stream.common.set_parameters = out_set_parameters;
5037 out->stream.common.get_parameters = out_get_parameters;
5038 out->stream.common.add_audio_effect = out_add_audio_effect;
5039 out->stream.common.remove_audio_effect = out_remove_audio_effect;
5040 out->stream.get_latency = out_get_latency;
5041 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07005042#ifdef NO_AUDIO_OUT
5043 out->stream.write = out_write_for_no_output;
5044#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005045 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07005046#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005047 out->stream.get_render_position = out_get_render_position;
5048 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005049 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005050
Eric Laurent0e46adf2016-12-16 12:49:24 -08005051 if (out->realtime)
5052 out->af_period_multiplier = af_period_multiplier;
5053 else
5054 out->af_period_multiplier = 1;
5055
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005056 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07005057 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005058 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005059
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005060 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005061 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005062 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
5063
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005064 config->format = out->stream.common.get_format(&out->stream.common);
5065 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
5066 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
5067
Kevin Rocarda325aa22018-04-03 09:15:52 -07005068 register_format(out->format, out->supported_formats);
5069 register_channel_mask(out->channel_mask, out->supported_channel_masks);
5070 register_sample_rate(out->sample_rate, out->supported_sample_rates);
5071
Andy Hunga452b0a2017-03-15 14:51:15 -07005072 out->error_log = error_log_create(
5073 ERROR_LOG_ENTRIES,
5074 1000000000 /* aggregate consecutive identical errors within one second in ns */);
5075
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005076 /*
5077 By locking output stream before registering, we allow the callback
5078 to update stream's state only after stream's initial state is set to
5079 adev state.
5080 */
5081 lock_output_stream(out);
5082 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
5083 pthread_mutex_lock(&adev->lock);
5084 out->card_status = adev->card_status;
5085 pthread_mutex_unlock(&adev->lock);
5086 pthread_mutex_unlock(&out->lock);
5087
vivek mehta4a824772017-06-08 19:05:49 -07005088 stream_app_type_cfg_init(&out->app_type_cfg);
5089
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005090 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005091
Eric Laurent994a6932013-07-17 11:51:42 -07005092 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005093 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005094
5095error_open:
5096 free(out);
5097 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07005098 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005099 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005100}
5101
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005102static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005103 struct audio_stream_out *stream)
5104{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005105 struct stream_out *out = (struct stream_out *)stream;
5106 struct audio_device *adev = out->dev;
5107
Eric Laurent994a6932013-07-17 11:51:42 -07005108 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005109
5110 // must deregister from sndmonitor first to prevent races
5111 // between the callback and close_stream
5112 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005113 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005114 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
5115 destroy_offload_callback_thread(out);
5116
5117 if (out->compr_config.codec != NULL)
5118 free(out->compr_config.codec);
5119 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07005120
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005121 out->a2dp_compress_mute = false;
5122
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07005123 if (adev->voice_tx_output == out)
5124 adev->voice_tx_output = NULL;
5125
Andy Hunga452b0a2017-03-15 14:51:15 -07005126 error_log_destroy(out->error_log);
5127 out->error_log = NULL;
5128
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005129 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005130 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005131 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005132 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07005133 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005134}
5135
5136static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
5137{
5138 struct audio_device *adev = (struct audio_device *)dev;
5139 struct str_parms *parms;
5140 char *str;
5141 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005142 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005143 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07005144 int status = 0;
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005145 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005146
Joe Onorato188b6222016-03-01 11:02:27 -08005147 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005148
5149 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005150
5151 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005152 status = voice_set_parameters(adev, parms);
5153 if (status != 0) {
5154 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005155 }
5156
5157 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
5158 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07005159 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005160 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5161 adev->bluetooth_nrec = true;
5162 else
5163 adev->bluetooth_nrec = false;
5164 }
5165
5166 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
5167 if (ret >= 0) {
5168 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5169 adev->screen_off = false;
5170 else
5171 adev->screen_off = true;
5172 }
5173
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005174 ret = str_parms_get_int(parms, "rotation", &val);
5175 if (ret >= 0) {
5176 bool reverse_speakers = false;
Eric Laurent5f4ca952018-10-19 17:33:43 -07005177 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005178 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005179 // FIXME: note that the code below assumes that the speakers are in the correct placement
5180 // relative to the user when the device is rotated 90deg from its default rotation. This
5181 // assumption is device-specific, not platform-specific like this code.
5182 case 270:
5183 reverse_speakers = true;
Eric Laurent5f4ca952018-10-19 17:33:43 -07005184 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005185 break;
5186 case 0:
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005187 case 180:
Eric Laurent5f4ca952018-10-19 17:33:43 -07005188 camera_rotation = CAMERA_ROTATION_PORTRAIT;
5189 break;
5190 case 90:
5191 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005192 break;
5193 default:
5194 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07005195 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005196 }
Eric Laurent03f09432014-03-25 18:09:11 -07005197 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07005198 // check and set swap
5199 // - check if orientation changed and speaker active
5200 // - set rotation and cache the rotation value
Eric Laurent5f4ca952018-10-19 17:33:43 -07005201 adev->camera_orientation =
5202 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
5203#ifndef MAXXAUDIO_QDSP_ENABLED
vivek mehtae59cfb22017-06-16 15:57:11 -07005204 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Eric Laurent5f4ca952018-10-19 17:33:43 -07005205#endif
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005206 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005207 }
5208
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005209 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
5210 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005211 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005212 }
5213
David Linee3fe402017-03-13 10:00:42 -07005214 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
5215 if (ret >= 0) {
5216 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07005217 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005218 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5219 if (ret >= 0) {
5220 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005221 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005222 }
Eric Laurent99dab492017-06-17 15:19:08 -07005223 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005224 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5225 if (ret >= 0) {
5226 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005227 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005228 }
5229 }
5230 }
5231
5232 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
5233 if (ret >= 0) {
5234 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07005235 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005236 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5237 if (ret >= 0) {
5238 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005239 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005240 }
Eric Laurent99dab492017-06-17 15:19:08 -07005241 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005242 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5243 if (ret >= 0) {
5244 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005245 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005246 }
5247 }
5248 }
5249
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08005250 audio_extn_hfp_set_parameters(adev, parms);
jasmine cha270b7762018-03-30 15:41:33 +08005251 audio_extn_ma_set_parameters(adev, parms);
5252
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005253 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
5254 if (status >= 0 && a2dp_reconfig) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005255 struct audio_usecase *usecase;
5256 struct listnode *node;
5257 list_for_each(node, &adev->usecase_list) {
5258 usecase = node_to_item(node, struct audio_usecase, list);
5259 if ((usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005260 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005261 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
5262
5263 pthread_mutex_unlock(&adev->lock);
5264 lock_output_stream(usecase->stream.out);
5265 pthread_mutex_lock(&adev->lock);
5266 audio_extn_a2dp_set_handoff_mode(true);
5267 // force device switch to reconfigure encoder
5268 select_devices(adev, usecase->id);
5269 audio_extn_a2dp_set_handoff_mode(false);
5270 pthread_mutex_unlock(&usecase->stream.out->lock);
5271 break;
5272 }
5273 }
5274 }
5275
Eric Laurent5f4ca952018-10-19 17:33:43 -07005276 //FIXME: to be replaced by proper video capture properties API
5277 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
5278 if (ret >= 0) {
5279 int camera_facing = CAMERA_FACING_BACK;
5280 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
5281 camera_facing = CAMERA_FACING_FRONT;
5282 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
5283 camera_facing = CAMERA_FACING_BACK;
5284 else {
5285 ALOGW("%s: invalid camera facing value: %s", __func__, value);
5286 goto done;
5287 }
5288 adev->camera_orientation =
5289 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
5290 struct audio_usecase *usecase;
5291 struct listnode *node;
5292 list_for_each(node, &adev->usecase_list) {
5293 usecase = node_to_item(node, struct audio_usecase, list);
5294 struct stream_in *in = usecase->stream.in;
5295 if (usecase->type == PCM_CAPTURE && in != NULL &&
5296 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
5297 select_devices(adev, in->usecase);
5298 }
5299 }
5300 }
5301
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005302done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005303 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005304 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07005305 ALOGV("%s: exit with code(%d)", __func__, status);
5306 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005307}
5308
5309static char* adev_get_parameters(const struct audio_hw_device *dev,
5310 const char *keys)
5311{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005312 struct audio_device *adev = (struct audio_device *)dev;
5313 struct str_parms *reply = str_parms_create();
5314 struct str_parms *query = str_parms_create_str(keys);
5315 char *str;
5316
5317 pthread_mutex_lock(&adev->lock);
5318
5319 voice_get_parameters(adev, query, reply);
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005320 audio_extn_a2dp_get_parameters(query, reply);
5321
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005322 str = str_parms_to_str(reply);
5323 str_parms_destroy(query);
5324 str_parms_destroy(reply);
5325
5326 pthread_mutex_unlock(&adev->lock);
5327 ALOGV("%s: exit: returns - %s", __func__, str);
5328 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005329}
5330
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005331static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005332{
5333 return 0;
5334}
5335
Haynes Mathew George5191a852013-09-11 14:19:36 -07005336static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
5337{
5338 int ret;
5339 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005340
Eric Laurent4cc4ce12014-09-10 13:21:01 -05005341 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
5342
Haynes Mathew George5191a852013-09-11 14:19:36 -07005343 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005344 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07005345 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005346
Haynes Mathew George5191a852013-09-11 14:19:36 -07005347 return ret;
5348}
5349
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005350static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005351{
5352 return -ENOSYS;
5353}
5354
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005355static int adev_get_master_volume(struct audio_hw_device *dev __unused,
5356 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005357{
5358 return -ENOSYS;
5359}
5360
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005361static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005362{
5363 return -ENOSYS;
5364}
5365
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005366static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005367{
5368 return -ENOSYS;
5369}
5370
5371static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
5372{
5373 struct audio_device *adev = (struct audio_device *)dev;
5374
5375 pthread_mutex_lock(&adev->lock);
5376 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07005377 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005378 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07005379 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
5380 voice_is_in_call(adev)) {
5381 voice_stop_call(adev);
5382 adev->current_call_output = NULL;
5383 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005384 }
5385 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05005386
5387 audio_extn_extspk_set_mode(adev->extspk, mode);
5388
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005389 return 0;
5390}
5391
5392static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
5393{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005394 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005395 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005396
Eric Laurent2bafff12016-03-17 12:17:23 -07005397 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005398 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005399 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
5400 ret = audio_extn_hfp_set_mic_mute(adev, state);
5401 } else {
5402 ret = voice_set_mic_mute(adev, state);
5403 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07005404 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00005405 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005406
5407 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005408}
5409
5410static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
5411{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005412 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005413 return 0;
5414}
5415
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005416static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005417 const struct audio_config *config)
5418{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07005419 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005420
Eric Laurent74b55762017-07-09 17:04:53 -07005421 /* Don't know if USB HIFI in this context so use true to be conservative */
5422 if (check_input_parameters(config->sample_rate, config->format, channel_count,
5423 true /*is_usb_hifi */) != 0)
5424 return 0;
5425
vivek mehtaa68fea62017-06-08 19:04:02 -07005426 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5427 config->sample_rate, config->format,
5428 channel_count,
5429 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005430}
5431
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005432static bool adev_input_allow_hifi_record(struct audio_device *adev,
5433 audio_devices_t devices,
5434 audio_input_flags_t flags,
5435 audio_source_t source) {
5436 const bool allowed = true;
5437
5438 if (!audio_is_usb_in_device(devices))
5439 return !allowed;
5440
5441 switch (flags) {
5442 case AUDIO_INPUT_FLAG_NONE:
5443 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
5444 break;
5445 default:
5446 return !allowed;
5447 }
5448
5449 switch (source) {
5450 case AUDIO_SOURCE_DEFAULT:
5451 case AUDIO_SOURCE_MIC:
5452 case AUDIO_SOURCE_UNPROCESSED:
5453 break;
5454 default:
5455 return !allowed;
5456 }
5457
5458 switch (adev->mode) {
5459 case 0:
5460 break;
5461 default:
5462 return !allowed;
5463 }
5464
5465 return allowed;
5466}
5467
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005468static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005469 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005470 audio_devices_t devices,
5471 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005472 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07005473 audio_input_flags_t flags,
5474 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05005475 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005476{
5477 struct audio_device *adev = (struct audio_device *)dev;
5478 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005479 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07005480 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005481 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005482 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005483 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
5484 devices,
5485 flags,
5486 source);
Andy Hung88ce1d92018-10-29 18:31:12 -07005487 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
5488 " sample_rate %u, channel_mask %#x, format %#x",
5489 __func__, flags, is_usb_dev, may_use_hifi_record,
5490 config->sample_rate, config->channel_mask, config->format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005491 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005492
Andy Hungd9653bd2017-08-01 19:31:39 -07005493 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
5494 return -ENOSYS;
5495 }
5496
Eric Laurent74b55762017-07-09 17:04:53 -07005497 if (!(is_usb_dev && may_use_hifi_record)) {
5498 if (config->sample_rate == 0)
5499 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
5500 if (config->channel_mask == AUDIO_CHANNEL_NONE)
5501 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5502 if (config->format == AUDIO_FORMAT_DEFAULT)
5503 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005504
Eric Laurent74b55762017-07-09 17:04:53 -07005505 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
5506
5507 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
5508 return -EINVAL;
5509 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005510
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005511 if (audio_extn_tfa_98xx_is_supported() &&
5512 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005513 return -EINVAL;
5514
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005515 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
5516
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005517 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005518 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005519
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005520 in->stream.common.get_sample_rate = in_get_sample_rate;
5521 in->stream.common.set_sample_rate = in_set_sample_rate;
5522 in->stream.common.get_buffer_size = in_get_buffer_size;
5523 in->stream.common.get_channels = in_get_channels;
5524 in->stream.common.get_format = in_get_format;
5525 in->stream.common.set_format = in_set_format;
5526 in->stream.common.standby = in_standby;
5527 in->stream.common.dump = in_dump;
5528 in->stream.common.set_parameters = in_set_parameters;
5529 in->stream.common.get_parameters = in_get_parameters;
5530 in->stream.common.add_audio_effect = in_add_audio_effect;
5531 in->stream.common.remove_audio_effect = in_remove_audio_effect;
5532 in->stream.set_gain = in_set_gain;
5533 in->stream.read = in_read;
5534 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08005535 in->stream.get_capture_position = in_get_capture_position;
jiabin8962a4d2018-03-19 18:21:24 -07005536 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLean57530d52018-12-17 08:24:21 -07005537 in->stream.set_microphone_direction = in_set_microphone_direction;
5538 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchenba338cd2019-01-21 11:57:17 +08005539 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005540
5541 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005542 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005543 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005544 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005545 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005546 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005547
Andy Hung88ce1d92018-10-29 18:31:12 -07005548 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Arun Mirpuriba2749a2018-04-17 14:32:24 -07005549 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
5550 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
5551 /* Force channel config requested to mono if incall
5552 record is being requested for only uplink/downlink */
5553 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
5554 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5555 ret = -EINVAL;
5556 goto err_open;
5557 }
5558 }
5559
Haynes Mathew George569b7482017-05-08 14:44:27 -07005560 if (is_usb_dev && may_use_hifi_record) {
5561 /* HiFi record selects an appropriate format, channel, rate combo
5562 depending on sink capabilities*/
5563 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
5564 &config->format,
5565 &in->supported_formats[0],
5566 MAX_SUPPORTED_FORMATS,
5567 &config->channel_mask,
5568 &in->supported_channel_masks[0],
5569 MAX_SUPPORTED_CHANNEL_MASKS,
5570 &config->sample_rate,
5571 &in->supported_sample_rates[0],
5572 MAX_SUPPORTED_SAMPLE_RATES);
5573 if (ret != 0) {
5574 ret = -EINVAL;
5575 goto err_open;
5576 }
Eric Laurent74b55762017-07-09 17:04:53 -07005577 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005578 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07005579 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07005580 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
5581 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
5582 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5583 bool ret_error = false;
5584 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5585 from HAL is 8_24
5586 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5587 8_24 return error indicating supported format is 8_24
5588 *> In case of any other source requesting 24 bit or float return error
5589 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07005590
vivek mehta57ff9b52016-04-28 14:13:08 -07005591 on error flinger will retry with supported format passed
5592 */
juyuchenbe5c67e2018-08-29 17:19:20 +08005593 if (!is_supported_24bits_audiosource(source)) {
vivek mehta57ff9b52016-04-28 14:13:08 -07005594 config->format = AUDIO_FORMAT_PCM_16_BIT;
5595 ret_error = true;
5596 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
5597 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
5598 ret_error = true;
5599 }
5600
5601 if (ret_error) {
5602 ret = -EINVAL;
5603 goto err_open;
5604 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005605 }
5606
vivek mehta57ff9b52016-04-28 14:13:08 -07005607 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07005608 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07005609
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005610 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005611 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
5612 if (config->sample_rate == 0)
5613 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5614 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5615 config->sample_rate != 8000) {
5616 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5617 ret = -EINVAL;
5618 goto err_open;
5619 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005620
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005621 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5622 config->format = AUDIO_FORMAT_PCM_16_BIT;
5623 ret = -EINVAL;
5624 goto err_open;
5625 }
5626
5627 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5628 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07005629 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005630 } else if (is_usb_dev && may_use_hifi_record) {
5631 in->usecase = USECASE_AUDIO_RECORD_HIFI;
5632 in->config = pcm_config_audio_capture;
5633 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005634 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5635 config->sample_rate,
5636 config->format,
5637 channel_count,
5638 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005639 in->config.period_size = buffer_size / frame_size;
5640 in->config.rate = config->sample_rate;
5641 in->af_period_multiplier = 1;
5642 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005643 } else {
5644 in->usecase = USECASE_AUDIO_RECORD;
5645 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08005646 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005647 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07005648#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005649 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07005650#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08005651 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005652 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08005653 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005654 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005655 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5656 config->sample_rate,
5657 config->format,
5658 channel_count,
5659 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005660 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005661 in->config.rate = config->sample_rate;
5662 in->af_period_multiplier = 1;
5663 } else {
5664 // period size is left untouched for rt mode playback
5665 in->config = pcm_config_audio_capture_rt;
5666 in->af_period_multiplier = af_period_multiplier;
5667 }
5668 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
5669 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005670 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08005671 in->usecase = USECASE_AUDIO_RECORD_MMAP;
5672 in->config = pcm_config_mmap_capture;
5673 in->stream.start = in_start;
5674 in->stream.stop = in_stop;
5675 in->stream.create_mmap_buffer = in_create_mmap_buffer;
5676 in->stream.get_mmap_position = in_get_mmap_position;
5677 in->af_period_multiplier = 1;
5678 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07005679 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07005680 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07005681 (config->sample_rate == 8000 ||
5682 config->sample_rate == 16000 ||
5683 config->sample_rate == 32000 ||
5684 config->sample_rate == 48000) &&
5685 channel_count == 1) {
5686 in->usecase = USECASE_AUDIO_RECORD_VOIP;
5687 in->config = pcm_config_audio_capture;
5688 frame_size = audio_stream_in_frame_size(&in->stream);
5689 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
5690 config->sample_rate,
5691 config->format,
5692 channel_count, false /*is_low_latency*/);
5693 in->config.period_size = buffer_size / frame_size;
5694 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
5695 in->config.rate = config->sample_rate;
5696 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005697 } else {
5698 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005699 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005700 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5701 config->sample_rate,
5702 config->format,
5703 channel_count,
5704 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005705 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005706 in->config.rate = config->sample_rate;
5707 in->af_period_multiplier = 1;
5708 }
5709 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
5710 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005711 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08005712
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005713 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07005714 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005715
Kevin Rocarda325aa22018-04-03 09:15:52 -07005716
5717 register_format(in->format, in->supported_formats);
5718 register_channel_mask(in->channel_mask, in->supported_channel_masks);
5719 register_sample_rate(in->sample_rate, in->supported_sample_rates);
5720
Andy Hungd13f0d32017-06-12 13:58:37 -07005721 in->error_log = error_log_create(
5722 ERROR_LOG_ENTRIES,
5723 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
5724
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005725 /* This stream could be for sound trigger lab,
5726 get sound trigger pcm if present */
5727 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005728
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005729 lock_input_stream(in);
5730 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5731 pthread_mutex_lock(&adev->lock);
5732 in->card_status = adev->card_status;
5733 pthread_mutex_unlock(&adev->lock);
5734 pthread_mutex_unlock(&in->lock);
5735
vivek mehta4a824772017-06-08 19:05:49 -07005736 stream_app_type_cfg_init(&in->app_type_cfg);
5737
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005738 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005739 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005740 return 0;
5741
5742err_open:
5743 free(in);
5744 *stream_in = NULL;
5745 return ret;
5746}
5747
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005748static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005749 struct audio_stream_in *stream)
5750{
Andy Hungd13f0d32017-06-12 13:58:37 -07005751 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005752 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005753
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005754 // must deregister from sndmonitor first to prevent races
5755 // between the callback and close_stream
5756 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005757 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07005758
5759 error_log_destroy(in->error_log);
5760 in->error_log = NULL;
5761
Andy Hung0dbb52b2017-08-09 13:51:38 -07005762 pthread_mutex_destroy(&in->pre_lock);
5763 pthread_mutex_destroy(&in->lock);
5764
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005765 free(stream);
5766
5767 return;
5768}
5769
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005770static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005771{
5772 return 0;
5773}
5774
Andy Hung31aca912014-03-20 17:14:59 -07005775/* verifies input and output devices and their capabilities.
5776 *
5777 * This verification is required when enabling extended bit-depth or
5778 * sampling rates, as not all qcom products support it.
5779 *
5780 * Suitable for calling only on initialization such as adev_open().
5781 * It fills the audio_device use_case_table[] array.
5782 *
5783 * Has a side-effect that it needs to configure audio routing / devices
5784 * in order to power up the devices and read the device parameters.
5785 * It does not acquire any hw device lock. Should restore the devices
5786 * back to "normal state" upon completion.
5787 */
5788static int adev_verify_devices(struct audio_device *adev)
5789{
5790 /* enumeration is a bit difficult because one really wants to pull
5791 * the use_case, device id, etc from the hidden pcm_device_table[].
5792 * In this case there are the following use cases and device ids.
5793 *
5794 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
5795 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005796 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07005797 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
5798 * [USECASE_AUDIO_RECORD] = {0, 0},
5799 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
5800 * [USECASE_VOICE_CALL] = {2, 2},
5801 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005802 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07005803 * USECASE_VOICE_CALL omitted, but possible for either input or output.
5804 */
5805
5806 /* should be the usecases enabled in adev_open_input_stream() */
5807 static const int test_in_usecases[] = {
5808 USECASE_AUDIO_RECORD,
5809 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
5810 };
5811 /* should be the usecases enabled in adev_open_output_stream()*/
5812 static const int test_out_usecases[] = {
5813 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
5814 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
5815 };
5816 static const usecase_type_t usecase_type_by_dir[] = {
5817 PCM_PLAYBACK,
5818 PCM_CAPTURE,
5819 };
5820 static const unsigned flags_by_dir[] = {
5821 PCM_OUT,
5822 PCM_IN,
5823 };
5824
5825 size_t i;
5826 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005827 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07005828 char info[512]; /* for possible debug info */
5829
5830 for (dir = 0; dir < 2; ++dir) {
5831 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
5832 const unsigned flags_dir = flags_by_dir[dir];
5833 const size_t testsize =
5834 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
5835 const int *testcases =
5836 dir ? test_in_usecases : test_out_usecases;
5837 const audio_devices_t audio_device =
5838 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
5839
5840 for (i = 0; i < testsize; ++i) {
5841 const audio_usecase_t audio_usecase = testcases[i];
5842 int device_id;
5843 snd_device_t snd_device;
5844 struct pcm_params **pparams;
5845 struct stream_out out;
5846 struct stream_in in;
5847 struct audio_usecase uc_info;
5848 int retval;
5849
5850 pparams = &adev->use_case_table[audio_usecase];
5851 pcm_params_free(*pparams); /* can accept null input */
5852 *pparams = NULL;
5853
5854 /* find the device ID for the use case (signed, for error) */
5855 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
5856 if (device_id < 0)
5857 continue;
5858
5859 /* prepare structures for device probing */
5860 memset(&uc_info, 0, sizeof(uc_info));
5861 uc_info.id = audio_usecase;
5862 uc_info.type = usecase_type;
5863 if (dir) {
Andy Hung31aca912014-03-20 17:14:59 -07005864 memset(&in, 0, sizeof(in));
5865 in.device = audio_device;
5866 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
5867 uc_info.stream.in = &in;
Andy Hung31aca912014-03-20 17:14:59 -07005868 }
5869 memset(&out, 0, sizeof(out));
5870 out.devices = audio_device; /* only field needed in select_devices */
5871 uc_info.stream.out = &out;
5872 uc_info.devices = audio_device;
5873 uc_info.in_snd_device = SND_DEVICE_NONE;
5874 uc_info.out_snd_device = SND_DEVICE_NONE;
5875 list_add_tail(&adev->usecase_list, &uc_info.list);
5876
5877 /* select device - similar to start_(in/out)put_stream() */
5878 retval = select_devices(adev, audio_usecase);
5879 if (retval >= 0) {
5880 *pparams = pcm_params_get(card_id, device_id, flags_dir);
5881#if LOG_NDEBUG == 0
5882 if (*pparams) {
5883 ALOGV("%s: (%s) card %d device %d", __func__,
5884 dir ? "input" : "output", card_id, device_id);
5885 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07005886 } else {
5887 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
5888 }
5889#endif
5890 }
5891
5892 /* deselect device - similar to stop_(in/out)put_stream() */
5893 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07005894 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07005895 /* 2. Disable the rx device */
5896 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07005897 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07005898 list_remove(&uc_info.list);
5899 }
5900 }
Andy Hung31aca912014-03-20 17:14:59 -07005901 return 0;
5902}
5903
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005904static int adev_close(hw_device_t *device)
5905{
Andy Hung31aca912014-03-20 17:14:59 -07005906 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005907 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005908
5909 if (!adev)
5910 return 0;
5911
5912 pthread_mutex_lock(&adev_init_lock);
5913
5914 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005915 audio_extn_snd_mon_unregister_listener(adev);
5916 audio_extn_tfa_98xx_deinit();
jasmine cha270b7762018-03-30 15:41:33 +08005917 audio_extn_ma_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005918 audio_route_free(adev->audio_route);
5919 free(adev->snd_dev_ref_cnt);
5920 platform_deinit(adev->platform);
5921 audio_extn_extspk_deinit(adev->extspk);
5922 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005923 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005924 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
5925 pcm_params_free(adev->use_case_table[i]);
5926 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005927 if (adev->adm_deinit)
5928 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005929 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005930 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07005931 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07005932
5933 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005934
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005935 return 0;
5936}
5937
Glenn Kasten4f993392014-05-14 07:30:48 -07005938/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5939 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5940 * just that it _might_ work.
5941 */
5942static int period_size_is_plausible_for_low_latency(int period_size)
5943{
5944 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005945 case 48:
5946 case 96:
5947 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07005948 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005949 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07005950 case 240:
5951 case 320:
5952 case 480:
5953 return 1;
5954 default:
5955 return 0;
5956 }
5957}
5958
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005959static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
5960{
5961 int card;
5962 card_status_t status;
5963
5964 if (!parms)
5965 return;
5966
5967 if (parse_snd_card_status(parms, &card, &status) < 0)
5968 return;
5969
5970 pthread_mutex_lock(&adev->lock);
5971 bool valid_cb = (card == adev->snd_card);
5972 if (valid_cb) {
5973 if (adev->card_status != status) {
5974 adev->card_status = status;
5975 platform_snd_card_update(adev->platform, status);
5976 }
5977 }
5978 pthread_mutex_unlock(&adev->lock);
5979 return;
5980}
5981
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005982/* out and adev lock held */
5983static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
5984{
5985 struct audio_usecase *uc_info;
5986 float left_p;
5987 float right_p;
5988 audio_devices_t devices;
5989
5990 uc_info = get_usecase_from_list(adev, out->usecase);
5991 if (uc_info == NULL) {
5992 ALOGE("%s: Could not find the usecase (%d) in the list",
5993 __func__, out->usecase);
5994 return -EINVAL;
5995 }
5996
5997 ALOGD("%s: enter: usecase(%d: %s)", __func__,
5998 out->usecase, use_case_table[out->usecase]);
5999
6000 if (restore) {
6001 // restore A2DP device for active usecases and unmute if required
6002 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
6003 !is_a2dp_device(uc_info->out_snd_device)) {
6004 ALOGD("%s: restoring A2DP and unmuting stream", __func__);
6005 select_devices(adev, uc_info->id);
6006 pthread_mutex_lock(&out->compr_mute_lock);
6007 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6008 (out->a2dp_compress_mute)) {
6009 out->a2dp_compress_mute = false;
6010 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
6011 }
6012 pthread_mutex_unlock(&out->compr_mute_lock);
6013 }
6014 } else {
6015 // mute compress stream if suspended
6016 pthread_mutex_lock(&out->compr_mute_lock);
6017 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6018 (!out->a2dp_compress_mute)) {
6019 if (!out->standby) {
6020 ALOGD("%s: selecting speaker and muting stream", __func__);
6021 devices = out->devices;
6022 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
6023 left_p = out->volume_l;
6024 right_p = out->volume_r;
6025 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6026 compress_pause(out->compr);
6027 set_compr_volume(&out->stream, 0.0f, 0.0f);
6028 out->a2dp_compress_mute = true;
6029 select_devices(adev, out->usecase);
6030 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6031 compress_resume(out->compr);
6032 out->devices = devices;
6033 out->volume_l = left_p;
6034 out->volume_r = right_p;
6035 }
6036 }
6037 pthread_mutex_unlock(&out->compr_mute_lock);
6038 }
6039 ALOGV("%s: exit", __func__);
6040 return 0;
6041}
6042
6043int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
6044{
6045 int ret = 0;
6046
6047 lock_output_stream(out);
6048 pthread_mutex_lock(&adev->lock);
6049
6050 ret = check_a2dp_restore_l(adev, out, restore);
6051
6052 pthread_mutex_unlock(&adev->lock);
6053 pthread_mutex_unlock(&out->lock);
6054 return ret;
6055}
6056
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006057static int adev_open(const hw_module_t *module, const char *name,
6058 hw_device_t **device)
6059{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07006060 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006061
Eric Laurent2bafff12016-03-17 12:17:23 -07006062 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006063 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006064 pthread_mutex_lock(&adev_init_lock);
6065 if (audio_device_ref_count != 0) {
6066 *device = &adev->device.common;
6067 audio_device_ref_count++;
6068 ALOGV("%s: returning existing instance of adev", __func__);
6069 ALOGV("%s: exit", __func__);
6070 pthread_mutex_unlock(&adev_init_lock);
6071 return 0;
6072 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006073 adev = calloc(1, sizeof(struct audio_device));
6074
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07006075 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
6076
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006077 adev->device.common.tag = HARDWARE_DEVICE_TAG;
6078 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
6079 adev->device.common.module = (struct hw_module_t *)module;
6080 adev->device.common.close = adev_close;
6081
6082 adev->device.init_check = adev_init_check;
6083 adev->device.set_voice_volume = adev_set_voice_volume;
6084 adev->device.set_master_volume = adev_set_master_volume;
6085 adev->device.get_master_volume = adev_get_master_volume;
6086 adev->device.set_master_mute = adev_set_master_mute;
6087 adev->device.get_master_mute = adev_get_master_mute;
6088 adev->device.set_mode = adev_set_mode;
6089 adev->device.set_mic_mute = adev_set_mic_mute;
6090 adev->device.get_mic_mute = adev_get_mic_mute;
6091 adev->device.set_parameters = adev_set_parameters;
6092 adev->device.get_parameters = adev_get_parameters;
6093 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
6094 adev->device.open_output_stream = adev_open_output_stream;
6095 adev->device.close_output_stream = adev_close_output_stream;
6096 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08006097
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006098 adev->device.close_input_stream = adev_close_input_stream;
6099 adev->device.dump = adev_dump;
jiabin8962a4d2018-03-19 18:21:24 -07006100 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006101
6102 /* Set the default route before the PCM stream is opened */
6103 pthread_mutex_lock(&adev->lock);
6104 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006105 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006106 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08006107 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07006108 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07006109 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07006110 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08006111 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006112 pthread_mutex_unlock(&adev->lock);
6113
6114 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07006115 adev->platform = platform_init(adev);
6116 if (!adev->platform) {
6117 free(adev->snd_dev_ref_cnt);
6118 free(adev);
6119 ALOGE("%s: Failed to init platform data, aborting.", __func__);
6120 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006121 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07006122 return -EINVAL;
6123 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05006124 adev->extspk = audio_extn_extspk_init(adev);
6125
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006126 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
6127 if (adev->visualizer_lib == NULL) {
6128 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
6129 } else {
6130 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
6131 adev->visualizer_start_output =
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07006132 (int (*)(audio_io_handle_t, int, int, int))dlsym(adev->visualizer_lib,
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006133 "visualizer_hal_start_output");
6134 adev->visualizer_stop_output =
6135 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
6136 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07006137 }
6138
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006139 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
6140 if (adev->offload_effects_lib == NULL) {
6141 ALOGW("%s: DLOPEN failed for %s", __func__,
6142 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6143 } else {
6144 ALOGV("%s: DLOPEN successful for %s", __func__,
6145 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6146 adev->offload_effects_start_output =
6147 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
6148 "offload_effects_bundle_hal_start_output");
6149 adev->offload_effects_stop_output =
6150 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
6151 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07006152 }
6153
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006154 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
6155 if (adev->adm_lib == NULL) {
6156 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
6157 } else {
6158 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
6159 adev->adm_init = (adm_init_t)
6160 dlsym(adev->adm_lib, "adm_init");
6161 adev->adm_deinit = (adm_deinit_t)
6162 dlsym(adev->adm_lib, "adm_deinit");
6163 adev->adm_register_input_stream = (adm_register_input_stream_t)
6164 dlsym(adev->adm_lib, "adm_register_input_stream");
6165 adev->adm_register_output_stream = (adm_register_output_stream_t)
6166 dlsym(adev->adm_lib, "adm_register_output_stream");
6167 adev->adm_deregister_stream = (adm_deregister_stream_t)
6168 dlsym(adev->adm_lib, "adm_deregister_stream");
6169 adev->adm_request_focus = (adm_request_focus_t)
6170 dlsym(adev->adm_lib, "adm_request_focus");
6171 adev->adm_abandon_focus = (adm_abandon_focus_t)
6172 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08006173 adev->adm_set_config = (adm_set_config_t)
6174 dlsym(adev->adm_lib, "adm_set_config");
6175 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
6176 dlsym(adev->adm_lib, "adm_request_focus_v2");
6177 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
6178 dlsym(adev->adm_lib, "adm_is_noirq_avail");
6179 adev->adm_on_routing_change = (adm_on_routing_change_t)
6180 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006181 }
6182
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07006183 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05006184 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07006185
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006186 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006187
Andy Hung31aca912014-03-20 17:14:59 -07006188 if (k_enable_extended_precision)
6189 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006190
Glenn Kasten4f993392014-05-14 07:30:48 -07006191 char value[PROPERTY_VALUE_MAX];
6192 int trial;
6193 if (property_get("audio_hal.period_size", value, NULL) > 0) {
6194 trial = atoi(value);
6195 if (period_size_is_plausible_for_low_latency(trial)) {
6196 pcm_config_low_latency.period_size = trial;
6197 pcm_config_low_latency.start_threshold = trial / 4;
6198 pcm_config_low_latency.avail_min = trial / 4;
6199 configured_low_latency_capture_period_size = trial;
6200 }
6201 }
6202 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
6203 trial = atoi(value);
6204 if (period_size_is_plausible_for_low_latency(trial)) {
6205 configured_low_latency_capture_period_size = trial;
6206 }
6207 }
6208
Vignesh Kulothunganb6f0a9c2018-03-22 13:50:22 -07006209 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
6210
Eric Laurent5f4ca952018-10-19 17:33:43 -07006211 adev->camera_orientation = CAMERA_DEFAULT;
6212
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08006213 // commented as full set of app type cfg is sent from platform
6214 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07006215 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08006216
6217 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
6218 af_period_multiplier = atoi(value);
6219 if (af_period_multiplier < 0) {
6220 af_period_multiplier = 2;
6221 } else if (af_period_multiplier > 4) {
6222 af_period_multiplier = 4;
6223 }
6224 ALOGV("new period_multiplier = %d", af_period_multiplier);
6225 }
6226
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08006227 audio_extn_tfa_98xx_init(adev);
jasmine cha270b7762018-03-30 15:41:33 +08006228 audio_extn_ma_init(adev->platform);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08006229
vivek mehta1a9b7c02015-06-25 11:49:38 -07006230 pthread_mutex_unlock(&adev_init_lock);
6231
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006232 if (adev->adm_init)
6233 adev->adm_data = adev->adm_init();
6234
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07006235 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07006236 audio_extn_snd_mon_init();
6237 pthread_mutex_lock(&adev->lock);
6238 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
6239 adev->card_status = CARD_STATUS_ONLINE;
6240 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07006241 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07006242
Eric Laurent2bafff12016-03-17 12:17:23 -07006243 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006244 return 0;
6245}
6246
6247static struct hw_module_methods_t hal_module_methods = {
6248 .open = adev_open,
6249};
6250
6251struct audio_module HAL_MODULE_INFO_SYM = {
6252 .common = {
6253 .tag = HARDWARE_MODULE_TAG,
6254 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
6255 .hal_api_version = HARDWARE_HAL_API_VERSION,
6256 .id = AUDIO_HARDWARE_MODULE_ID,
6257 .name = "QCOM Audio HAL",
6258 .author = "Code Aurora Forum",
6259 .methods = &hal_module_methods,
6260 },
6261};