blob: ccf922eeaafd015eb7a650cb8a96bce0105bb016 [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) ||
1534 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001535 in_snd_device = vc_usecase->in_snd_device;
1536 out_snd_device = vc_usecase->out_snd_device;
1537 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001538 } else if (audio_extn_hfp_is_active(adev)) {
1539 hfp_ucid = audio_extn_hfp_get_usecase();
1540 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1541 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1542 in_snd_device = hfp_usecase->in_snd_device;
1543 out_snd_device = hfp_usecase->out_snd_device;
1544 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001545 }
1546 if (usecase->type == PCM_PLAYBACK) {
1547 usecase->devices = usecase->stream.out->devices;
1548 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001549 if (out_snd_device == SND_DEVICE_NONE) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001550 struct stream_out *voip_out = adev->primary_output;
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001551 struct stream_in *voip_in = get_voice_communication_input(adev);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001552
Eric Laurentb23d5282013-05-14 15:27:20 -07001553 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001554 usecase->stream.out->devices);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001555
1556 if (voip_usecase)
1557 voip_out = voip_usecase->stream.out;
1558
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001559 if (usecase->stream.out == voip_out && voip_in != NULL) {
1560 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001561 }
1562 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001563 } else if (usecase->type == PCM_CAPTURE) {
1564 usecase->devices = usecase->stream.in->device;
1565 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001566 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001567 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001568 struct stream_in *voip_in = get_voice_communication_input(adev);
1569
1570 if (voip_in != NULL) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001571
1572 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1573 USECASE_AUDIO_PLAYBACK_VOIP);
1574
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001575 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001576 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1577 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001578 } else if (voip_usecase) {
1579 out_device = voip_usecase->stream.out->devices;
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001580 } else if (adev->primary_output) {
1581 out_device = adev->primary_output->devices;
1582 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001583 }
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001584 in_snd_device = platform_get_input_snd_device(adev->platform,
1585 usecase->stream.in,
1586 out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001587 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001588 }
1589 }
1590
1591 if (out_snd_device == usecase->out_snd_device &&
1592 in_snd_device == usecase->in_snd_device) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001593 if (!force_device_switch(usecase))
1594 return 0;
1595 }
1596
1597 if (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready()) {
1598 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1599 return 0;
1600 }
1601
Aniket Kumar Lata9723a962018-05-16 17:41:55 -07001602 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
1603 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001604 (!audio_extn_a2dp_is_ready())) {
1605 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
juyuchen9baad392018-06-05 19:02:10 +08001606 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
1607 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
1608 else
1609 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001610 }
1611
juyuchen66c4ecf2018-08-06 15:39:34 +08001612 if (usecase->id == USECASE_INCALL_MUSIC_UPLINK) {
1613 out_snd_device = SND_DEVICE_OUT_VOICE_MUSIC_TX;
1614 }
1615
Eric Laurent2bafff12016-03-17 12:17:23 -07001616 if (out_snd_device != SND_DEVICE_NONE &&
1617 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1618 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1619 __func__,
1620 use_case_table[uc_id],
1621 adev->last_logged_snd_device[uc_id][0],
1622 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1623 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1624 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1625 -1,
1626 out_snd_device,
1627 platform_get_snd_device_name(out_snd_device),
1628 platform_get_snd_device_acdb_id(out_snd_device));
1629 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1630 }
1631 if (in_snd_device != SND_DEVICE_NONE &&
1632 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1633 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1634 __func__,
1635 use_case_table[uc_id],
1636 adev->last_logged_snd_device[uc_id][1],
1637 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1638 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1639 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1640 -1,
1641 in_snd_device,
1642 platform_get_snd_device_name(in_snd_device),
1643 platform_get_snd_device_acdb_id(in_snd_device));
1644 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1645 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001646
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001647 /*
1648 * Limitation: While in call, to do a device switch we need to disable
1649 * and enable both RX and TX devices though one of them is same as current
1650 * device.
1651 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001652 if ((usecase->type == VOICE_CALL) &&
1653 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1654 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001655 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001656 /* Disable sidetone only if voice call already exists */
1657 if (voice_is_call_state_active(adev))
1658 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001659 }
1660
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001661 /* Disable current sound devices */
1662 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001663 disable_audio_route(adev, usecase);
1664 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001665 }
1666
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001667 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001668 disable_audio_route(adev, usecase);
1669 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001670 }
1671
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001672 /* Applicable only on the targets that has external modem.
1673 * New device information should be sent to modem before enabling
1674 * the devices to reduce in-call device switch time.
1675 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001676 if ((usecase->type == VOICE_CALL) &&
1677 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1678 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001679 status = platform_switch_voice_call_enable_device_config(adev->platform,
1680 out_snd_device,
1681 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001682 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001683
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001684 /* Enable new sound devices */
1685 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001686 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001687 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) ||
1688 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001689 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001690 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001691 }
1692
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001693 if (in_snd_device != SND_DEVICE_NONE) {
1694 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001695 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001696 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001697
Eric Laurentb23d5282013-05-14 15:27:20 -07001698 if (usecase->type == VOICE_CALL)
1699 status = platform_switch_voice_call_device_post(adev->platform,
1700 out_snd_device,
1701 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001702
sangwoo170731f2013-06-08 15:36:36 +09001703 usecase->in_snd_device = in_snd_device;
1704 usecase->out_snd_device = out_snd_device;
1705
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001706 audio_extn_tfa_98xx_set_mode();
1707
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001708 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001709
Jasmine Cha70771b62018-05-15 15:02:43 +08001710 audio_extn_ma_set_device(usecase);
jasmine cha270b7762018-03-30 15:41:33 +08001711
Vignesh Kulothungan64698822018-01-23 11:25:18 -08001712 /* If input stream is already running the effect needs to be
1713 applied on the new input device that's being enabled here. */
1714 if (in_snd_device != SND_DEVICE_NONE)
1715 check_and_enable_effect(adev);
1716
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001717 /* Applicable only on the targets that has external modem.
1718 * Enable device command should be sent to modem only after
1719 * enabling voice call mixer controls
1720 */
vivek mehta765eb642015-08-07 19:46:06 -07001721 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001722 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1723 out_snd_device,
1724 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001725 /* Enable sidetone only if voice call already exists */
1726 if (voice_is_call_state_active(adev))
1727 voice_set_sidetone(adev, out_snd_device, true);
1728 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001729
Yung Ti Sue9d64f92018-06-22 17:38:47 +08001730 if (usecase->type != PCM_CAPTURE && voip_usecase) {
Eric Laurentf4520b02017-09-20 18:31:58 -07001731 struct stream_out *voip_out = voip_usecase->stream.out;
1732 audio_extn_utils_send_app_type_gain(adev,
1733 voip_out->app_type_cfg.app_type,
1734 &voip_out->app_type_cfg.gain[0]);
1735 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001736 return status;
1737}
1738
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001739static int stop_input_stream(struct stream_in *in)
1740{
1741 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001742 struct audio_usecase *uc_info;
1743 struct audio_device *adev = in->dev;
1744
Eric Laurent994a6932013-07-17 11:51:42 -07001745 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001746 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001747
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001748 uc_info = get_usecase_from_list(adev, in->usecase);
1749 if (uc_info == NULL) {
1750 ALOGE("%s: Could not find the usecase (%d) in the list",
1751 __func__, in->usecase);
1752 return -EINVAL;
1753 }
1754
vivek mehta781065c2017-04-04 12:55:01 -07001755 /* Close in-call recording streams */
1756 voice_check_and_stop_incall_rec_usecase(adev, in);
1757
Eric Laurent150dbfe2013-02-27 14:31:02 -08001758 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001759 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001760
1761 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001762 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001763
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001764 list_remove(&uc_info->list);
1765 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001766
Eric Laurent994a6932013-07-17 11:51:42 -07001767 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001768 return ret;
1769}
1770
1771int start_input_stream(struct stream_in *in)
1772{
1773 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001774 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001775 struct audio_usecase *uc_info;
1776 struct audio_device *adev = in->dev;
1777
Eric Laurent994a6932013-07-17 11:51:42 -07001778 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001779
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001780 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1781 return -EIO;
1782
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001783 if (in->card_status == CARD_STATUS_OFFLINE ||
1784 adev->card_status == CARD_STATUS_OFFLINE) {
1785 ALOGW("in->card_status or adev->card_status offline, try again");
1786 ret = -EAGAIN;
1787 goto error_config;
1788 }
1789
vivek mehta781065c2017-04-04 12:55:01 -07001790 /* Check if source matches incall recording usecase criteria */
1791 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1792 if (ret)
1793 goto error_config;
1794 else
1795 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1796
Eric Laurentb23d5282013-05-14 15:27:20 -07001797 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001798 if (in->pcm_device_id < 0) {
1799 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1800 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001801 ret = -EINVAL;
1802 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001803 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001804
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001805 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1806 uc_info->id = in->usecase;
1807 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001808 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001809 uc_info->devices = in->device;
1810 uc_info->in_snd_device = SND_DEVICE_NONE;
1811 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001812
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001813 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001814
Wei Wangf4837d52017-11-21 14:51:20 -08001815 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001816 audio_extn_perf_lock_acquire();
1817
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001818 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001819
Eric Laurent0e46adf2016-12-16 12:49:24 -08001820 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001821 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001822 ALOGE("%s: pcm stream not ready", __func__);
1823 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001824 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001825 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001826 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001827 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1828 goto error_open;
1829 }
1830 } else {
1831 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1832 unsigned int pcm_open_retry_count = 0;
1833
1834 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1835 flags |= PCM_MMAP | PCM_NOIRQ;
1836 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1837 } else if (in->realtime) {
1838 flags |= PCM_MMAP | PCM_NOIRQ;
1839 }
1840
1841 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1842 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1843
1844 while (1) {
1845 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1846 flags, &in->config);
1847 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1848 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1849 if (in->pcm != NULL) {
1850 pcm_close(in->pcm);
1851 in->pcm = NULL;
1852 }
1853 if (pcm_open_retry_count-- == 0) {
1854 ret = -EIO;
1855 goto error_open;
1856 }
1857 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1858 continue;
1859 }
1860 break;
1861 }
1862
1863 ALOGV("%s: pcm_prepare", __func__);
1864 ret = pcm_prepare(in->pcm);
1865 if (ret < 0) {
1866 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001867 pcm_close(in->pcm);
1868 in->pcm = NULL;
1869 goto error_open;
1870 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001871 if (in->realtime) {
1872 ret = pcm_start(in->pcm);
1873 if (ret < 0) {
1874 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1875 pcm_close(in->pcm);
1876 in->pcm = NULL;
1877 goto error_open;
1878 }
1879 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001880 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001881 register_in_stream(in);
Vignesh Kulothungan64698822018-01-23 11:25:18 -08001882 check_and_enable_effect(adev);
Wei Wangf4837d52017-11-21 14:51:20 -08001883 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001884 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001885 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001886
Eric Laurent0e46adf2016-12-16 12:49:24 -08001887 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001888
1889error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001890 stop_input_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001891 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001892 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001893
1894error_config:
Eric Laurent2bafff12016-03-17 12:17:23 -07001895 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001896 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001897}
1898
Eric Laurenta1478072015-09-21 17:21:52 -07001899void lock_input_stream(struct stream_in *in)
1900{
1901 pthread_mutex_lock(&in->pre_lock);
1902 pthread_mutex_lock(&in->lock);
1903 pthread_mutex_unlock(&in->pre_lock);
1904}
1905
1906void lock_output_stream(struct stream_out *out)
1907{
1908 pthread_mutex_lock(&out->pre_lock);
1909 pthread_mutex_lock(&out->lock);
1910 pthread_mutex_unlock(&out->pre_lock);
1911}
1912
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001913/* must be called with out->lock locked */
1914static int send_offload_cmd_l(struct stream_out* out, int command)
1915{
1916 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1917
1918 ALOGVV("%s %d", __func__, command);
1919
1920 cmd->cmd = command;
1921 list_add_tail(&out->offload_cmd_list, &cmd->node);
1922 pthread_cond_signal(&out->offload_cond);
1923 return 0;
1924}
1925
1926/* must be called iwth out->lock locked */
1927static void stop_compressed_output_l(struct stream_out *out)
1928{
1929 out->offload_state = OFFLOAD_STATE_IDLE;
1930 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001931 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001932 if (out->compr != NULL) {
1933 compress_stop(out->compr);
1934 while (out->offload_thread_blocked) {
1935 pthread_cond_wait(&out->cond, &out->lock);
1936 }
1937 }
1938}
1939
1940static void *offload_thread_loop(void *context)
1941{
1942 struct stream_out *out = (struct stream_out *) context;
1943 struct listnode *item;
1944
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001945 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1946 set_sched_policy(0, SP_FOREGROUND);
1947 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1948
1949 ALOGV("%s", __func__);
juyuchenb0f5bfd2018-12-12 17:58:09 +08001950
Eric Laurenta1478072015-09-21 17:21:52 -07001951 lock_output_stream(out);
juyuchenb0f5bfd2018-12-12 17:58:09 +08001952 out->offload_state = OFFLOAD_STATE_IDLE;
1953 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001954 for (;;) {
1955 struct offload_cmd *cmd = NULL;
1956 stream_callback_event_t event;
1957 bool send_callback = false;
1958
1959 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1960 __func__, list_empty(&out->offload_cmd_list),
1961 out->offload_state);
1962 if (list_empty(&out->offload_cmd_list)) {
1963 ALOGV("%s SLEEPING", __func__);
1964 pthread_cond_wait(&out->offload_cond, &out->lock);
1965 ALOGV("%s RUNNING", __func__);
1966 continue;
1967 }
1968
1969 item = list_head(&out->offload_cmd_list);
1970 cmd = node_to_item(item, struct offload_cmd, node);
1971 list_remove(item);
1972
1973 ALOGVV("%s STATE %d CMD %d out->compr %p",
1974 __func__, out->offload_state, cmd->cmd, out->compr);
1975
1976 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1977 free(cmd);
1978 break;
1979 }
1980
1981 if (out->compr == NULL) {
1982 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001983 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001984 pthread_cond_signal(&out->cond);
1985 continue;
1986 }
1987 out->offload_thread_blocked = true;
1988 pthread_mutex_unlock(&out->lock);
1989 send_callback = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001990 switch (cmd->cmd) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001991 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1992 compress_wait(out->compr, -1);
1993 send_callback = true;
1994 event = STREAM_CBK_EVENT_WRITE_READY;
1995 break;
1996 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001997 compress_next_track(out->compr);
1998 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001999 send_callback = true;
2000 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08002001 /* Resend the metadata for next iteration */
2002 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002003 break;
2004 case OFFLOAD_CMD_DRAIN:
2005 compress_drain(out->compr);
2006 send_callback = true;
2007 event = STREAM_CBK_EVENT_DRAIN_READY;
2008 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002009 case OFFLOAD_CMD_ERROR:
2010 send_callback = true;
2011 event = STREAM_CBK_EVENT_ERROR;
2012 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002013 default:
2014 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2015 break;
2016 }
Eric Laurenta1478072015-09-21 17:21:52 -07002017 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002018 out->offload_thread_blocked = false;
2019 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07002020 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08002021 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002022 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002023 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002024 free(cmd);
2025 }
2026
2027 pthread_cond_signal(&out->cond);
2028 while (!list_empty(&out->offload_cmd_list)) {
2029 item = list_head(&out->offload_cmd_list);
2030 list_remove(item);
2031 free(node_to_item(item, struct offload_cmd, node));
2032 }
2033 pthread_mutex_unlock(&out->lock);
2034
2035 return NULL;
2036}
2037
2038static int create_offload_callback_thread(struct stream_out *out)
2039{
2040 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2041 list_init(&out->offload_cmd_list);
2042 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2043 offload_thread_loop, out);
2044 return 0;
2045}
2046
2047static int destroy_offload_callback_thread(struct stream_out *out)
2048{
Eric Laurenta1478072015-09-21 17:21:52 -07002049 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002050 stop_compressed_output_l(out);
2051 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2052
2053 pthread_mutex_unlock(&out->lock);
2054 pthread_join(out->offload_thread, (void **) NULL);
2055 pthread_cond_destroy(&out->offload_cond);
2056
2057 return 0;
2058}
2059
Eric Laurent07eeafd2013-10-06 12:52:49 -07002060static bool allow_hdmi_channel_config(struct audio_device *adev)
2061{
2062 struct listnode *node;
2063 struct audio_usecase *usecase;
2064 bool ret = true;
2065
2066 list_for_each(node, &adev->usecase_list) {
2067 usecase = node_to_item(node, struct audio_usecase, list);
2068 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2069 /*
2070 * If voice call is already existing, do not proceed further to avoid
2071 * disabling/enabling both RX and TX devices, CSD calls, etc.
2072 * Once the voice call done, the HDMI channels can be configured to
2073 * max channels of remaining use cases.
2074 */
2075 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08002076 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07002077 __func__);
2078 ret = false;
2079 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002080 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
2081 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07002082 "no change in HDMI channels", __func__);
2083 ret = false;
2084 break;
2085 }
2086 }
2087 }
2088 return ret;
2089}
2090
2091static int check_and_set_hdmi_channels(struct audio_device *adev,
2092 unsigned int channels)
2093{
2094 struct listnode *node;
2095 struct audio_usecase *usecase;
2096
2097 /* Check if change in HDMI channel config is allowed */
2098 if (!allow_hdmi_channel_config(adev))
2099 return 0;
2100
2101 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08002102 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002103 return 0;
2104 }
2105
2106 platform_set_hdmi_channels(adev->platform, channels);
2107 adev->cur_hdmi_channels = channels;
2108
2109 /*
2110 * Deroute all the playback streams routed to HDMI so that
2111 * the back end is deactivated. Note that backend will not
2112 * be deactivated if any one stream is connected to it.
2113 */
2114 list_for_each(node, &adev->usecase_list) {
2115 usecase = node_to_item(node, struct audio_usecase, list);
2116 if (usecase->type == PCM_PLAYBACK &&
2117 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002118 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002119 }
2120 }
2121
2122 /*
2123 * Enable all the streams disabled above. Now the HDMI backend
2124 * will be activated with new channel configuration
2125 */
2126 list_for_each(node, &adev->usecase_list) {
2127 usecase = node_to_item(node, struct audio_usecase, list);
2128 if (usecase->type == PCM_PLAYBACK &&
2129 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002130 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002131 }
2132 }
2133
2134 return 0;
2135}
2136
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002137static int check_and_set_usb_service_interval(struct audio_device *adev,
2138 struct audio_usecase *uc_info,
2139 bool min)
2140{
2141 struct listnode *node;
2142 struct audio_usecase *usecase;
2143 bool switch_usecases = false;
2144 bool reconfig = false;
2145
2146 if ((uc_info->id != USECASE_AUDIO_PLAYBACK_MMAP) &&
2147 (uc_info->id != USECASE_AUDIO_PLAYBACK_ULL))
2148 return -1;
2149
2150 /* set if the valid usecase do not already exist */
2151 list_for_each(node, &adev->usecase_list) {
2152 usecase = node_to_item(node, struct audio_usecase, list);
2153 if (usecase->type == PCM_PLAYBACK &&
2154 (audio_is_usb_out_device(usecase->devices & AUDIO_DEVICE_OUT_ALL_USB))) {
2155 switch (usecase->id) {
2156 case USECASE_AUDIO_PLAYBACK_MMAP:
2157 case USECASE_AUDIO_PLAYBACK_ULL:
2158 // cannot reconfig while mmap/ull is present.
2159 return -1;
2160 default:
2161 switch_usecases = true;
2162 break;
2163 }
2164 }
2165 if (switch_usecases)
2166 break;
2167 }
2168 /*
2169 * client can try to set service interval in start_output_stream
2170 * to min or to 0 (i.e reset) in stop_output_stream .
2171 */
2172 unsigned long service_interval =
2173 audio_extn_usb_find_service_interval(min, true /*playback*/);
2174 int ret = platform_set_usb_service_interval(adev->platform,
2175 true /*playback*/,
2176 service_interval,
2177 &reconfig);
2178 /* no change or not supported or no active usecases */
2179 if (ret || !reconfig || !switch_usecases)
2180 return -1;
2181 return 0;
2182#undef VALID_USECASE
2183}
2184
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002185static int stop_output_stream(struct stream_out *out)
2186{
2187 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002188 struct audio_usecase *uc_info;
2189 struct audio_device *adev = out->dev;
HW Lee88512e92018-06-12 15:26:09 +08002190 bool has_voip_usecase =
2191 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002192
Eric Laurent994a6932013-07-17 11:51:42 -07002193 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002194 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002195 uc_info = get_usecase_from_list(adev, out->usecase);
2196 if (uc_info == NULL) {
2197 ALOGE("%s: Could not find the usecase (%d) in the list",
2198 __func__, out->usecase);
2199 return -EINVAL;
2200 }
2201
Haynes Mathew George41f86652014-06-17 14:22:15 -07002202 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2203 if (adev->visualizer_stop_output != NULL)
2204 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
2205 if (adev->offload_effects_stop_output != NULL)
2206 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002207 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2208 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2209 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07002210 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002211
Arun Mirpuri0cc2f312018-05-29 17:26:07 -07002212 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
2213 voice_set_device_mute_flag(adev, false);
2214
Eric Laurent150dbfe2013-02-27 14:31:02 -08002215 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002216 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002217
2218 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002219 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002220
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002221 list_remove(&uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002222
Eric Laurent0499d4f2014-08-25 22:39:29 -05002223 audio_extn_extspk_update(adev->extspk);
2224
Eric Laurent07eeafd2013-10-06 12:52:49 -07002225 /* Must be called after removing the usecase from list */
2226 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2227 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
HW Lee88512e92018-06-12 15:26:09 +08002228 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002229 ret = check_and_set_usb_service_interval(adev, uc_info, false /*min*/);
2230 if (ret == 0) {
2231 /* default service interval was successfully updated,
2232 reopen USB backend with new service interval */
2233 check_and_route_playback_usecases(adev, uc_info, uc_info->out_snd_device);
2234 }
2235 ret = 0;
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07002236 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002237
HW Lee88512e92018-06-12 15:26:09 +08002238 if (has_voip_usecase ||
2239 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
2240 struct listnode *node;
2241 struct audio_usecase *usecase;
2242 list_for_each(node, &adev->usecase_list) {
2243 usecase = node_to_item(node, struct audio_usecase, list);
2244 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
2245 continue;
2246
2247 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
2248 __func__, usecase->id, use_case_table[usecase->id],
2249 out->usecase, use_case_table[out->usecase]);
2250 select_devices(adev, usecase->id);
2251 }
2252 }
2253
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002254 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07002255 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002256 return ret;
2257}
2258
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002259struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
2260 unsigned int flags, unsigned int pcm_open_retry_count,
2261 struct pcm_config *config)
2262{
2263 struct pcm* pcm = NULL;
2264
2265 while (1) {
2266 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
2267 if (pcm == NULL || !pcm_is_ready(pcm)) {
2268 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
2269 if (pcm != NULL) {
2270 pcm_close(pcm);
2271 pcm = NULL;
2272 }
2273 if (pcm_open_retry_count-- == 0)
2274 return NULL;
2275
2276 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2277 continue;
2278 }
2279 break;
2280 }
2281
2282 if (pcm_is_ready(pcm)) {
2283 int ret = pcm_prepare(pcm);
2284 if (ret < 0) {
2285 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2286 pcm_close(pcm);
2287 pcm = NULL;
2288 }
2289 }
2290
2291 return pcm;
2292}
2293
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002294int start_output_stream(struct stream_out *out)
2295{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002296 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002297 struct audio_usecase *uc_info;
2298 struct audio_device *adev = out->dev;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002299 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002300
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002301 ALOGV("%s: enter: usecase(%d: %s) %s devices(%#x)",
2302 __func__, out->usecase, use_case_table[out->usecase],
2303 out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS ? "(with haptics)" : "",
2304 out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002305
2306 if (out->card_status == CARD_STATUS_OFFLINE ||
2307 adev->card_status == CARD_STATUS_OFFLINE) {
2308 ALOGW("out->card_status or adev->card_status offline, try again");
2309 ret = -EAGAIN;
2310 goto error_config;
2311 }
2312
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002313 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2314 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002315 if (out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002316 a2dp_combo = true;
2317 } else {
2318 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2319 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2320 ret = -EAGAIN;
2321 goto error_config;
2322 }
2323 }
2324 }
2325 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002326 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002327 if (out->pcm_device_id < 0) {
2328 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2329 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002330 ret = -EINVAL;
2331 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002332 }
2333
2334 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
2335 uc_info->id = out->usecase;
2336 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002337 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002338 uc_info->devices = out->devices;
2339 uc_info->in_snd_device = SND_DEVICE_NONE;
2340 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002341
Eric Laurent07eeafd2013-10-06 12:52:49 -07002342 /* This must be called before adding this usecase to the list */
2343 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2344 check_and_set_hdmi_channels(adev, out->config.channels);
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002345 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
2346 check_and_set_usb_service_interval(adev, uc_info, true /*min*/);
2347 /* USB backend is not reopened immediately.
2348 This is eventually done as part of select_devices */
2349 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002350
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002351 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002352
Wei Wangf4837d52017-11-21 14:51:20 -08002353 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002354 audio_extn_perf_lock_acquire();
2355
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002356 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2357 (!audio_extn_a2dp_is_ready())) {
2358 if (!a2dp_combo) {
2359 check_a2dp_restore_l(adev, out, false);
2360 } else {
2361 audio_devices_t dev = out->devices;
juyuchen9baad392018-06-05 19:02:10 +08002362 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2363 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2364 else
2365 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002366 select_devices(adev, out->usecase);
2367 out->devices = dev;
2368 }
2369 } else {
2370 select_devices(adev, out->usecase);
2371 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002372
Eric Laurent0499d4f2014-08-25 22:39:29 -05002373 audio_extn_extspk_update(adev->extspk);
2374
Arun Mirpuri0cc2f312018-05-29 17:26:07 -07002375 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
2376 voice_set_device_mute_flag(adev, true);
2377
Andy Hung31aca912014-03-20 17:14:59 -07002378 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002379 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002380 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2381 out->pcm = NULL;
2382 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
2383 COMPRESS_IN, &out->compr_config);
2384 if (out->compr && !is_compress_ready(out->compr)) {
2385 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2386 compress_close(out->compr);
2387 out->compr = NULL;
2388 ret = -EIO;
2389 goto error_open;
2390 }
2391 if (out->offload_callback)
2392 compress_nonblock(out->compr, out->non_blocking);
2393
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07002394 if (adev->visualizer_start_output != NULL) {
2395 int capture_device_id =
2396 platform_get_pcm_device_id(USECASE_AUDIO_RECORD_AFE_PROXY,
2397 PCM_CAPTURE);
2398 adev->visualizer_start_output(out->handle, out->pcm_device_id,
2399 adev->snd_card, capture_device_id);
2400 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002401 if (adev->offload_effects_start_output != NULL)
2402 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
2403 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002404 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002405 ALOGE("%s: pcm stream not ready", __func__);
2406 goto error_open;
2407 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002408 ret = pcm_start(out->pcm);
2409 if (ret < 0) {
2410 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2411 goto error_open;
2412 }
2413 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07002414 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002415 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002416
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002417 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2418 flags |= PCM_MMAP | PCM_NOIRQ;
2419 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002420 } else if (out->realtime) {
2421 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07002422 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002423
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002424 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
2425 flags, pcm_open_retry_count,
2426 &(out->config));
2427 if (out->pcm == NULL) {
2428 ret = -EIO;
2429 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002430 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002431
2432 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
2433 if (adev->haptic_pcm != NULL) {
2434 pcm_close(adev->haptic_pcm);
2435 adev->haptic_pcm = NULL;
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002436 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002437 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
2438 adev->haptic_pcm_device_id,
2439 flags, pcm_open_retry_count,
2440 &(adev->haptics_config));
2441 // failure to open haptics pcm shouldnt stop audio,
2442 // so do not close audio pcm in case of error
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002443 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002444
Eric Laurent0e46adf2016-12-16 12:49:24 -08002445 if (out->realtime) {
2446 ret = pcm_start(out->pcm);
2447 if (ret < 0) {
2448 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
2449 pcm_close(out->pcm);
2450 out->pcm = NULL;
2451 goto error_open;
2452 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002453 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002454 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002455
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002456 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08002457 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002458 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002459 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07002460
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002461 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2462 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2463 audio_low_latency_hint_start();
2464 }
2465
vivek mehtae59cfb22017-06-16 15:57:11 -07002466 // consider a scenario where on pause lower layers are tear down.
2467 // so on resume, swap mixer control need to be sent only when
2468 // backend is active, hence rather than sending from enable device
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002469 // sending it from start of stream
vivek mehtae59cfb22017-06-16 15:57:11 -07002470
2471 platform_set_swap_channels(adev, true);
2472
Eric Laurent994a6932013-07-17 11:51:42 -07002473 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002474 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002475error_open:
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002476 if (adev->haptic_pcm) {
2477 pcm_close(adev->haptic_pcm);
2478 adev->haptic_pcm = NULL;
2479 }
Wei Wangf4837d52017-11-21 14:51:20 -08002480 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002481 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002482 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002483error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002484 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002485}
2486
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002487static int check_input_parameters(uint32_t sample_rate,
2488 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07002489 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002490{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002491 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2492 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002493 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2494 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002495 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2496 return -EINVAL;
2497 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002498
Eric Laurent74b55762017-07-09 17:04:53 -07002499 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2500 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002501 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002502 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002503 return -EINVAL;
2504 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002505
2506 switch (sample_rate) {
2507 case 8000:
2508 case 11025:
2509 case 12000:
2510 case 16000:
2511 case 22050:
2512 case 24000:
2513 case 32000:
2514 case 44100:
2515 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002516 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002517 break;
2518 default:
vivek mehtadae44712015-07-27 14:13:18 -07002519 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002520 return -EINVAL;
2521 }
2522
2523 return 0;
2524}
2525
Kevin Rocarda325aa22018-04-03 09:15:52 -07002526/** Add a value in a list if not already present.
2527 * @return true if value was successfully inserted or already present,
2528 * false if the list is full and does not contain the value.
2529 */
2530static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
2531 for (size_t i = 0; i < list_length; i++) {
2532 if (list[i] == value) return true; // value is already present
2533 if (list[i] == 0) { // no values in this slot
2534 list[i] = value;
2535 return true; // value inserted
2536 }
2537 }
2538 return false; // could not insert value
2539}
2540
2541/** Add channel_mask in supported_channel_masks if not already present.
2542 * @return true if channel_mask was successfully inserted or already present,
2543 * false if supported_channel_masks is full and does not contain channel_mask.
2544 */
2545static void register_channel_mask(audio_channel_mask_t channel_mask,
2546 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
2547 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
2548 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
2549}
2550
2551/** Add format in supported_formats if not already present.
2552 * @return true if format was successfully inserted or already present,
2553 * false if supported_formats is full and does not contain format.
2554 */
2555static void register_format(audio_format_t format,
2556 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
2557 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
2558 "%s: stream can not declare supporting its format %x", __func__, format);
2559}
2560/** Add sample_rate in supported_sample_rates if not already present.
2561 * @return true if sample_rate was successfully inserted or already present,
2562 * false if supported_sample_rates is full and does not contain sample_rate.
2563 */
2564static void register_sample_rate(uint32_t sample_rate,
2565 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
2566 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
2567 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
2568}
2569
vivek mehtaa68fea62017-06-08 19:04:02 -07002570static size_t get_stream_buffer_size(size_t duration_ms,
2571 uint32_t sample_rate,
2572 audio_format_t format,
2573 int channel_count,
2574 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002575{
2576 size_t size = 0;
2577
vivek mehtaa68fea62017-06-08 19:04:02 -07002578 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002579 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002580 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002581
2582 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002583
Glenn Kasten4f993392014-05-14 07:30:48 -07002584 /* make sure the size is multiple of 32 bytes
2585 * At 48 kHz mono 16-bit PCM:
2586 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2587 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2588 */
2589 size += 0x1f;
2590 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002591
2592 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002593}
2594
2595static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2596{
2597 struct stream_out *out = (struct stream_out *)stream;
2598
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002599 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002600}
2601
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002602static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002603{
2604 return -ENOSYS;
2605}
2606
2607static size_t out_get_buffer_size(const struct audio_stream *stream)
2608{
2609 struct stream_out *out = (struct stream_out *)stream;
2610
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002611 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2612 return out->compr_config.fragment_size;
2613 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002614 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002615 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002616}
2617
2618static uint32_t out_get_channels(const struct audio_stream *stream)
2619{
2620 struct stream_out *out = (struct stream_out *)stream;
2621
2622 return out->channel_mask;
2623}
2624
2625static audio_format_t out_get_format(const struct audio_stream *stream)
2626{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002627 struct stream_out *out = (struct stream_out *)stream;
2628
2629 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002630}
2631
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002632static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002633{
2634 return -ENOSYS;
2635}
2636
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002637/* must be called with out->lock locked */
2638static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002639{
2640 struct stream_out *out = (struct stream_out *)stream;
2641 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002642 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002643
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002644 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002645 if (adev->adm_deregister_stream)
2646 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002647 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002648 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002649 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2650 if (out->pcm) {
2651 pcm_close(out->pcm);
2652 out->pcm = NULL;
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002653
2654 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
2655 if (adev->haptic_pcm) {
2656 pcm_close(adev->haptic_pcm);
2657 adev->haptic_pcm = NULL;
2658 }
2659
2660 if (adev->haptic_buffer != NULL) {
2661 free(adev->haptic_buffer);
2662 adev->haptic_buffer = NULL;
2663 adev->haptic_buffer_size = 0;
2664 }
2665 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002666 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002667 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002668 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002669 out->playback_started = false;
2670 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002671 } else {
2672 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002673 out->gapless_mdata.encoder_delay = 0;
2674 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002675 if (out->compr != NULL) {
2676 compress_close(out->compr);
2677 out->compr = NULL;
2678 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002679 }
Phil Burkbc991042017-02-24 08:06:44 -08002680 if (do_stop) {
2681 stop_output_stream(out);
2682 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002683 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002684 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002685 return 0;
2686}
2687
2688static int out_standby(struct audio_stream *stream)
2689{
2690 struct stream_out *out = (struct stream_out *)stream;
2691
2692 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2693 out->usecase, use_case_table[out->usecase]);
2694
2695 lock_output_stream(out);
2696 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002697 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002698 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002699 return 0;
2700}
2701
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002702static int out_on_error(struct audio_stream *stream)
2703{
2704 struct stream_out *out = (struct stream_out *)stream;
2705 struct audio_device *adev = out->dev;
2706 bool do_standby = false;
2707
2708 lock_output_stream(out);
2709 if (!out->standby) {
2710 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2711 stop_compressed_output_l(out);
2712 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2713 } else
2714 do_standby = true;
2715 }
2716 pthread_mutex_unlock(&out->lock);
2717
2718 if (do_standby)
2719 return out_standby(&out->stream.common);
2720
2721 return 0;
2722}
2723
Andy Hung7401c7c2016-09-21 12:41:21 -07002724static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002725{
Andy Hung7401c7c2016-09-21 12:41:21 -07002726 struct stream_out *out = (struct stream_out *)stream;
2727
2728 // We try to get the lock for consistency,
2729 // but it isn't necessary for these variables.
2730 // If we're not in standby, we may be blocked on a write.
2731 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2732 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2733 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2734
2735 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002736 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002737 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002738
2739 // dump error info
2740 (void)error_log_dump(
2741 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002742
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002743 return 0;
2744}
2745
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002746static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2747{
2748 int ret = 0;
2749 char value[32];
2750 struct compr_gapless_mdata tmp_mdata;
2751
2752 if (!out || !parms) {
2753 return -EINVAL;
2754 }
2755
2756 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2757 if (ret >= 0) {
2758 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2759 } else {
2760 return -EINVAL;
2761 }
2762
2763 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2764 if (ret >= 0) {
2765 tmp_mdata.encoder_padding = atoi(value);
2766 } else {
2767 return -EINVAL;
2768 }
2769
2770 out->gapless_mdata = tmp_mdata;
2771 out->send_new_metadata = 1;
2772 ALOGV("%s new encoder delay %u and padding %u", __func__,
2773 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2774
2775 return 0;
2776}
2777
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002778static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2779{
2780 return out == adev->primary_output || out == adev->voice_tx_output;
2781}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002782
Kevin Rocard1e02c882017-08-09 15:26:07 -07002783static int get_alive_usb_card(struct str_parms* parms) {
2784 int card;
2785 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2786 !audio_extn_usb_alive(card)) {
2787 return card;
2788 }
2789 return -ENODEV;
2790}
2791
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002792static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2793{
2794 struct stream_out *out = (struct stream_out *)stream;
2795 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002796 struct audio_usecase *usecase;
2797 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002798 struct str_parms *parms;
2799 char value[32];
2800 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002801 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002802 int status = 0;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002803 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002804
Eric Laurent2e140aa2016-06-30 17:14:46 -07002805 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002806 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002807 parms = str_parms_create_str(kvpairs);
2808 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2809 if (ret >= 0) {
2810 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002811
Eric Laurenta1478072015-09-21 17:21:52 -07002812 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002813
2814 // The usb driver needs to be closed after usb device disconnection
2815 // otherwise audio is no longer played on the new usb devices.
2816 // By forcing the stream in standby, the usb stack refcount drops to 0
2817 // and the driver is closed.
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002818 if (val == AUDIO_DEVICE_NONE &&
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002819 audio_is_usb_out_device(out->devices)) {
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002820 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2821 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2822 out_standby_l(&out->stream.common);
2823 }
2824 val = AUDIO_DEVICE_OUT_SPEAKER;
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002825 }
2826
Eric Laurent150dbfe2013-02-27 14:31:02 -08002827 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002828
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002829 /*
2830 * When HDMI cable is unplugged the music playback is paused and
2831 * the policy manager sends routing=0. But the audioflinger
2832 * continues to write data until standby time (3sec).
2833 * As the HDMI core is turned off, the write gets blocked.
2834 * Avoid this by routing audio to speaker until standby.
2835 */
2836 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2837 val == AUDIO_DEVICE_NONE) {
2838 val = AUDIO_DEVICE_OUT_SPEAKER;
2839 }
2840
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002841 /*
2842 * When A2DP is disconnected the
2843 * music playback is paused and the policy manager sends routing=0
2844 * But the audioflingercontinues to write data until standby time
2845 * (3sec). As BT is turned off, the write gets blocked.
2846 * Avoid this by routing audio to speaker until standby.
2847 */
2848 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2849 (val == AUDIO_DEVICE_NONE) &&
2850 !audio_extn_a2dp_is_ready()) {
2851 val = AUDIO_DEVICE_OUT_SPEAKER;
2852 }
2853
2854 /* To avoid a2dp to sco overlapping / BT device improper state
2855 * check with BT lib about a2dp streaming support before routing
2856 */
2857 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2858 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002859 if (val & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002860 //combo usecase just by pass a2dp
2861 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2862 bypass_a2dp = true;
2863 } else {
2864 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2865 /* update device to a2dp and don't route as BT returned error
2866 * However it is still possible a2dp routing called because
2867 * of current active device disconnection (like wired headset)
2868 */
2869 out->devices = val;
2870 pthread_mutex_unlock(&out->lock);
2871 pthread_mutex_unlock(&adev->lock);
2872 status = -ENOSYS;
2873 goto routing_fail;
2874 }
2875 }
2876 }
2877
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002878 audio_devices_t new_dev = val;
2879
2880 // Workaround: If routing to an non existing usb device, fail gracefully
2881 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002882 int card;
2883 if (audio_is_usb_out_device(new_dev) &&
2884 (card = get_alive_usb_card(parms)) >= 0) {
2885
2886 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002887 pthread_mutex_unlock(&adev->lock);
2888 pthread_mutex_unlock(&out->lock);
2889 status = -ENOSYS;
2890 goto routing_fail;
2891 }
2892
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002893 /*
2894 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002895 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002896 * the select_devices(). But how do we undo this?
2897 *
2898 * For example, music playback is active on headset (deep-buffer usecase)
2899 * and if we go to ringtones and select a ringtone, low-latency usecase
2900 * will be started on headset+speaker. As we can't enable headset+speaker
2901 * and headset devices at the same time, select_devices() switches the music
2902 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2903 * So when the ringtone playback is completed, how do we undo the same?
2904 *
2905 * We are relying on the out_set_parameters() call on deep-buffer output,
2906 * once the ringtone playback is ended.
2907 * NOTE: We should not check if the current devices are same as new devices.
2908 * Because select_devices() must be called to switch back the music
2909 * playback to headset.
2910 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002911 if (new_dev != AUDIO_DEVICE_NONE) {
2912 bool same_dev = out->devices == new_dev;
2913 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002914
Eric Laurenta7657192014-10-09 21:09:33 -07002915 if (output_drives_call(adev, out)) {
Vignesh Kulothungana5c9da12017-11-10 11:41:24 -08002916 if (!voice_is_call_state_active(adev)) {
Eric Laurenta7657192014-10-09 21:09:33 -07002917 if (adev->mode == AUDIO_MODE_IN_CALL) {
2918 adev->current_call_output = out;
2919 ret = voice_start_call(adev);
2920 }
2921 } else {
2922 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002923 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002924 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002925 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002926
2927 if (!out->standby) {
2928 if (!same_dev) {
2929 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002930 // inform adm before actual routing to prevent glitches.
2931 if (adev->adm_on_routing_change) {
2932 adev->adm_on_routing_change(adev->adm_data,
2933 out->handle);
2934 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002935 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002936 if (!bypass_a2dp) {
2937 select_devices(adev, out->usecase);
2938 } else {
juyuchen9baad392018-06-05 19:02:10 +08002939 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2940 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2941 else
2942 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002943 select_devices(adev, out->usecase);
2944 out->devices = new_dev;
2945 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002946 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002947
2948 // on device switch force swap, lower functions will make sure
2949 // to check if swap is allowed or not.
2950
2951 if (!same_dev)
2952 platform_set_swap_channels(adev, true);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002953
2954 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2955 out->a2dp_compress_mute &&
2956 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
2957 pthread_mutex_lock(&out->compr_mute_lock);
2958 out->a2dp_compress_mute = false;
2959 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
2960 pthread_mutex_unlock(&out->compr_mute_lock);
2961 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002962 }
2963
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002964 }
2965
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002966 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002967 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002968
2969 /*handles device and call state changes*/
2970 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002971 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002972 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002973
2974 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2975 parse_compress_metadata(out, parms);
2976 }
2977
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002978 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002979 ALOGV("%s: exit: code(%d)", __func__, status);
2980 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002981}
2982
Haynes Mathew George569b7482017-05-08 14:44:27 -07002983static bool stream_get_parameter_channels(struct str_parms *query,
2984 struct str_parms *reply,
2985 audio_channel_mask_t *supported_channel_masks) {
2986 int ret = -1;
Andy Hung64fdb452018-09-07 11:25:33 -07002987 char value[ARRAY_SIZE(channels_name_to_enum_table) * 32 /* max channel name size */];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002988 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002989 size_t i, j;
2990
2991 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2992 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002993 value[0] = '\0';
2994 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002995 while (supported_channel_masks[i] != 0) {
2996 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2997 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002998 if (!first) {
2999 strcat(value, "|");
3000 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003001 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003002 first = false;
3003 break;
3004 }
3005 }
3006 i++;
3007 }
3008 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003009 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003010 return ret >= 0;
3011}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003012
Haynes Mathew George569b7482017-05-08 14:44:27 -07003013static bool stream_get_parameter_formats(struct str_parms *query,
3014 struct str_parms *reply,
3015 audio_format_t *supported_formats) {
3016 int ret = -1;
3017 char value[256];
3018 int i;
3019
3020 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
3021 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003022 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07003023 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003024 case AUDIO_FORMAT_PCM_16_BIT:
3025 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
3026 break;
3027 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
3028 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
3029 break;
3030 case AUDIO_FORMAT_PCM_32_BIT:
3031 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
3032 break;
3033 default:
3034 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07003035 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003036 break;
3037 }
3038 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003039 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003040 return ret >= 0;
3041}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003042
Haynes Mathew George569b7482017-05-08 14:44:27 -07003043static bool stream_get_parameter_rates(struct str_parms *query,
3044 struct str_parms *reply,
3045 uint32_t *supported_sample_rates) {
3046
3047 int i;
3048 char value[256];
3049 int ret = -1;
3050 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
3051 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003052 value[0] = '\0';
3053 i=0;
3054 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003055 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003056 int avail = sizeof(value) - cursor;
3057 ret = snprintf(value + cursor, avail, "%s%d",
3058 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07003059 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003060 if (ret < 0 || ret >= avail) {
3061 // if cursor is at the last element of the array
3062 // overwrite with \0 is duplicate work as
3063 // snprintf already put a \0 in place.
3064 // else
3065 // we had space to write the '|' at value[cursor]
3066 // (which will be overwritten) or no space to fill
3067 // the first element (=> cursor == 0)
3068 value[cursor] = '\0';
3069 break;
3070 }
3071 cursor += ret;
3072 ++i;
3073 }
3074 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
3075 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003076 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003077 return ret >= 0;
3078}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003079
Haynes Mathew George569b7482017-05-08 14:44:27 -07003080static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
3081{
3082 struct stream_out *out = (struct stream_out *)stream;
3083 struct str_parms *query = str_parms_create_str(keys);
3084 char *str;
3085 struct str_parms *reply = str_parms_create();
3086 bool replied = false;
3087 ALOGV("%s: enter: keys - %s", __func__, keys);
3088
3089 replied |= stream_get_parameter_channels(query, reply,
3090 &out->supported_channel_masks[0]);
3091 replied |= stream_get_parameter_formats(query, reply,
3092 &out->supported_formats[0]);
3093 replied |= stream_get_parameter_rates(query, reply,
3094 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003095 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003096 str = str_parms_to_str(reply);
3097 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07003098 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003099 }
3100 str_parms_destroy(query);
3101 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07003102 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003103 return str;
3104}
3105
3106static uint32_t out_get_latency(const struct audio_stream_out *stream)
3107{
Haynes Mathew George03c40102016-01-29 17:57:48 -08003108 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003109 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003110 uint32_t latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003111
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003112 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3113 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003114 else if ((out->realtime) ||
3115 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003116 // since the buffer won't be filled up faster than realtime,
3117 // return a smaller number
3118 period_ms = (out->af_period_multiplier * out->config.period_size *
3119 1000) / (out->config.rate);
3120 hw_delay = platform_render_latency(out->usecase)/1000;
3121 return period_ms + hw_delay;
3122 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003123
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003124 latency = (out->config.period_count * out->config.period_size * 1000) /
3125 (out->config.rate);
3126
3127 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
3128 latency += audio_extn_a2dp_get_encoder_latency();
3129
3130 return latency;
3131}
3132
3133static int set_compr_volume(struct audio_stream_out *stream, float left,
3134 float right)
3135{
3136 struct stream_out *out = (struct stream_out *)stream;
3137 int volume[2];
3138 char mixer_ctl_name[128];
3139 struct audio_device *adev = out->dev;
3140 struct mixer_ctl *ctl;
3141 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
3142 PCM_PLAYBACK);
3143
3144 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3145 "Compress Playback %d Volume", pcm_device_id);
3146 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3147 if (!ctl) {
3148 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3149 __func__, mixer_ctl_name);
3150 return -EINVAL;
3151 }
3152 ALOGV("%s: ctl for mixer cmd - %s, left %f, right %f",
3153 __func__, mixer_ctl_name, left, right);
3154 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3155 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3156 mixer_ctl_set_array(ctl, volume, sizeof(volume) / sizeof(volume[0]));
3157
3158 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003159}
3160
3161static int out_set_volume(struct audio_stream_out *stream, float left,
3162 float right)
3163{
Eric Laurenta9024de2013-04-04 09:19:12 -07003164 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003165 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003166
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003167 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07003168 /* only take left channel into account: the API is for stereo anyway */
3169 out->muted = (left == 0.0f);
3170 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003171 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003172 pthread_mutex_lock(&out->compr_mute_lock);
3173 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
3174 if (!out->a2dp_compress_mute)
3175 ret = set_compr_volume(stream, left, right);
3176 out->volume_l = left;
3177 out->volume_r = right;
3178 pthread_mutex_unlock(&out->compr_mute_lock);
3179 return ret;
vivek mehtaa68fea62017-06-08 19:04:02 -07003180 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07003181 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
3182 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
3183 if (!out->standby) {
3184 // if in standby, cached volume will be sent after stream is opened
3185 audio_extn_utils_send_app_type_gain(out->dev,
3186 out->app_type_cfg.app_type,
3187 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07003188 }
vivek mehtaa68fea62017-06-08 19:04:02 -07003189 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07003190 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003191
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003192 return -ENOSYS;
3193}
3194
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003195// note: this call is safe only if the stream_cb is
3196// removed first in close_output_stream (as is done now).
3197static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3198{
3199 if (!stream || !parms)
3200 return;
3201
3202 struct stream_out *out = (struct stream_out *)stream;
3203 struct audio_device *adev = out->dev;
3204
3205 card_status_t status;
3206 int card;
3207 if (parse_snd_card_status(parms, &card, &status) < 0)
3208 return;
3209
3210 pthread_mutex_lock(&adev->lock);
3211 bool valid_cb = (card == adev->snd_card);
3212 pthread_mutex_unlock(&adev->lock);
3213
3214 if (!valid_cb)
3215 return;
3216
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003217 lock_output_stream(out);
3218 if (out->card_status != status)
3219 out->card_status = status;
3220 pthread_mutex_unlock(&out->lock);
3221
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07003222 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
3223 use_case_table[out->usecase],
3224 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3225
3226 if (status == CARD_STATUS_OFFLINE)
3227 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003228
3229 return;
3230}
3231
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003232#ifdef NO_AUDIO_OUT
3233static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05003234 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003235{
3236 struct stream_out *out = (struct stream_out *)stream;
3237
3238 /* No Output device supported other than BT for playback.
3239 * Sleep for the amount of buffer duration
3240 */
Eric Laurenta1478072015-09-21 17:21:52 -07003241 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05003242 usleep(bytes * 1000000 / audio_stream_out_frame_size(
3243 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003244 out_get_sample_rate(&out->stream.common));
3245 pthread_mutex_unlock(&out->lock);
3246 return bytes;
3247}
3248#endif
3249
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003250static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3251 size_t bytes)
3252{
3253 struct stream_out *out = (struct stream_out *)stream;
3254 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07003255 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07003256 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003257
Eric Laurenta1478072015-09-21 17:21:52 -07003258 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07003259 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07003260 const size_t frame_size = audio_stream_out_frame_size(stream);
3261 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07003262
Eric Laurent0e46adf2016-12-16 12:49:24 -08003263 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3264 error_code = ERROR_CODE_WRITE;
3265 goto exit;
3266 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003267
3268 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3269 (audio_extn_a2dp_is_suspended())) {
juyuchen9baad392018-06-05 19:02:10 +08003270 if (!(out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003271 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3272 ret = -EIO;
3273 goto exit;
3274 }
3275 }
3276 }
3277
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003278 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003279 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003280 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003281 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07003282
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003283 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003284 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003285 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07003286 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003287 goto exit;
3288 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07003289
vivek mehta40125092017-08-21 18:48:51 -07003290 // after standby always force set last known cal step
3291 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
3292 ALOGD("%s: retry previous failed cal level set", __func__);
3293 send_gain_dep_calibration_l();
3294 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003295 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003296
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003297 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003298 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003299 if (out->send_new_metadata) {
3300 ALOGVV("send new gapless metadata");
3301 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3302 out->send_new_metadata = 0;
3303 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003304 unsigned int avail;
3305 struct timespec tstamp;
3306 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
3307 /* Do not limit write size if the available frames count is unknown */
3308 if (ret != 0) {
3309 avail = bytes;
3310 }
3311 if (avail == 0) {
3312 ret = 0;
3313 } else {
3314 if (avail > bytes) {
3315 avail = bytes;
3316 }
3317 ret = compress_write(out->compr, buffer, avail);
3318 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
3319 __func__, avail, ret);
3320 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003321
Eric Laurent6e895242013-09-05 16:10:57 -07003322 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003323 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
3324 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003325 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003326 compress_start(out->compr);
3327 out->playback_started = 1;
3328 out->offload_state = OFFLOAD_STATE_PLAYING;
3329 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003330 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07003331 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07003332 } else {
3333 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07003334 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003335 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07003336 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003337 return ret;
3338 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07003339 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003340 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003341 size_t bytes_to_write = bytes;
3342
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003343 if (out->muted)
3344 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07003345 // FIXME: this can be removed once audio flinger mixer supports mono output
Nadav Bar3d72cfc2018-01-07 12:19:24 +02003346 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP || out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003347 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3348 int16_t *src = (int16_t *)buffer;
3349 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003350
Eric Laurentad2dde92017-09-20 18:27:31 -07003351 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
3352 out->format != AUDIO_FORMAT_PCM_16_BIT,
3353 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003354
Eric Laurentad2dde92017-09-20 18:27:31 -07003355 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
3356 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
3357 }
3358 bytes_to_write /= 2;
3359 }
3360 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes_to_write);
3361
Glenn Kasten5a59dff2018-02-22 08:05:35 -08003362 long ns = (frames * (int64_t) NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003363 request_out_focus(out, ns);
3364
3365 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08003366 if (use_mmap) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003367 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08003368 } else {
3369 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
3370 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3371 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
3372 size_t frame_size = channel_count * bytes_per_sample;
3373 size_t frame_count = bytes_to_write / frame_size;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003374
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08003375 bool force_haptic_path =
3376 property_get_bool("vendor.audio.test_haptic", false);
3377
3378 // extract Haptics data from Audio buffer
3379 bool alloc_haptic_buffer = false;
3380 int haptic_channel_count = adev->haptics_config.channels;
3381 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
3382 size_t audio_frame_size = frame_size - haptic_frame_size;
3383 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
3384
3385 if (adev->haptic_buffer == NULL) {
3386 alloc_haptic_buffer = true;
3387 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
3388 free(adev->haptic_buffer);
3389 adev->haptic_buffer_size = 0;
3390 alloc_haptic_buffer = true;
3391 }
3392
3393 if (alloc_haptic_buffer) {
3394 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
3395 adev->haptic_buffer_size = total_haptic_buffer_size;
3396 }
3397
3398 size_t src_index = 0, aud_index = 0, hap_index = 0;
3399 uint8_t *audio_buffer = (uint8_t *)buffer;
3400 uint8_t *haptic_buffer = adev->haptic_buffer;
3401
3402 // This is required for testing only. This works for stereo data only.
3403 // One channel is fed to audio stream and other to haptic stream for testing.
3404 if (force_haptic_path) {
3405 audio_frame_size = haptic_frame_size = bytes_per_sample;
3406 }
3407
3408 for (size_t i = 0; i < frame_count; i++) {
3409 for (size_t j = 0; j < audio_frame_size; j++)
3410 audio_buffer[aud_index++] = audio_buffer[src_index++];
3411
3412 for (size_t j = 0; j < haptic_frame_size; j++)
3413 haptic_buffer[hap_index++] = audio_buffer[src_index++];
3414 }
3415
3416 // This is required for testing only.
3417 // Discard haptic channel data.
3418 if (force_haptic_path) {
3419 src_index += haptic_frame_size;
3420 }
3421
3422 // write to audio pipeline
3423 ret = pcm_write(out->pcm,
3424 (void *)audio_buffer,
3425 frame_count * audio_frame_size);
3426
3427 // write to haptics pipeline
3428 if (adev->haptic_pcm)
3429 ret = pcm_write(adev->haptic_pcm,
3430 (void *)adev->haptic_buffer,
3431 frame_count * haptic_frame_size);
3432
3433 } else {
3434 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
3435 }
3436 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003437 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07003438 } else {
3439 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003440 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003441 }
3442
3443exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07003444 // For PCM we always consume the buffer and return #bytes regardless of ret.
3445 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003446 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07003447 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003448 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07003449
Andy Hung7401c7c2016-09-21 12:41:21 -07003450 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07003451 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07003452 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3453 ALOGE_IF(out->pcm != NULL,
3454 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07003455 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003456 // usleep not guaranteed for values over 1 second but we don't limit here.
3457 }
3458 }
Andy Hungda9b56b2016-09-16 20:06:35 -07003459
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003460 pthread_mutex_unlock(&out->lock);
3461
3462 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07003463 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003464 if (sleeptime_us != 0)
3465 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003466 }
3467 return bytes;
3468}
3469
3470static int out_get_render_position(const struct audio_stream_out *stream,
3471 uint32_t *dsp_frames)
3472{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003473 struct stream_out *out = (struct stream_out *)stream;
3474 *dsp_frames = 0;
3475 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07003476 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003477 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003478 unsigned long frames = 0;
3479 // TODO: check return value
3480 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
3481 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003482 ALOGVV("%s rendered frames %d sample_rate %d",
3483 __func__, *dsp_frames, out->sample_rate);
3484 }
3485 pthread_mutex_unlock(&out->lock);
3486 return 0;
3487 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003488 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003489}
3490
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003491static int out_add_audio_effect(const struct audio_stream *stream __unused,
3492 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003493{
3494 return 0;
3495}
3496
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003497static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3498 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003499{
3500 return 0;
3501}
3502
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003503static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3504 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003505{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003506 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003507}
3508
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003509static int out_get_presentation_position(const struct audio_stream_out *stream,
3510 uint64_t *frames, struct timespec *timestamp)
3511{
3512 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003513 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07003514 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003515
Eric Laurenta1478072015-09-21 17:21:52 -07003516 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003517
Eric Laurent949a0892013-09-20 09:20:13 -07003518 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3519 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003520 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07003521 compress_get_tstamp(out->compr, &dsp_frames,
3522 &out->sample_rate);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003523 // Adjustment accounts for A2DP encoder latency with offload usecases
3524 // Note: Encoder latency is returned in ms.
3525 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3526 unsigned long offset =
3527 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3528 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
3529 }
Eric Laurent949a0892013-09-20 09:20:13 -07003530 ALOGVV("%s rendered frames %ld sample_rate %d",
3531 __func__, dsp_frames, out->sample_rate);
3532 *frames = dsp_frames;
3533 ret = 0;
3534 /* this is the best we can do */
3535 clock_gettime(CLOCK_MONOTONIC, timestamp);
3536 }
3537 } else {
3538 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07003539 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003540 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3541 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003542 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003543 // This adjustment accounts for buffering after app processor.
3544 // It is based on estimated DSP latency per use case, rather than exact.
3545 signed_frames -=
3546 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3547
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003548 // Adjustment accounts for A2DP encoder latency with non-offload usecases
3549 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3550 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3551 signed_frames -=
3552 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3553 }
3554
Eric Laurent949a0892013-09-20 09:20:13 -07003555 // It would be unusual for this value to be negative, but check just in case ...
3556 if (signed_frames >= 0) {
3557 *frames = signed_frames;
3558 ret = 0;
3559 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003560 }
3561 }
3562 }
3563
3564 pthread_mutex_unlock(&out->lock);
3565
3566 return ret;
3567}
3568
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003569static int out_set_callback(struct audio_stream_out *stream,
3570 stream_callback_t callback, void *cookie)
3571{
3572 struct stream_out *out = (struct stream_out *)stream;
3573
3574 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003575 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003576 out->offload_callback = callback;
3577 out->offload_cookie = cookie;
3578 pthread_mutex_unlock(&out->lock);
3579 return 0;
3580}
3581
3582static int out_pause(struct audio_stream_out* stream)
3583{
3584 struct stream_out *out = (struct stream_out *)stream;
3585 int status = -ENOSYS;
3586 ALOGV("%s", __func__);
3587 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003588 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003589 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
3590 status = compress_pause(out->compr);
3591 out->offload_state = OFFLOAD_STATE_PAUSED;
3592 }
3593 pthread_mutex_unlock(&out->lock);
3594 }
3595 return status;
3596}
3597
3598static int out_resume(struct audio_stream_out* stream)
3599{
3600 struct stream_out *out = (struct stream_out *)stream;
3601 int status = -ENOSYS;
3602 ALOGV("%s", __func__);
3603 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3604 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07003605 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003606 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
3607 status = compress_resume(out->compr);
3608 out->offload_state = OFFLOAD_STATE_PLAYING;
3609 }
3610 pthread_mutex_unlock(&out->lock);
3611 }
3612 return status;
3613}
3614
3615static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3616{
3617 struct stream_out *out = (struct stream_out *)stream;
3618 int status = -ENOSYS;
3619 ALOGV("%s", __func__);
3620 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003621 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003622 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3623 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3624 else
3625 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3626 pthread_mutex_unlock(&out->lock);
3627 }
3628 return status;
3629}
3630
3631static int out_flush(struct audio_stream_out* stream)
3632{
3633 struct stream_out *out = (struct stream_out *)stream;
3634 ALOGV("%s", __func__);
3635 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003636 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003637 stop_compressed_output_l(out);
3638 pthread_mutex_unlock(&out->lock);
3639 return 0;
3640 }
3641 return -ENOSYS;
3642}
3643
Eric Laurent0e46adf2016-12-16 12:49:24 -08003644static int out_stop(const struct audio_stream_out* stream)
3645{
3646 struct stream_out *out = (struct stream_out *)stream;
3647 struct audio_device *adev = out->dev;
3648 int ret = -ENOSYS;
3649
3650 ALOGV("%s", __func__);
3651 pthread_mutex_lock(&adev->lock);
3652 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3653 out->playback_started && out->pcm != NULL) {
3654 pcm_stop(out->pcm);
3655 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08003656 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003657 }
3658 pthread_mutex_unlock(&adev->lock);
3659 return ret;
3660}
3661
3662static int out_start(const struct audio_stream_out* stream)
3663{
3664 struct stream_out *out = (struct stream_out *)stream;
3665 struct audio_device *adev = out->dev;
3666 int ret = -ENOSYS;
3667
3668 ALOGV("%s", __func__);
3669 pthread_mutex_lock(&adev->lock);
3670 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3671 !out->playback_started && out->pcm != NULL) {
3672 ret = start_output_stream(out);
3673 if (ret == 0) {
3674 out->playback_started = true;
3675 }
3676 }
3677 pthread_mutex_unlock(&adev->lock);
3678 return ret;
3679}
3680
Phil Burkbc991042017-02-24 08:06:44 -08003681/*
3682 * Modify config->period_count based on min_size_frames
3683 */
3684static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
3685{
3686 int periodCountRequested = (min_size_frames + config->period_size - 1)
3687 / config->period_size;
3688 int periodCount = MMAP_PERIOD_COUNT_MIN;
3689
3690 ALOGV("%s original config.period_size = %d config.period_count = %d",
3691 __func__, config->period_size, config->period_count);
3692
3693 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
3694 periodCount *= 2;
3695 }
3696 config->period_count = periodCount;
3697
3698 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
3699}
3700
Eric Laurent0e46adf2016-12-16 12:49:24 -08003701static int out_create_mmap_buffer(const struct audio_stream_out *stream,
3702 int32_t min_size_frames,
3703 struct audio_mmap_buffer_info *info)
3704{
3705 struct stream_out *out = (struct stream_out *)stream;
3706 struct audio_device *adev = out->dev;
3707 int ret = 0;
3708 unsigned int offset1;
3709 unsigned int frames1;
3710 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003711 uint32_t mmap_size;
3712 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003713
3714 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003715 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003716 pthread_mutex_lock(&adev->lock);
3717
3718 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003719 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003720 ret = -EINVAL;
3721 goto exit;
3722 }
3723 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003724 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003725 ret = -ENOSYS;
3726 goto exit;
3727 }
3728 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3729 if (out->pcm_device_id < 0) {
3730 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3731 __func__, out->pcm_device_id, out->usecase);
3732 ret = -EINVAL;
3733 goto exit;
3734 }
Phil Burkbc991042017-02-24 08:06:44 -08003735
3736 adjust_mmap_period_count(&out->config, min_size_frames);
3737
Eric Laurent0e46adf2016-12-16 12:49:24 -08003738 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3739 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3740 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3741 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3742 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3743 step = "open";
3744 ret = -ENODEV;
3745 goto exit;
3746 }
3747 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3748 if (ret < 0) {
3749 step = "begin";
3750 goto exit;
3751 }
3752 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003753 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003754 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003755 ret = platform_get_mmap_data_fd(adev->platform,
3756 out->pcm_device_id, 0 /*playback*/,
3757 &info->shared_memory_fd,
3758 &mmap_size);
3759 if (ret < 0) {
3760 // Fall back to non exclusive mode
3761 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3762 } else {
3763 if (mmap_size < buffer_size) {
3764 step = "mmap";
3765 goto exit;
3766 }
3767 // FIXME: indicate exclusive mode support by returning a negative buffer size
3768 info->buffer_size_frames *= -1;
3769 }
3770 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003771
3772 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3773 if (ret < 0) {
3774 step = "commit";
3775 goto exit;
3776 }
Phil Burkbc991042017-02-24 08:06:44 -08003777
3778 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003779 ret = 0;
3780
3781 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3782 __func__, info->shared_memory_address, info->buffer_size_frames);
3783
3784exit:
3785 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003786 if (out->pcm == NULL) {
3787 ALOGE("%s: %s - %d", __func__, step, ret);
3788 } else {
3789 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003790 pcm_close(out->pcm);
3791 out->pcm = NULL;
3792 }
3793 }
3794 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003795 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003796 return ret;
3797}
3798
3799static int out_get_mmap_position(const struct audio_stream_out *stream,
3800 struct audio_mmap_position *position)
3801{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003802 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003803 struct stream_out *out = (struct stream_out *)stream;
3804 ALOGVV("%s", __func__);
3805 if (position == NULL) {
3806 return -EINVAL;
3807 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003808 lock_output_stream(out);
3809 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3810 out->pcm == NULL) {
3811 ret = -ENOSYS;
3812 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003813 }
3814
3815 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003816 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003817 if (ret < 0) {
3818 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003819 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003820 }
Andy Hungfc044e12017-03-20 09:24:22 -07003821 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003822exit:
3823 pthread_mutex_unlock(&out->lock);
3824 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003825}
3826
3827
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003828/** audio_stream_in implementation **/
3829static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3830{
3831 struct stream_in *in = (struct stream_in *)stream;
3832
3833 return in->config.rate;
3834}
3835
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003836static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003837{
3838 return -ENOSYS;
3839}
3840
3841static size_t in_get_buffer_size(const struct audio_stream *stream)
3842{
3843 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003844 return in->config.period_size * in->af_period_multiplier *
3845 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003846}
3847
3848static uint32_t in_get_channels(const struct audio_stream *stream)
3849{
3850 struct stream_in *in = (struct stream_in *)stream;
3851
3852 return in->channel_mask;
3853}
3854
vivek mehta4ed66e62016-04-15 23:33:34 -07003855static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003856{
vivek mehta4ed66e62016-04-15 23:33:34 -07003857 struct stream_in *in = (struct stream_in *)stream;
3858 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003859}
3860
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003861static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003862{
3863 return -ENOSYS;
3864}
3865
3866static int in_standby(struct audio_stream *stream)
3867{
3868 struct stream_in *in = (struct stream_in *)stream;
3869 struct audio_device *adev = in->dev;
3870 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003871 bool do_stop = true;
3872
Eric Laurent994a6932013-07-17 11:51:42 -07003873 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003874
3875 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003876
3877 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003878 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003879 audio_extn_sound_trigger_stop_lab(in);
3880 in->standby = true;
3881 }
3882
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003883 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003884 if (adev->adm_deregister_stream)
3885 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3886
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003887 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003888 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003889 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003890 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003891 in->capture_started = false;
3892 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003893 if (in->pcm) {
3894 pcm_close(in->pcm);
3895 in->pcm = NULL;
3896 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003897 adev->enable_voicerx = false;
3898 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003899 if (do_stop) {
3900 status = stop_input_stream(in);
3901 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003902 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003903 }
3904 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003905 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003906 return status;
3907}
3908
Andy Hungd13f0d32017-06-12 13:58:37 -07003909static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003910{
Andy Hungd13f0d32017-06-12 13:58:37 -07003911 struct stream_in *in = (struct stream_in *)stream;
3912
3913 // We try to get the lock for consistency,
3914 // but it isn't necessary for these variables.
3915 // If we're not in standby, we may be blocked on a read.
3916 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3917 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3918 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3919 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3920
3921 if (locked) {
3922 pthread_mutex_unlock(&in->lock);
3923 }
3924
3925 // dump error info
3926 (void)error_log_dump(
3927 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003928 return 0;
3929}
3930
3931static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3932{
3933 struct stream_in *in = (struct stream_in *)stream;
3934 struct audio_device *adev = in->dev;
3935 struct str_parms *parms;
3936 char *str;
3937 char value[32];
3938 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003939 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003940
Eric Laurent994a6932013-07-17 11:51:42 -07003941 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003942 parms = str_parms_create_str(kvpairs);
3943
3944 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3945
Eric Laurenta1478072015-09-21 17:21:52 -07003946 lock_input_stream(in);
3947
Eric Laurent150dbfe2013-02-27 14:31:02 -08003948 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003949 if (ret >= 0) {
3950 val = atoi(value);
3951 /* no audio source uses val == 0 */
3952 if ((in->source != val) && (val != 0)) {
3953 in->source = val;
3954 }
3955 }
3956
3957 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003958
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003959 if (ret >= 0) {
3960 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003961 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003962
3963 // Workaround: If routing to an non existing usb device, fail gracefully
3964 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003965 int card;
3966 if (audio_is_usb_in_device(val) &&
3967 (card = get_alive_usb_card(parms)) >= 0) {
3968
3969 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003970 status = -ENOSYS;
3971 } else {
3972
3973 in->device = val;
3974 /* If recording is in progress, change the tx device to new device */
3975 if (!in->standby) {
3976 ALOGV("update input routing change");
3977 // inform adm before actual routing to prevent glitches.
3978 if (adev->adm_on_routing_change) {
3979 adev->adm_on_routing_change(adev->adm_data,
3980 in->capture_handle);
3981 }
3982 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003983 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003984 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003985 }
3986 }
3987
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003988 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003989 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003990
3991 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003992 ALOGV("%s: exit: status(%d)", __func__, status);
3993 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003994}
3995
Haynes Mathew George569b7482017-05-08 14:44:27 -07003996static char* in_get_parameters(const struct audio_stream *stream,
3997 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003998{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003999 struct stream_in *in = (struct stream_in *)stream;
4000 struct str_parms *query = str_parms_create_str(keys);
4001 char *str;
4002 struct str_parms *reply = str_parms_create();
4003 bool replied = false;
4004
4005 ALOGV("%s: enter: keys - %s", __func__, keys);
4006 replied |= stream_get_parameter_channels(query, reply,
4007 &in->supported_channel_masks[0]);
4008 replied |= stream_get_parameter_formats(query, reply,
4009 &in->supported_formats[0]);
4010 replied |= stream_get_parameter_rates(query, reply,
4011 &in->supported_sample_rates[0]);
4012 if (replied) {
4013 str = str_parms_to_str(reply);
4014 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07004015 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07004016 }
4017 str_parms_destroy(query);
4018 str_parms_destroy(reply);
4019 ALOGV("%s: exit: returns - %s", __func__, str);
4020 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004021}
4022
Eric Laurent51f3c662018-04-10 18:21:34 -07004023static int in_set_gain(struct audio_stream_in *stream, float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004024{
Eric Laurent51f3c662018-04-10 18:21:34 -07004025 struct stream_in *in = (struct stream_in *)stream;
4026 char mixer_ctl_name[128];
4027 struct mixer_ctl *ctl;
4028 int ctl_value;
4029
4030 ALOGV("%s: gain %f", __func__, gain);
4031
4032 if (stream == NULL)
4033 return -EINVAL;
4034
4035 /* in_set_gain() only used to silence MMAP capture for now */
4036 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
4037 return -ENOSYS;
4038
4039 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
4040
4041 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
4042 if (!ctl) {
4043 ALOGW("%s: Could not get ctl for mixer cmd - %s",
4044 __func__, mixer_ctl_name);
4045 return -ENOSYS;
4046 }
4047
4048 if (gain < RECORD_GAIN_MIN)
4049 gain = RECORD_GAIN_MIN;
4050 else if (gain > RECORD_GAIN_MAX)
4051 gain = RECORD_GAIN_MAX;
4052 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
4053
4054 mixer_ctl_set_value(ctl, 0, ctl_value);
4055 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004056}
4057
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004058static void in_snd_mon_cb(void * stream, struct str_parms * parms)
4059{
4060 if (!stream || !parms)
4061 return;
4062
4063 struct stream_in *in = (struct stream_in *)stream;
4064 struct audio_device *adev = in->dev;
4065
4066 card_status_t status;
4067 int card;
4068 if (parse_snd_card_status(parms, &card, &status) < 0)
4069 return;
4070
4071 pthread_mutex_lock(&adev->lock);
4072 bool valid_cb = (card == adev->snd_card);
4073 pthread_mutex_unlock(&adev->lock);
4074
4075 if (!valid_cb)
4076 return;
4077
4078 lock_input_stream(in);
4079 if (in->card_status != status)
4080 in->card_status = status;
4081 pthread_mutex_unlock(&in->lock);
4082
4083 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
4084 use_case_table[in->usecase],
4085 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4086
4087 // a better solution would be to report error back to AF and let
4088 // it put the stream to standby
4089 if (status == CARD_STATUS_OFFLINE)
4090 in_standby(&in->stream.common);
4091
4092 return;
4093}
4094
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004095static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
4096 size_t bytes)
4097{
4098 struct stream_in *in = (struct stream_in *)stream;
4099 struct audio_device *adev = in->dev;
4100 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07004101 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07004102 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004103
Eric Laurenta1478072015-09-21 17:21:52 -07004104 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07004105 const size_t frame_size = audio_stream_in_frame_size(stream);
4106 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07004107
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004108 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004109 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004110 /* Read from sound trigger HAL */
4111 audio_extn_sound_trigger_read(in, buffer, bytes);
4112 pthread_mutex_unlock(&in->lock);
4113 return bytes;
4114 }
4115
Eric Laurent0e46adf2016-12-16 12:49:24 -08004116 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
4117 ret = -ENOSYS;
4118 goto exit;
4119 }
4120
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004121 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004122 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004123 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004124 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004125 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004126 goto exit;
4127 }
4128 in->standby = 0;
4129 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004130
Andy Hungd13f0d32017-06-12 13:58:37 -07004131 // errors that occur here are read errors.
4132 error_code = ERROR_CODE_READ;
4133
Haynes Mathew George03c40102016-01-29 17:57:48 -08004134 //what's the duration requested by the client?
4135 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
4136 in->config.rate;
4137 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004138
Haynes Mathew George03c40102016-01-29 17:57:48 -08004139 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004140 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08004141 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004142 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07004143 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004144 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004145 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004146 if (ret < 0) {
4147 ALOGE("Failed to read w/err %s", strerror(errno));
4148 ret = -errno;
4149 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004150 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4151 if (bytes % 4 == 0) {
4152 /* data from DSP comes in 24_8 format, convert it to 8_24 */
4153 int_buf_stream = buffer;
4154 for (size_t itt=0; itt < bytes/4 ; itt++) {
4155 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07004156 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004157 } else {
4158 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
4159 ret = -EINVAL;
4160 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07004161 }
4162 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004163 }
4164
Haynes Mathew George03c40102016-01-29 17:57:48 -08004165 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004166
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004167 /*
4168 * Instead of writing zeroes here, we could trust the hardware
4169 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004170 * 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 -08004171 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08004172 if (ret == 0 && adev->mic_muted &&
4173 !voice_is_in_call_rec_stream(in) &&
4174 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004175 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07004176 in->frames_muted += frames;
4177 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004178
4179exit:
4180 pthread_mutex_unlock(&in->lock);
4181
4182 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07004183 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004184 in_standby(&in->stream.common);
4185 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07004186 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08004187 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07004188 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08004189 }
4190 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07004191 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004192 }
4193 return bytes;
4194}
4195
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004196static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004197{
4198 return 0;
4199}
4200
Andy Hung6ebe5962016-01-15 17:46:57 -08004201static int in_get_capture_position(const struct audio_stream_in *stream,
4202 int64_t *frames, int64_t *time)
4203{
4204 if (stream == NULL || frames == NULL || time == NULL) {
4205 return -EINVAL;
4206 }
4207 struct stream_in *in = (struct stream_in *)stream;
4208 int ret = -ENOSYS;
4209
4210 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08004211 // note: ST sessions do not close the alsa pcm driver synchronously
4212 // on standby. Therefore, we may return an error even though the
4213 // pcm stream is still opened.
4214 if (in->standby) {
4215 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
4216 "%s stream in standby but pcm not NULL for non ST session", __func__);
4217 goto exit;
4218 }
Andy Hung6ebe5962016-01-15 17:46:57 -08004219 if (in->pcm) {
4220 struct timespec timestamp;
4221 unsigned int avail;
4222 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
4223 *frames = in->frames_read + avail;
4224 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
4225 ret = 0;
4226 }
4227 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08004228exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08004229 pthread_mutex_unlock(&in->lock);
4230 return ret;
4231}
4232
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004233static int add_remove_audio_effect(const struct audio_stream *stream,
4234 effect_handle_t effect,
4235 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004236{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004237 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004238 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004239 int status = 0;
4240 effect_descriptor_t desc;
4241
4242 status = (*effect)->get_descriptor(effect, &desc);
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004243 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
4244
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004245 if (status != 0)
4246 return status;
4247
Eric Laurenta1478072015-09-21 17:21:52 -07004248 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004249 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07004250 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07004251 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07004252 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004253 in->enable_aec != enable &&
4254 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
4255 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004256 if (!enable)
4257 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07004258 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
4259 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
4260 adev->enable_voicerx = enable;
4261 struct audio_usecase *usecase;
4262 struct listnode *node;
4263 list_for_each(node, &adev->usecase_list) {
4264 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07004265 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07004266 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05004267 }
4268 }
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004269 if (!in->standby
4270 && enable_disable_effect(in->dev, in, EFFECT_AEC, enable) == -ENOSYS)
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004271 select_devices(in->dev, in->usecase);
4272 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07004273 if (in->enable_ns != enable &&
4274 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
4275 in->enable_ns = enable;
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004276 if (!in->standby) {
4277 if (in->source != AUDIO_SOURCE_VOICE_COMMUNICATION
4278 || enable_disable_effect(in->dev, in, EFFECT_NS, enable) == -ENOSYS)
4279 select_devices(in->dev, in->usecase);
4280 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07004281 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004282 pthread_mutex_unlock(&in->dev->lock);
4283 pthread_mutex_unlock(&in->lock);
4284
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004285 return 0;
4286}
4287
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004288static int in_add_audio_effect(const struct audio_stream *stream,
4289 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004290{
Eric Laurent994a6932013-07-17 11:51:42 -07004291 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004292 return add_remove_audio_effect(stream, effect, true);
4293}
4294
4295static int in_remove_audio_effect(const struct audio_stream *stream,
4296 effect_handle_t effect)
4297{
Eric Laurent994a6932013-07-17 11:51:42 -07004298 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004299 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004300}
4301
Eric Laurent0e46adf2016-12-16 12:49:24 -08004302static int in_stop(const struct audio_stream_in* stream)
4303{
4304 struct stream_in *in = (struct stream_in *)stream;
4305 struct audio_device *adev = in->dev;
4306
4307 int ret = -ENOSYS;
4308 ALOGV("%s", __func__);
4309 pthread_mutex_lock(&adev->lock);
4310 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4311 in->capture_started && in->pcm != NULL) {
4312 pcm_stop(in->pcm);
4313 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08004314 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004315 }
4316 pthread_mutex_unlock(&adev->lock);
4317 return ret;
4318}
4319
4320static int in_start(const struct audio_stream_in* stream)
4321{
4322 struct stream_in *in = (struct stream_in *)stream;
4323 struct audio_device *adev = in->dev;
4324 int ret = -ENOSYS;
4325
4326 ALOGV("%s in %p", __func__, in);
4327 pthread_mutex_lock(&adev->lock);
4328 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4329 !in->capture_started && in->pcm != NULL) {
4330 if (!in->capture_started) {
4331 ret = start_input_stream(in);
4332 if (ret == 0) {
4333 in->capture_started = true;
4334 }
4335 }
4336 }
4337 pthread_mutex_unlock(&adev->lock);
4338 return ret;
4339}
4340
4341static int in_create_mmap_buffer(const struct audio_stream_in *stream,
4342 int32_t min_size_frames,
4343 struct audio_mmap_buffer_info *info)
4344{
4345 struct stream_in *in = (struct stream_in *)stream;
4346 struct audio_device *adev = in->dev;
4347 int ret = 0;
4348 unsigned int offset1;
4349 unsigned int frames1;
4350 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07004351 uint32_t mmap_size;
4352 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004353
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004354 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004355 pthread_mutex_lock(&adev->lock);
4356 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08004357
Eric Laurent0e46adf2016-12-16 12:49:24 -08004358 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004359 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004360 ret = -EINVAL;
4361 goto exit;
4362 }
4363 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08004364 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004365 ALOGV("%s in %p", __func__, in);
4366 ret = -ENOSYS;
4367 goto exit;
4368 }
4369 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
4370 if (in->pcm_device_id < 0) {
4371 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4372 __func__, in->pcm_device_id, in->usecase);
4373 ret = -EINVAL;
4374 goto exit;
4375 }
Phil Burkbc991042017-02-24 08:06:44 -08004376
4377 adjust_mmap_period_count(&in->config, min_size_frames);
4378
Eric Laurent0e46adf2016-12-16 12:49:24 -08004379 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4380 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
4381 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
4382 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
4383 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
4384 step = "open";
4385 ret = -ENODEV;
4386 goto exit;
4387 }
4388
4389 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
4390 if (ret < 0) {
4391 step = "begin";
4392 goto exit;
4393 }
4394 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07004395 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004396 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07004397 ret = platform_get_mmap_data_fd(adev->platform,
4398 in->pcm_device_id, 1 /*capture*/,
4399 &info->shared_memory_fd,
4400 &mmap_size);
4401 if (ret < 0) {
4402 // Fall back to non exclusive mode
4403 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
4404 } else {
4405 if (mmap_size < buffer_size) {
4406 step = "mmap";
4407 goto exit;
4408 }
4409 // FIXME: indicate exclusive mode support by returning a negative buffer size
4410 info->buffer_size_frames *= -1;
4411 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08004412
Haynes Mathew George96483a22017-03-28 14:52:47 -07004413 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004414
4415 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4416 if (ret < 0) {
4417 step = "commit";
4418 goto exit;
4419 }
4420
Phil Burkbc991042017-02-24 08:06:44 -08004421 in->standby = false;
4422 ret = 0;
4423
Eric Laurent0e46adf2016-12-16 12:49:24 -08004424 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4425 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004426
4427exit:
4428 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004429 if (in->pcm == NULL) {
4430 ALOGE("%s: %s - %d", __func__, step, ret);
4431 } else {
4432 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08004433 pcm_close(in->pcm);
4434 in->pcm = NULL;
4435 }
4436 }
4437 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004438 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004439 return ret;
4440}
4441
4442static int in_get_mmap_position(const struct audio_stream_in *stream,
4443 struct audio_mmap_position *position)
4444{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004445 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004446 struct stream_in *in = (struct stream_in *)stream;
4447 ALOGVV("%s", __func__);
4448 if (position == NULL) {
4449 return -EINVAL;
4450 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004451 lock_input_stream(in);
4452 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
4453 in->pcm == NULL) {
4454 ret = -ENOSYS;
4455 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004456 }
4457 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004458 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004459 if (ret < 0) {
4460 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004461 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004462 }
Andy Hungfc044e12017-03-20 09:24:22 -07004463 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004464exit:
4465 pthread_mutex_unlock(&in->lock);
4466 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004467}
4468
jiabin8962a4d2018-03-19 18:21:24 -07004469static int in_get_active_microphones(const struct audio_stream_in *stream,
4470 struct audio_microphone_characteristic_t *mic_array,
4471 size_t *mic_count) {
4472 struct stream_in *in = (struct stream_in *)stream;
4473 struct audio_device *adev = in->dev;
4474 ALOGVV("%s", __func__);
4475
4476 lock_input_stream(in);
4477 pthread_mutex_lock(&adev->lock);
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004478 int ret = platform_get_active_microphones(adev->platform,
jiabin8962a4d2018-03-19 18:21:24 -07004479 audio_channel_count_from_in_mask(in->channel_mask),
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004480 in->usecase, mic_array, mic_count);
jiabin8962a4d2018-03-19 18:21:24 -07004481 pthread_mutex_unlock(&adev->lock);
4482 pthread_mutex_unlock(&in->lock);
4483
4484 return ret;
4485}
4486
4487static int adev_get_microphones(const struct audio_hw_device *dev,
4488 struct audio_microphone_characteristic_t *mic_array,
4489 size_t *mic_count) {
4490 struct audio_device *adev = (struct audio_device *)dev;
4491 ALOGVV("%s", __func__);
4492
4493 pthread_mutex_lock(&adev->lock);
4494 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
4495 pthread_mutex_unlock(&adev->lock);
4496
4497 return ret;
4498}
Eric Laurent0e46adf2016-12-16 12:49:24 -08004499
Paul McLean57530d52018-12-17 08:24:21 -07004500static int in_set_microphone_direction(const struct audio_stream_in *stream,
4501 audio_microphone_direction_t dir) {
4502 (void)stream;
4503 (void)dir;
4504 ALOGVV("%s", __func__);
4505 return -ENOSYS;
4506}
4507
4508static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
4509 (void)stream;
4510 (void)zoom;
4511 ALOGVV("%s", __func__);
4512 return -ENOSYS;
4513}
4514
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004515static int adev_open_output_stream(struct audio_hw_device *dev,
4516 audio_io_handle_t handle,
4517 audio_devices_t devices,
4518 audio_output_flags_t flags,
4519 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07004520 struct audio_stream_out **stream_out,
4521 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004522{
4523 struct audio_device *adev = (struct audio_device *)dev;
4524 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004525 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004526 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
4527 bool is_usb_dev = audio_is_usb_out_device(devices) &&
4528 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08004529 bool force_haptic_path =
4530 property_get_bool("vendor.audio.test_haptic", false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004531
Andy Hungd9653bd2017-08-01 19:31:39 -07004532 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
4533 return -ENOSYS;
4534 }
4535
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004536 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
4537 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08004538
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004539 *stream_out = NULL;
4540 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4541
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004542 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
4543
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004544 if (devices == AUDIO_DEVICE_NONE)
4545 devices = AUDIO_DEVICE_OUT_SPEAKER;
4546
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004547 out->flags = flags;
4548 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004549 out->dev = adev;
Eric Laurentc4aef752013-09-12 17:45:53 -07004550 out->handle = handle;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004551 out->a2dp_compress_mute = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004552
4553 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004554 if ((is_hdmi || is_usb_dev) &&
4555 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
4556 (flags == AUDIO_OUTPUT_FLAG_NONE ||
4557 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Eric Laurentab805ee2018-03-30 12:20:38 -07004558 audio_format_t req_format = config->format;
4559 audio_channel_mask_t req_channel_mask = config->channel_mask;
4560 uint32_t req_sample_rate = config->sample_rate;
4561
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004562 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004563 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004564 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004565 if (config->sample_rate == 0)
4566 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Eric Laurentab805ee2018-03-30 12:20:38 -07004567 if (config->channel_mask == AUDIO_CHANNEL_NONE)
Haynes Mathew George569b7482017-05-08 14:44:27 -07004568 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
4569 if (config->format == AUDIO_FORMAT_DEFAULT)
4570 config->format = AUDIO_FORMAT_PCM_16_BIT;
4571 } else if (is_usb_dev) {
4572 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
4573 &config->format,
4574 &out->supported_formats[0],
4575 MAX_SUPPORTED_FORMATS,
4576 &config->channel_mask,
4577 &out->supported_channel_masks[0],
4578 MAX_SUPPORTED_CHANNEL_MASKS,
4579 &config->sample_rate,
4580 &out->supported_sample_rates[0],
4581 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004582 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004583 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004584 pthread_mutex_unlock(&adev->lock);
Eric Laurentab805ee2018-03-30 12:20:38 -07004585 if (ret != 0) {
4586 // For MMAP NO IRQ, allow conversions in ADSP
4587 if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
4588 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004589
Eric Laurentab805ee2018-03-30 12:20:38 -07004590 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
4591 config->sample_rate = req_sample_rate;
4592 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
4593 config->channel_mask = req_channel_mask;
4594 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
4595 config->format = req_format;
4596 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004597
Haynes Mathew George569b7482017-05-08 14:44:27 -07004598 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004599 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004600 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004601 if (is_hdmi) {
4602 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4603 out->config = pcm_config_hdmi_multi;
4604 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
4605 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4606 out->config = pcm_config_mmap_playback;
4607 out->stream.start = out_start;
4608 out->stream.stop = out_stop;
4609 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4610 out->stream.get_mmap_position = out_get_mmap_position;
4611 } else {
4612 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4613 out->config = pcm_config_hifi;
4614 }
4615
4616 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004617 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004618 if (is_hdmi) {
4619 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
4620 audio_bytes_per_sample(out->format));
4621 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004622 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004623 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07004624 pthread_mutex_lock(&adev->lock);
4625 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4626 pthread_mutex_unlock(&adev->lock);
4627
4628 // reject offload during card offline to allow
4629 // fallback to s/w paths
4630 if (offline) {
4631 ret = -ENODEV;
4632 goto error_open;
4633 }
4634
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004635 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4636 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4637 ALOGE("%s: Unsupported Offload information", __func__);
4638 ret = -EINVAL;
4639 goto error_open;
4640 }
4641 if (!is_supported_format(config->offload_info.format)) {
4642 ALOGE("%s: Unsupported audio format", __func__);
4643 ret = -EINVAL;
4644 goto error_open;
4645 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004646 out->sample_rate = config->offload_info.sample_rate;
4647 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
4648 out->channel_mask = config->offload_info.channel_mask;
4649 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
4650 out->channel_mask = config->channel_mask;
4651 else
4652 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4653
4654 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004655
4656 out->compr_config.codec = (struct snd_codec *)
4657 calloc(1, sizeof(struct snd_codec));
4658
4659 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004660
4661 out->stream.set_callback = out_set_callback;
4662 out->stream.pause = out_pause;
4663 out->stream.resume = out_resume;
4664 out->stream.drain = out_drain;
4665 out->stream.flush = out_flush;
4666
4667 out->compr_config.codec->id =
4668 get_snd_codec_id(config->offload_info.format);
4669 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
4670 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004671 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004672 out->compr_config.codec->bit_rate =
4673 config->offload_info.bit_rate;
4674 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004675 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004676 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
4677
4678 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4679 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004680
4681 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004682 create_offload_callback_thread(out);
4683 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4684 __func__, config->offload_info.version,
4685 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02004686 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4687 switch (config->sample_rate) {
4688 case 0:
4689 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4690 break;
4691 case 8000:
4692 case 16000:
4693 case 48000:
4694 out->sample_rate = config->sample_rate;
4695 break;
4696 default:
4697 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
4698 config->sample_rate);
4699 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4700 ret = -EINVAL;
4701 goto error_open;
4702 }
4703 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4704 switch (config->channel_mask) {
4705 case AUDIO_CHANNEL_NONE:
4706 case AUDIO_CHANNEL_OUT_STEREO:
4707 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4708 break;
4709 default:
4710 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
4711 config->channel_mask);
4712 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4713 ret = -EINVAL;
4714 goto error_open;
4715 }
4716 switch (config->format) {
4717 case AUDIO_FORMAT_DEFAULT:
4718 case AUDIO_FORMAT_PCM_16_BIT:
4719 out->format = AUDIO_FORMAT_PCM_16_BIT;
4720 break;
4721 default:
4722 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
4723 config->format);
4724 config->format = AUDIO_FORMAT_PCM_16_BIT;
4725 ret = -EINVAL;
4726 goto error_open;
4727 }
4728
4729 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004730 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004731 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004732 case 0:
4733 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
4734 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07004735 case 8000:
4736 case 16000:
4737 case 48000:
4738 out->sample_rate = config->sample_rate;
4739 break;
4740 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004741 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
4742 config->sample_rate);
4743 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4744 ret = -EINVAL;
4745 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004746 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004747 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4748 switch (config->channel_mask) {
4749 case AUDIO_CHANNEL_NONE:
4750 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4751 break;
4752 case AUDIO_CHANNEL_OUT_STEREO:
4753 out->channel_mask = config->channel_mask;
4754 break;
4755 default:
4756 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
4757 config->channel_mask);
4758 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4759 ret = -EINVAL;
4760 break;
4761 }
4762 switch (config->format) {
4763 case AUDIO_FORMAT_DEFAULT:
4764 out->format = AUDIO_FORMAT_PCM_16_BIT;
4765 break;
4766 case AUDIO_FORMAT_PCM_16_BIT:
4767 out->format = config->format;
4768 break;
4769 default:
4770 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
4771 config->format);
4772 config->format = AUDIO_FORMAT_PCM_16_BIT;
4773 ret = -EINVAL;
4774 break;
4775 }
4776 if (ret != 0)
4777 goto error_open;
4778
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004779 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4780 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004781 out->config.rate = out->sample_rate;
4782 out->config.channels =
4783 audio_channel_count_from_out_mask(out->channel_mask);
4784 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004785 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004786 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
4787 switch (config->sample_rate) {
4788 case 0:
4789 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4790 break;
4791 case 8000:
4792 case 16000:
4793 case 32000:
4794 case 48000:
4795 out->sample_rate = config->sample_rate;
4796 break;
4797 default:
4798 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
4799 config->sample_rate);
4800 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4801 ret = -EINVAL;
4802 break;
4803 }
Eric Laurentad2dde92017-09-20 18:27:31 -07004804 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004805 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 Voip RX", __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 Voip RX", __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
vivek mehtaa68fea62017-06-08 19:04:02 -07004836 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07004837 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4838 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004839 out->config.rate = out->sample_rate;
4840 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07004841 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004842 out->sample_rate,
4843 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07004844 out->config.channels,
4845 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004846 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07004847 out->config.period_size = buffer_size / frame_size;
4848 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
4849 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004850 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004851 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07004852 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4853 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004854 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07004855 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
4856 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004857 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07004858 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004859 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004860 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004861 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004862 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4863 out->config = pcm_config_mmap_playback;
4864 out->stream.start = out_start;
4865 out->stream.stop = out_stop;
4866 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4867 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004868 } else {
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08004869 if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
4870 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
4871 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
4872 if (adev->haptic_pcm_device_id < 0) {
4873 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
4874 __func__, adev->haptic_pcm_device_id, out->usecase);
4875 ret = -ENOSYS;
4876 goto error_open;
4877 }
4878 out->config = pcm_config_haptics_audio;
4879 if (force_haptic_path)
4880 adev->haptics_config = pcm_config_haptics_audio;
4881 else
4882 adev->haptics_config = pcm_config_haptics;
4883 } else {
4884 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4885 out->config = pcm_config_low_latency;
4886 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07004887 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004888
4889 if (config->sample_rate == 0) {
4890 out->sample_rate = out->config.rate;
4891 } else {
4892 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004893 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08004894
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004895 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
4896 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
4897 } else {
4898 out->channel_mask = config->channel_mask;
4899 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08004900
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004901 if (config->format == AUDIO_FORMAT_DEFAULT)
4902 out->format = audio_format_from_pcm_format(out->config.format);
4903 else if (!audio_is_linear_pcm(config->format)) {
4904 config->format = AUDIO_FORMAT_PCM_16_BIT;
4905 ret = -EINVAL;
4906 goto error_open;
4907 } else {
4908 out->format = config->format;
4909 }
4910
4911 out->config.rate = out->sample_rate;
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08004912
4913 if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
4914 out->config.channels =
4915 audio_channel_count_from_out_mask(out->channel_mask &
4916 ~AUDIO_CHANNEL_HAPTIC_ALL);
4917
4918 if (force_haptic_path) {
4919 out->config.channels = 1;
4920 adev->haptics_config.channels = 1;
4921 } else {
4922 adev->haptics_config.channels =
4923 audio_channel_count_from_out_mask(out->channel_mask &
4924 AUDIO_CHANNEL_HAPTIC_ALL);
4925 }
4926 } else {
4927 out->config.channels =
4928 audio_channel_count_from_out_mask(out->channel_mask);
4929 }
4930
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004931 if (out->format != audio_format_from_pcm_format(out->config.format)) {
4932 out->config.format = pcm_format_from_audio_format(out->format);
4933 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004934 }
Kevin Rocard50eff892017-05-02 16:52:05 -07004935
4936 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
4937 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004938 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004939 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
4940 __func__, config->sample_rate, config->format, config->channel_mask);
4941 config->sample_rate = out->sample_rate;
4942 config->format = out->format;
4943 config->channel_mask = out->channel_mask;
4944 ret = -EINVAL;
4945 goto error_open;
4946 }
4947
Andy Hung6fcba9c2014-03-18 11:53:32 -07004948 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
4949 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004950
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004951 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004952 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004953 adev->primary_output = out;
4954 else {
4955 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004956 ret = -EEXIST;
4957 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004958 }
4959 }
4960
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004961 /* Check if this usecase is already existing */
4962 pthread_mutex_lock(&adev->lock);
4963 if (get_usecase_from_list(adev, out->usecase) != NULL) {
4964 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004965 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004966 ret = -EEXIST;
4967 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004968 }
4969 pthread_mutex_unlock(&adev->lock);
4970
4971 out->stream.common.get_sample_rate = out_get_sample_rate;
4972 out->stream.common.set_sample_rate = out_set_sample_rate;
4973 out->stream.common.get_buffer_size = out_get_buffer_size;
4974 out->stream.common.get_channels = out_get_channels;
4975 out->stream.common.get_format = out_get_format;
4976 out->stream.common.set_format = out_set_format;
4977 out->stream.common.standby = out_standby;
4978 out->stream.common.dump = out_dump;
4979 out->stream.common.set_parameters = out_set_parameters;
4980 out->stream.common.get_parameters = out_get_parameters;
4981 out->stream.common.add_audio_effect = out_add_audio_effect;
4982 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4983 out->stream.get_latency = out_get_latency;
4984 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004985#ifdef NO_AUDIO_OUT
4986 out->stream.write = out_write_for_no_output;
4987#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004988 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004989#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004990 out->stream.get_render_position = out_get_render_position;
4991 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004992 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004993
Eric Laurent0e46adf2016-12-16 12:49:24 -08004994 if (out->realtime)
4995 out->af_period_multiplier = af_period_multiplier;
4996 else
4997 out->af_period_multiplier = 1;
4998
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004999 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07005000 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005001 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005002
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005003 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005004 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005005 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
5006
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005007 config->format = out->stream.common.get_format(&out->stream.common);
5008 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
5009 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
5010
Kevin Rocarda325aa22018-04-03 09:15:52 -07005011 register_format(out->format, out->supported_formats);
5012 register_channel_mask(out->channel_mask, out->supported_channel_masks);
5013 register_sample_rate(out->sample_rate, out->supported_sample_rates);
5014
Andy Hunga452b0a2017-03-15 14:51:15 -07005015 out->error_log = error_log_create(
5016 ERROR_LOG_ENTRIES,
5017 1000000000 /* aggregate consecutive identical errors within one second in ns */);
5018
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005019 /*
5020 By locking output stream before registering, we allow the callback
5021 to update stream's state only after stream's initial state is set to
5022 adev state.
5023 */
5024 lock_output_stream(out);
5025 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
5026 pthread_mutex_lock(&adev->lock);
5027 out->card_status = adev->card_status;
5028 pthread_mutex_unlock(&adev->lock);
5029 pthread_mutex_unlock(&out->lock);
5030
vivek mehta4a824772017-06-08 19:05:49 -07005031 stream_app_type_cfg_init(&out->app_type_cfg);
5032
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005033 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005034
Eric Laurent994a6932013-07-17 11:51:42 -07005035 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005036 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005037
5038error_open:
5039 free(out);
5040 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07005041 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005042 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005043}
5044
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005045static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005046 struct audio_stream_out *stream)
5047{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005048 struct stream_out *out = (struct stream_out *)stream;
5049 struct audio_device *adev = out->dev;
5050
Eric Laurent994a6932013-07-17 11:51:42 -07005051 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005052
5053 // must deregister from sndmonitor first to prevent races
5054 // between the callback and close_stream
5055 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005056 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005057 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
5058 destroy_offload_callback_thread(out);
5059
5060 if (out->compr_config.codec != NULL)
5061 free(out->compr_config.codec);
5062 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07005063
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005064 out->a2dp_compress_mute = false;
5065
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07005066 if (adev->voice_tx_output == out)
5067 adev->voice_tx_output = NULL;
5068
Andy Hunga452b0a2017-03-15 14:51:15 -07005069 error_log_destroy(out->error_log);
5070 out->error_log = NULL;
5071
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005072 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005073 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005074 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005075 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07005076 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005077}
5078
5079static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
5080{
5081 struct audio_device *adev = (struct audio_device *)dev;
5082 struct str_parms *parms;
5083 char *str;
5084 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005085 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005086 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07005087 int status = 0;
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005088 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005089
Joe Onorato188b6222016-03-01 11:02:27 -08005090 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005091
5092 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005093
5094 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005095 status = voice_set_parameters(adev, parms);
5096 if (status != 0) {
5097 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005098 }
5099
5100 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
5101 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07005102 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005103 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5104 adev->bluetooth_nrec = true;
5105 else
5106 adev->bluetooth_nrec = false;
5107 }
5108
5109 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
5110 if (ret >= 0) {
5111 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5112 adev->screen_off = false;
5113 else
5114 adev->screen_off = true;
5115 }
5116
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005117 ret = str_parms_get_int(parms, "rotation", &val);
5118 if (ret >= 0) {
5119 bool reverse_speakers = false;
Eric Laurent5f4ca952018-10-19 17:33:43 -07005120 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005121 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005122 // FIXME: note that the code below assumes that the speakers are in the correct placement
5123 // relative to the user when the device is rotated 90deg from its default rotation. This
5124 // assumption is device-specific, not platform-specific like this code.
5125 case 270:
5126 reverse_speakers = true;
Eric Laurent5f4ca952018-10-19 17:33:43 -07005127 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005128 break;
5129 case 0:
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005130 case 180:
Eric Laurent5f4ca952018-10-19 17:33:43 -07005131 camera_rotation = CAMERA_ROTATION_PORTRAIT;
5132 break;
5133 case 90:
5134 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005135 break;
5136 default:
5137 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07005138 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005139 }
Eric Laurent03f09432014-03-25 18:09:11 -07005140 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07005141 // check and set swap
5142 // - check if orientation changed and speaker active
5143 // - set rotation and cache the rotation value
Eric Laurent5f4ca952018-10-19 17:33:43 -07005144 adev->camera_orientation =
5145 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
5146#ifndef MAXXAUDIO_QDSP_ENABLED
vivek mehtae59cfb22017-06-16 15:57:11 -07005147 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Eric Laurent5f4ca952018-10-19 17:33:43 -07005148#endif
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005149 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005150 }
5151
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005152 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
5153 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005154 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005155 }
5156
David Linee3fe402017-03-13 10:00:42 -07005157 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
5158 if (ret >= 0) {
5159 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07005160 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005161 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5162 if (ret >= 0) {
5163 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005164 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005165 }
Eric Laurent99dab492017-06-17 15:19:08 -07005166 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005167 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5168 if (ret >= 0) {
5169 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005170 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005171 }
5172 }
5173 }
5174
5175 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
5176 if (ret >= 0) {
5177 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07005178 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005179 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5180 if (ret >= 0) {
5181 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005182 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005183 }
Eric Laurent99dab492017-06-17 15:19:08 -07005184 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005185 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5186 if (ret >= 0) {
5187 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005188 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005189 }
5190 }
5191 }
5192
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08005193 audio_extn_hfp_set_parameters(adev, parms);
jasmine cha270b7762018-03-30 15:41:33 +08005194 audio_extn_ma_set_parameters(adev, parms);
5195
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005196 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
5197 if (status >= 0 && a2dp_reconfig) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005198 struct audio_usecase *usecase;
5199 struct listnode *node;
5200 list_for_each(node, &adev->usecase_list) {
5201 usecase = node_to_item(node, struct audio_usecase, list);
5202 if ((usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005203 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005204 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
5205
5206 pthread_mutex_unlock(&adev->lock);
5207 lock_output_stream(usecase->stream.out);
5208 pthread_mutex_lock(&adev->lock);
5209 audio_extn_a2dp_set_handoff_mode(true);
5210 // force device switch to reconfigure encoder
5211 select_devices(adev, usecase->id);
5212 audio_extn_a2dp_set_handoff_mode(false);
5213 pthread_mutex_unlock(&usecase->stream.out->lock);
5214 break;
5215 }
5216 }
5217 }
5218
Eric Laurent5f4ca952018-10-19 17:33:43 -07005219 //FIXME: to be replaced by proper video capture properties API
5220 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
5221 if (ret >= 0) {
5222 int camera_facing = CAMERA_FACING_BACK;
5223 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
5224 camera_facing = CAMERA_FACING_FRONT;
5225 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
5226 camera_facing = CAMERA_FACING_BACK;
5227 else {
5228 ALOGW("%s: invalid camera facing value: %s", __func__, value);
5229 goto done;
5230 }
5231 adev->camera_orientation =
5232 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
5233 struct audio_usecase *usecase;
5234 struct listnode *node;
5235 list_for_each(node, &adev->usecase_list) {
5236 usecase = node_to_item(node, struct audio_usecase, list);
5237 struct stream_in *in = usecase->stream.in;
5238 if (usecase->type == PCM_CAPTURE && in != NULL &&
5239 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
5240 select_devices(adev, in->usecase);
5241 }
5242 }
5243 }
5244
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005245done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005246 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005247 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07005248 ALOGV("%s: exit with code(%d)", __func__, status);
5249 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005250}
5251
5252static char* adev_get_parameters(const struct audio_hw_device *dev,
5253 const char *keys)
5254{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005255 struct audio_device *adev = (struct audio_device *)dev;
5256 struct str_parms *reply = str_parms_create();
5257 struct str_parms *query = str_parms_create_str(keys);
5258 char *str;
5259
5260 pthread_mutex_lock(&adev->lock);
5261
5262 voice_get_parameters(adev, query, reply);
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005263 audio_extn_a2dp_get_parameters(query, reply);
5264
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005265 str = str_parms_to_str(reply);
5266 str_parms_destroy(query);
5267 str_parms_destroy(reply);
5268
5269 pthread_mutex_unlock(&adev->lock);
5270 ALOGV("%s: exit: returns - %s", __func__, str);
5271 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005272}
5273
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005274static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005275{
5276 return 0;
5277}
5278
Haynes Mathew George5191a852013-09-11 14:19:36 -07005279static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
5280{
5281 int ret;
5282 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005283
Eric Laurent4cc4ce12014-09-10 13:21:01 -05005284 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
5285
Haynes Mathew George5191a852013-09-11 14:19:36 -07005286 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005287 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07005288 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005289
Haynes Mathew George5191a852013-09-11 14:19:36 -07005290 return ret;
5291}
5292
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005293static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005294{
5295 return -ENOSYS;
5296}
5297
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005298static int adev_get_master_volume(struct audio_hw_device *dev __unused,
5299 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005300{
5301 return -ENOSYS;
5302}
5303
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005304static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005305{
5306 return -ENOSYS;
5307}
5308
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005309static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005310{
5311 return -ENOSYS;
5312}
5313
5314static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
5315{
5316 struct audio_device *adev = (struct audio_device *)dev;
5317
5318 pthread_mutex_lock(&adev->lock);
5319 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07005320 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005321 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07005322 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
5323 voice_is_in_call(adev)) {
5324 voice_stop_call(adev);
5325 adev->current_call_output = NULL;
5326 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005327 }
5328 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05005329
5330 audio_extn_extspk_set_mode(adev->extspk, mode);
5331
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005332 return 0;
5333}
5334
5335static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
5336{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005337 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005338 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005339
Eric Laurent2bafff12016-03-17 12:17:23 -07005340 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005341 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005342 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
5343 ret = audio_extn_hfp_set_mic_mute(adev, state);
5344 } else {
5345 ret = voice_set_mic_mute(adev, state);
5346 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07005347 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00005348 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005349
5350 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005351}
5352
5353static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
5354{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005355 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005356 return 0;
5357}
5358
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005359static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005360 const struct audio_config *config)
5361{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07005362 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005363
Eric Laurent74b55762017-07-09 17:04:53 -07005364 /* Don't know if USB HIFI in this context so use true to be conservative */
5365 if (check_input_parameters(config->sample_rate, config->format, channel_count,
5366 true /*is_usb_hifi */) != 0)
5367 return 0;
5368
vivek mehtaa68fea62017-06-08 19:04:02 -07005369 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5370 config->sample_rate, config->format,
5371 channel_count,
5372 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005373}
5374
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005375static bool adev_input_allow_hifi_record(struct audio_device *adev,
5376 audio_devices_t devices,
5377 audio_input_flags_t flags,
5378 audio_source_t source) {
5379 const bool allowed = true;
5380
5381 if (!audio_is_usb_in_device(devices))
5382 return !allowed;
5383
5384 switch (flags) {
5385 case AUDIO_INPUT_FLAG_NONE:
5386 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
5387 break;
5388 default:
5389 return !allowed;
5390 }
5391
5392 switch (source) {
5393 case AUDIO_SOURCE_DEFAULT:
5394 case AUDIO_SOURCE_MIC:
5395 case AUDIO_SOURCE_UNPROCESSED:
5396 break;
5397 default:
5398 return !allowed;
5399 }
5400
5401 switch (adev->mode) {
5402 case 0:
5403 break;
5404 default:
5405 return !allowed;
5406 }
5407
5408 return allowed;
5409}
5410
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005411static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005412 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005413 audio_devices_t devices,
5414 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005415 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07005416 audio_input_flags_t flags,
5417 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05005418 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005419{
5420 struct audio_device *adev = (struct audio_device *)dev;
5421 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005422 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07005423 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005424 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005425 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005426 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
5427 devices,
5428 flags,
5429 source);
Andy Hung88ce1d92018-10-29 18:31:12 -07005430 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
5431 " sample_rate %u, channel_mask %#x, format %#x",
5432 __func__, flags, is_usb_dev, may_use_hifi_record,
5433 config->sample_rate, config->channel_mask, config->format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005434 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005435
Andy Hungd9653bd2017-08-01 19:31:39 -07005436 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
5437 return -ENOSYS;
5438 }
5439
Eric Laurent74b55762017-07-09 17:04:53 -07005440 if (!(is_usb_dev && may_use_hifi_record)) {
5441 if (config->sample_rate == 0)
5442 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
5443 if (config->channel_mask == AUDIO_CHANNEL_NONE)
5444 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5445 if (config->format == AUDIO_FORMAT_DEFAULT)
5446 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005447
Eric Laurent74b55762017-07-09 17:04:53 -07005448 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
5449
5450 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
5451 return -EINVAL;
5452 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005453
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005454 if (audio_extn_tfa_98xx_is_supported() &&
5455 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005456 return -EINVAL;
5457
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005458 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
5459
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005460 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005461 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005462
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005463 in->stream.common.get_sample_rate = in_get_sample_rate;
5464 in->stream.common.set_sample_rate = in_set_sample_rate;
5465 in->stream.common.get_buffer_size = in_get_buffer_size;
5466 in->stream.common.get_channels = in_get_channels;
5467 in->stream.common.get_format = in_get_format;
5468 in->stream.common.set_format = in_set_format;
5469 in->stream.common.standby = in_standby;
5470 in->stream.common.dump = in_dump;
5471 in->stream.common.set_parameters = in_set_parameters;
5472 in->stream.common.get_parameters = in_get_parameters;
5473 in->stream.common.add_audio_effect = in_add_audio_effect;
5474 in->stream.common.remove_audio_effect = in_remove_audio_effect;
5475 in->stream.set_gain = in_set_gain;
5476 in->stream.read = in_read;
5477 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08005478 in->stream.get_capture_position = in_get_capture_position;
jiabin8962a4d2018-03-19 18:21:24 -07005479 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLean57530d52018-12-17 08:24:21 -07005480 in->stream.set_microphone_direction = in_set_microphone_direction;
5481 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005482
5483 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005484 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005485 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005486 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005487 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005488 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005489
Andy Hung88ce1d92018-10-29 18:31:12 -07005490 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Arun Mirpuriba2749a2018-04-17 14:32:24 -07005491 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
5492 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
5493 /* Force channel config requested to mono if incall
5494 record is being requested for only uplink/downlink */
5495 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
5496 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5497 ret = -EINVAL;
5498 goto err_open;
5499 }
5500 }
5501
Haynes Mathew George569b7482017-05-08 14:44:27 -07005502 if (is_usb_dev && may_use_hifi_record) {
5503 /* HiFi record selects an appropriate format, channel, rate combo
5504 depending on sink capabilities*/
5505 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
5506 &config->format,
5507 &in->supported_formats[0],
5508 MAX_SUPPORTED_FORMATS,
5509 &config->channel_mask,
5510 &in->supported_channel_masks[0],
5511 MAX_SUPPORTED_CHANNEL_MASKS,
5512 &config->sample_rate,
5513 &in->supported_sample_rates[0],
5514 MAX_SUPPORTED_SAMPLE_RATES);
5515 if (ret != 0) {
5516 ret = -EINVAL;
5517 goto err_open;
5518 }
Eric Laurent74b55762017-07-09 17:04:53 -07005519 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005520 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07005521 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07005522 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
5523 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
5524 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5525 bool ret_error = false;
5526 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5527 from HAL is 8_24
5528 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5529 8_24 return error indicating supported format is 8_24
5530 *> In case of any other source requesting 24 bit or float return error
5531 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07005532
vivek mehta57ff9b52016-04-28 14:13:08 -07005533 on error flinger will retry with supported format passed
5534 */
juyuchenbe5c67e2018-08-29 17:19:20 +08005535 if (!is_supported_24bits_audiosource(source)) {
vivek mehta57ff9b52016-04-28 14:13:08 -07005536 config->format = AUDIO_FORMAT_PCM_16_BIT;
5537 ret_error = true;
5538 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
5539 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
5540 ret_error = true;
5541 }
5542
5543 if (ret_error) {
5544 ret = -EINVAL;
5545 goto err_open;
5546 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005547 }
5548
vivek mehta57ff9b52016-04-28 14:13:08 -07005549 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07005550 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07005551
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005552 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005553 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
5554 if (config->sample_rate == 0)
5555 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5556 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5557 config->sample_rate != 8000) {
5558 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5559 ret = -EINVAL;
5560 goto err_open;
5561 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005562
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005563 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5564 config->format = AUDIO_FORMAT_PCM_16_BIT;
5565 ret = -EINVAL;
5566 goto err_open;
5567 }
5568
5569 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5570 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07005571 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005572 } else if (is_usb_dev && may_use_hifi_record) {
5573 in->usecase = USECASE_AUDIO_RECORD_HIFI;
5574 in->config = pcm_config_audio_capture;
5575 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005576 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5577 config->sample_rate,
5578 config->format,
5579 channel_count,
5580 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005581 in->config.period_size = buffer_size / frame_size;
5582 in->config.rate = config->sample_rate;
5583 in->af_period_multiplier = 1;
5584 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005585 } else {
5586 in->usecase = USECASE_AUDIO_RECORD;
5587 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08005588 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005589 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07005590#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005591 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07005592#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08005593 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005594 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08005595 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005596 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005597 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5598 config->sample_rate,
5599 config->format,
5600 channel_count,
5601 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005602 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005603 in->config.rate = config->sample_rate;
5604 in->af_period_multiplier = 1;
5605 } else {
5606 // period size is left untouched for rt mode playback
5607 in->config = pcm_config_audio_capture_rt;
5608 in->af_period_multiplier = af_period_multiplier;
5609 }
5610 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
5611 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005612 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08005613 in->usecase = USECASE_AUDIO_RECORD_MMAP;
5614 in->config = pcm_config_mmap_capture;
5615 in->stream.start = in_start;
5616 in->stream.stop = in_stop;
5617 in->stream.create_mmap_buffer = in_create_mmap_buffer;
5618 in->stream.get_mmap_position = in_get_mmap_position;
5619 in->af_period_multiplier = 1;
5620 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07005621 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07005622 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07005623 (config->sample_rate == 8000 ||
5624 config->sample_rate == 16000 ||
5625 config->sample_rate == 32000 ||
5626 config->sample_rate == 48000) &&
5627 channel_count == 1) {
5628 in->usecase = USECASE_AUDIO_RECORD_VOIP;
5629 in->config = pcm_config_audio_capture;
5630 frame_size = audio_stream_in_frame_size(&in->stream);
5631 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
5632 config->sample_rate,
5633 config->format,
5634 channel_count, false /*is_low_latency*/);
5635 in->config.period_size = buffer_size / frame_size;
5636 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
5637 in->config.rate = config->sample_rate;
5638 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005639 } else {
5640 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005641 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005642 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5643 config->sample_rate,
5644 config->format,
5645 channel_count,
5646 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005647 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005648 in->config.rate = config->sample_rate;
5649 in->af_period_multiplier = 1;
5650 }
5651 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
5652 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005653 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08005654
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005655 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07005656 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005657
Kevin Rocarda325aa22018-04-03 09:15:52 -07005658
5659 register_format(in->format, in->supported_formats);
5660 register_channel_mask(in->channel_mask, in->supported_channel_masks);
5661 register_sample_rate(in->sample_rate, in->supported_sample_rates);
5662
Andy Hungd13f0d32017-06-12 13:58:37 -07005663 in->error_log = error_log_create(
5664 ERROR_LOG_ENTRIES,
5665 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
5666
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005667 /* This stream could be for sound trigger lab,
5668 get sound trigger pcm if present */
5669 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005670
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005671 lock_input_stream(in);
5672 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5673 pthread_mutex_lock(&adev->lock);
5674 in->card_status = adev->card_status;
5675 pthread_mutex_unlock(&adev->lock);
5676 pthread_mutex_unlock(&in->lock);
5677
vivek mehta4a824772017-06-08 19:05:49 -07005678 stream_app_type_cfg_init(&in->app_type_cfg);
5679
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005680 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005681 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005682 return 0;
5683
5684err_open:
5685 free(in);
5686 *stream_in = NULL;
5687 return ret;
5688}
5689
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005690static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005691 struct audio_stream_in *stream)
5692{
Andy Hungd13f0d32017-06-12 13:58:37 -07005693 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005694 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005695
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005696 // must deregister from sndmonitor first to prevent races
5697 // between the callback and close_stream
5698 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005699 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07005700
5701 error_log_destroy(in->error_log);
5702 in->error_log = NULL;
5703
Andy Hung0dbb52b2017-08-09 13:51:38 -07005704 pthread_mutex_destroy(&in->pre_lock);
5705 pthread_mutex_destroy(&in->lock);
5706
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005707 free(stream);
5708
5709 return;
5710}
5711
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005712static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005713{
5714 return 0;
5715}
5716
Andy Hung31aca912014-03-20 17:14:59 -07005717/* verifies input and output devices and their capabilities.
5718 *
5719 * This verification is required when enabling extended bit-depth or
5720 * sampling rates, as not all qcom products support it.
5721 *
5722 * Suitable for calling only on initialization such as adev_open().
5723 * It fills the audio_device use_case_table[] array.
5724 *
5725 * Has a side-effect that it needs to configure audio routing / devices
5726 * in order to power up the devices and read the device parameters.
5727 * It does not acquire any hw device lock. Should restore the devices
5728 * back to "normal state" upon completion.
5729 */
5730static int adev_verify_devices(struct audio_device *adev)
5731{
5732 /* enumeration is a bit difficult because one really wants to pull
5733 * the use_case, device id, etc from the hidden pcm_device_table[].
5734 * In this case there are the following use cases and device ids.
5735 *
5736 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
5737 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005738 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07005739 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
5740 * [USECASE_AUDIO_RECORD] = {0, 0},
5741 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
5742 * [USECASE_VOICE_CALL] = {2, 2},
5743 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005744 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07005745 * USECASE_VOICE_CALL omitted, but possible for either input or output.
5746 */
5747
5748 /* should be the usecases enabled in adev_open_input_stream() */
5749 static const int test_in_usecases[] = {
5750 USECASE_AUDIO_RECORD,
5751 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
5752 };
5753 /* should be the usecases enabled in adev_open_output_stream()*/
5754 static const int test_out_usecases[] = {
5755 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
5756 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
5757 };
5758 static const usecase_type_t usecase_type_by_dir[] = {
5759 PCM_PLAYBACK,
5760 PCM_CAPTURE,
5761 };
5762 static const unsigned flags_by_dir[] = {
5763 PCM_OUT,
5764 PCM_IN,
5765 };
5766
5767 size_t i;
5768 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005769 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07005770 char info[512]; /* for possible debug info */
5771
5772 for (dir = 0; dir < 2; ++dir) {
5773 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
5774 const unsigned flags_dir = flags_by_dir[dir];
5775 const size_t testsize =
5776 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
5777 const int *testcases =
5778 dir ? test_in_usecases : test_out_usecases;
5779 const audio_devices_t audio_device =
5780 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
5781
5782 for (i = 0; i < testsize; ++i) {
5783 const audio_usecase_t audio_usecase = testcases[i];
5784 int device_id;
5785 snd_device_t snd_device;
5786 struct pcm_params **pparams;
5787 struct stream_out out;
5788 struct stream_in in;
5789 struct audio_usecase uc_info;
5790 int retval;
5791
5792 pparams = &adev->use_case_table[audio_usecase];
5793 pcm_params_free(*pparams); /* can accept null input */
5794 *pparams = NULL;
5795
5796 /* find the device ID for the use case (signed, for error) */
5797 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
5798 if (device_id < 0)
5799 continue;
5800
5801 /* prepare structures for device probing */
5802 memset(&uc_info, 0, sizeof(uc_info));
5803 uc_info.id = audio_usecase;
5804 uc_info.type = usecase_type;
5805 if (dir) {
Andy Hung31aca912014-03-20 17:14:59 -07005806 memset(&in, 0, sizeof(in));
5807 in.device = audio_device;
5808 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
5809 uc_info.stream.in = &in;
Andy Hung31aca912014-03-20 17:14:59 -07005810 }
5811 memset(&out, 0, sizeof(out));
5812 out.devices = audio_device; /* only field needed in select_devices */
5813 uc_info.stream.out = &out;
5814 uc_info.devices = audio_device;
5815 uc_info.in_snd_device = SND_DEVICE_NONE;
5816 uc_info.out_snd_device = SND_DEVICE_NONE;
5817 list_add_tail(&adev->usecase_list, &uc_info.list);
5818
5819 /* select device - similar to start_(in/out)put_stream() */
5820 retval = select_devices(adev, audio_usecase);
5821 if (retval >= 0) {
5822 *pparams = pcm_params_get(card_id, device_id, flags_dir);
5823#if LOG_NDEBUG == 0
5824 if (*pparams) {
5825 ALOGV("%s: (%s) card %d device %d", __func__,
5826 dir ? "input" : "output", card_id, device_id);
5827 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07005828 } else {
5829 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
5830 }
5831#endif
5832 }
5833
5834 /* deselect device - similar to stop_(in/out)put_stream() */
5835 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07005836 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07005837 /* 2. Disable the rx device */
5838 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07005839 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07005840 list_remove(&uc_info.list);
5841 }
5842 }
Andy Hung31aca912014-03-20 17:14:59 -07005843 return 0;
5844}
5845
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005846static int adev_close(hw_device_t *device)
5847{
Andy Hung31aca912014-03-20 17:14:59 -07005848 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005849 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005850
5851 if (!adev)
5852 return 0;
5853
5854 pthread_mutex_lock(&adev_init_lock);
5855
5856 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005857 audio_extn_snd_mon_unregister_listener(adev);
5858 audio_extn_tfa_98xx_deinit();
jasmine cha270b7762018-03-30 15:41:33 +08005859 audio_extn_ma_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005860 audio_route_free(adev->audio_route);
5861 free(adev->snd_dev_ref_cnt);
5862 platform_deinit(adev->platform);
5863 audio_extn_extspk_deinit(adev->extspk);
5864 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005865 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005866 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
5867 pcm_params_free(adev->use_case_table[i]);
5868 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005869 if (adev->adm_deinit)
5870 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005871 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005872 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07005873 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07005874
5875 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005876
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005877 return 0;
5878}
5879
Glenn Kasten4f993392014-05-14 07:30:48 -07005880/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5881 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5882 * just that it _might_ work.
5883 */
5884static int period_size_is_plausible_for_low_latency(int period_size)
5885{
5886 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005887 case 48:
5888 case 96:
5889 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07005890 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005891 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07005892 case 240:
5893 case 320:
5894 case 480:
5895 return 1;
5896 default:
5897 return 0;
5898 }
5899}
5900
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005901static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
5902{
5903 int card;
5904 card_status_t status;
5905
5906 if (!parms)
5907 return;
5908
5909 if (parse_snd_card_status(parms, &card, &status) < 0)
5910 return;
5911
5912 pthread_mutex_lock(&adev->lock);
5913 bool valid_cb = (card == adev->snd_card);
5914 if (valid_cb) {
5915 if (adev->card_status != status) {
5916 adev->card_status = status;
5917 platform_snd_card_update(adev->platform, status);
5918 }
5919 }
5920 pthread_mutex_unlock(&adev->lock);
5921 return;
5922}
5923
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005924/* out and adev lock held */
5925static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
5926{
5927 struct audio_usecase *uc_info;
5928 float left_p;
5929 float right_p;
5930 audio_devices_t devices;
5931
5932 uc_info = get_usecase_from_list(adev, out->usecase);
5933 if (uc_info == NULL) {
5934 ALOGE("%s: Could not find the usecase (%d) in the list",
5935 __func__, out->usecase);
5936 return -EINVAL;
5937 }
5938
5939 ALOGD("%s: enter: usecase(%d: %s)", __func__,
5940 out->usecase, use_case_table[out->usecase]);
5941
5942 if (restore) {
5943 // restore A2DP device for active usecases and unmute if required
5944 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
5945 !is_a2dp_device(uc_info->out_snd_device)) {
5946 ALOGD("%s: restoring A2DP and unmuting stream", __func__);
5947 select_devices(adev, uc_info->id);
5948 pthread_mutex_lock(&out->compr_mute_lock);
5949 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5950 (out->a2dp_compress_mute)) {
5951 out->a2dp_compress_mute = false;
5952 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5953 }
5954 pthread_mutex_unlock(&out->compr_mute_lock);
5955 }
5956 } else {
5957 // mute compress stream if suspended
5958 pthread_mutex_lock(&out->compr_mute_lock);
5959 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5960 (!out->a2dp_compress_mute)) {
5961 if (!out->standby) {
5962 ALOGD("%s: selecting speaker and muting stream", __func__);
5963 devices = out->devices;
5964 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
5965 left_p = out->volume_l;
5966 right_p = out->volume_r;
5967 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5968 compress_pause(out->compr);
5969 set_compr_volume(&out->stream, 0.0f, 0.0f);
5970 out->a2dp_compress_mute = true;
5971 select_devices(adev, out->usecase);
5972 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5973 compress_resume(out->compr);
5974 out->devices = devices;
5975 out->volume_l = left_p;
5976 out->volume_r = right_p;
5977 }
5978 }
5979 pthread_mutex_unlock(&out->compr_mute_lock);
5980 }
5981 ALOGV("%s: exit", __func__);
5982 return 0;
5983}
5984
5985int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
5986{
5987 int ret = 0;
5988
5989 lock_output_stream(out);
5990 pthread_mutex_lock(&adev->lock);
5991
5992 ret = check_a2dp_restore_l(adev, out, restore);
5993
5994 pthread_mutex_unlock(&adev->lock);
5995 pthread_mutex_unlock(&out->lock);
5996 return ret;
5997}
5998
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005999static int adev_open(const hw_module_t *module, const char *name,
6000 hw_device_t **device)
6001{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07006002 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006003
Eric Laurent2bafff12016-03-17 12:17:23 -07006004 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006005 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006006 pthread_mutex_lock(&adev_init_lock);
6007 if (audio_device_ref_count != 0) {
6008 *device = &adev->device.common;
6009 audio_device_ref_count++;
6010 ALOGV("%s: returning existing instance of adev", __func__);
6011 ALOGV("%s: exit", __func__);
6012 pthread_mutex_unlock(&adev_init_lock);
6013 return 0;
6014 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006015 adev = calloc(1, sizeof(struct audio_device));
6016
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07006017 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
6018
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006019 adev->device.common.tag = HARDWARE_DEVICE_TAG;
6020 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
6021 adev->device.common.module = (struct hw_module_t *)module;
6022 adev->device.common.close = adev_close;
6023
6024 adev->device.init_check = adev_init_check;
6025 adev->device.set_voice_volume = adev_set_voice_volume;
6026 adev->device.set_master_volume = adev_set_master_volume;
6027 adev->device.get_master_volume = adev_get_master_volume;
6028 adev->device.set_master_mute = adev_set_master_mute;
6029 adev->device.get_master_mute = adev_get_master_mute;
6030 adev->device.set_mode = adev_set_mode;
6031 adev->device.set_mic_mute = adev_set_mic_mute;
6032 adev->device.get_mic_mute = adev_get_mic_mute;
6033 adev->device.set_parameters = adev_set_parameters;
6034 adev->device.get_parameters = adev_get_parameters;
6035 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
6036 adev->device.open_output_stream = adev_open_output_stream;
6037 adev->device.close_output_stream = adev_close_output_stream;
6038 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08006039
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006040 adev->device.close_input_stream = adev_close_input_stream;
6041 adev->device.dump = adev_dump;
jiabin8962a4d2018-03-19 18:21:24 -07006042 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006043
6044 /* Set the default route before the PCM stream is opened */
6045 pthread_mutex_lock(&adev->lock);
6046 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006047 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006048 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08006049 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07006050 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07006051 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07006052 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08006053 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006054 pthread_mutex_unlock(&adev->lock);
6055
6056 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07006057 adev->platform = platform_init(adev);
6058 if (!adev->platform) {
6059 free(adev->snd_dev_ref_cnt);
6060 free(adev);
6061 ALOGE("%s: Failed to init platform data, aborting.", __func__);
6062 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006063 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07006064 return -EINVAL;
6065 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05006066 adev->extspk = audio_extn_extspk_init(adev);
6067
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006068 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
6069 if (adev->visualizer_lib == NULL) {
6070 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
6071 } else {
6072 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
6073 adev->visualizer_start_output =
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07006074 (int (*)(audio_io_handle_t, int, int, int))dlsym(adev->visualizer_lib,
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006075 "visualizer_hal_start_output");
6076 adev->visualizer_stop_output =
6077 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
6078 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07006079 }
6080
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006081 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
6082 if (adev->offload_effects_lib == NULL) {
6083 ALOGW("%s: DLOPEN failed for %s", __func__,
6084 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6085 } else {
6086 ALOGV("%s: DLOPEN successful for %s", __func__,
6087 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6088 adev->offload_effects_start_output =
6089 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
6090 "offload_effects_bundle_hal_start_output");
6091 adev->offload_effects_stop_output =
6092 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
6093 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07006094 }
6095
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006096 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
6097 if (adev->adm_lib == NULL) {
6098 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
6099 } else {
6100 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
6101 adev->adm_init = (adm_init_t)
6102 dlsym(adev->adm_lib, "adm_init");
6103 adev->adm_deinit = (adm_deinit_t)
6104 dlsym(adev->adm_lib, "adm_deinit");
6105 adev->adm_register_input_stream = (adm_register_input_stream_t)
6106 dlsym(adev->adm_lib, "adm_register_input_stream");
6107 adev->adm_register_output_stream = (adm_register_output_stream_t)
6108 dlsym(adev->adm_lib, "adm_register_output_stream");
6109 adev->adm_deregister_stream = (adm_deregister_stream_t)
6110 dlsym(adev->adm_lib, "adm_deregister_stream");
6111 adev->adm_request_focus = (adm_request_focus_t)
6112 dlsym(adev->adm_lib, "adm_request_focus");
6113 adev->adm_abandon_focus = (adm_abandon_focus_t)
6114 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08006115 adev->adm_set_config = (adm_set_config_t)
6116 dlsym(adev->adm_lib, "adm_set_config");
6117 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
6118 dlsym(adev->adm_lib, "adm_request_focus_v2");
6119 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
6120 dlsym(adev->adm_lib, "adm_is_noirq_avail");
6121 adev->adm_on_routing_change = (adm_on_routing_change_t)
6122 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006123 }
6124
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07006125 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05006126 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07006127
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006128 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006129
Andy Hung31aca912014-03-20 17:14:59 -07006130 if (k_enable_extended_precision)
6131 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006132
Glenn Kasten4f993392014-05-14 07:30:48 -07006133 char value[PROPERTY_VALUE_MAX];
6134 int trial;
6135 if (property_get("audio_hal.period_size", value, NULL) > 0) {
6136 trial = atoi(value);
6137 if (period_size_is_plausible_for_low_latency(trial)) {
6138 pcm_config_low_latency.period_size = trial;
6139 pcm_config_low_latency.start_threshold = trial / 4;
6140 pcm_config_low_latency.avail_min = trial / 4;
6141 configured_low_latency_capture_period_size = trial;
6142 }
6143 }
6144 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
6145 trial = atoi(value);
6146 if (period_size_is_plausible_for_low_latency(trial)) {
6147 configured_low_latency_capture_period_size = trial;
6148 }
6149 }
6150
Vignesh Kulothunganb6f0a9c2018-03-22 13:50:22 -07006151 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
6152
Eric Laurent5f4ca952018-10-19 17:33:43 -07006153 adev->camera_orientation = CAMERA_DEFAULT;
6154
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08006155 // commented as full set of app type cfg is sent from platform
6156 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07006157 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08006158
6159 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
6160 af_period_multiplier = atoi(value);
6161 if (af_period_multiplier < 0) {
6162 af_period_multiplier = 2;
6163 } else if (af_period_multiplier > 4) {
6164 af_period_multiplier = 4;
6165 }
6166 ALOGV("new period_multiplier = %d", af_period_multiplier);
6167 }
6168
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08006169 audio_extn_tfa_98xx_init(adev);
jasmine cha270b7762018-03-30 15:41:33 +08006170 audio_extn_ma_init(adev->platform);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08006171
vivek mehta1a9b7c02015-06-25 11:49:38 -07006172 pthread_mutex_unlock(&adev_init_lock);
6173
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006174 if (adev->adm_init)
6175 adev->adm_data = adev->adm_init();
6176
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07006177 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07006178 audio_extn_snd_mon_init();
6179 pthread_mutex_lock(&adev->lock);
6180 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
6181 adev->card_status = CARD_STATUS_ONLINE;
6182 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07006183 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07006184
Eric Laurent2bafff12016-03-17 12:17:23 -07006185 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006186 return 0;
6187}
6188
6189static struct hw_module_methods_t hal_module_methods = {
6190 .open = adev_open,
6191};
6192
6193struct audio_module HAL_MODULE_INFO_SYM = {
6194 .common = {
6195 .tag = HARDWARE_MODULE_TAG,
6196 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
6197 .hal_api_version = HARDWARE_HAL_API_VERSION,
6198 .id = AUDIO_HARDWARE_MODULE_ID,
6199 .name = "QCOM Audio HAL",
6200 .author = "Code Aurora Forum",
6201 .methods = &hal_module_methods,
6202 },
6203};