blob: 98d67c4788aa7b70adc3388974d1ba171bc5909b [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>
43#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080044
Eric Laurentb23d5282013-05-14 15:27:20 -070045#include <hardware/audio_effect.h>
Andy Hung31aca912014-03-20 17:14:59 -070046#include <hardware/audio_alsaops.h>
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
Haynes Mathew George03c40102016-01-29 17:57:48 -0800134static int af_period_multiplier = 4;
135struct pcm_config pcm_config_rt = {
136 .channels = DEFAULT_CHANNEL_COUNT,
137 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
138 .period_size = ULL_PERIOD_SIZE, //1 ms
139 .period_count = 512, //=> buffer size is 512ms
140 .format = PCM_FORMAT_S16_LE,
141 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
142 .stop_threshold = INT_MAX,
143 .silence_threshold = 0,
144 .silence_size = 0,
145 .avail_min = ULL_PERIOD_SIZE, //1 ms
146};
147
Eric Laurentb23d5282013-05-14 15:27:20 -0700148struct pcm_config pcm_config_hdmi_multi = {
149 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
150 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
151 .period_size = HDMI_MULTI_PERIOD_SIZE,
152 .period_count = HDMI_MULTI_PERIOD_COUNT,
153 .format = PCM_FORMAT_S16_LE,
154 .start_threshold = 0,
155 .stop_threshold = INT_MAX,
156 .avail_min = 0,
157};
158
Eric Laurent0e46adf2016-12-16 12:49:24 -0800159struct pcm_config pcm_config_mmap_playback = {
160 .channels = DEFAULT_CHANNEL_COUNT,
161 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
162 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800163 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800164 .format = PCM_FORMAT_S16_LE,
165 .start_threshold = MMAP_PERIOD_SIZE*8,
166 .stop_threshold = INT32_MAX,
167 .silence_threshold = 0,
168 .silence_size = 0,
169 .avail_min = MMAP_PERIOD_SIZE, //1 ms
170};
171
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800172struct pcm_config pcm_config_hifi = {
173 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
174 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
175 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
176 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
177 .format = PCM_FORMAT_S24_3LE,
178 .start_threshold = 0,
179 .stop_threshold = INT_MAX,
180 .avail_min = 0,
181};
182
Eric Laurentb23d5282013-05-14 15:27:20 -0700183struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700184 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700185 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
186 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700187 .stop_threshold = INT_MAX,
188 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700189};
190
Haynes Mathew George03c40102016-01-29 17:57:48 -0800191struct pcm_config pcm_config_audio_capture_rt = {
192 .channels = DEFAULT_CHANNEL_COUNT,
193 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
194 .period_size = ULL_PERIOD_SIZE,
195 .period_count = 512,
196 .format = PCM_FORMAT_S16_LE,
197 .start_threshold = 0,
198 .stop_threshold = INT_MAX,
199 .silence_threshold = 0,
200 .silence_size = 0,
201 .avail_min = ULL_PERIOD_SIZE, //1 ms
202};
203
Eric Laurent0e46adf2016-12-16 12:49:24 -0800204struct pcm_config pcm_config_mmap_capture = {
205 .channels = DEFAULT_CHANNEL_COUNT,
206 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
207 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800208 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800209 .format = PCM_FORMAT_S16_LE,
210 .start_threshold = 0,
211 .stop_threshold = INT_MAX,
212 .silence_threshold = 0,
213 .silence_size = 0,
214 .avail_min = MMAP_PERIOD_SIZE, //1 ms
215};
216
vivek mehtaa68fea62017-06-08 19:04:02 -0700217struct pcm_config pcm_config_voip = {
218 .channels = 1,
219 .period_count = 2,
220 .format = PCM_FORMAT_S16_LE,
221 .stop_threshold = INT_MAX,
222 .avail_min = 0,
223};
224
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700225#define AFE_PROXY_CHANNEL_COUNT 2
226#define AFE_PROXY_SAMPLING_RATE 48000
227
228#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
229#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
230
231struct pcm_config pcm_config_afe_proxy_playback = {
232 .channels = AFE_PROXY_CHANNEL_COUNT,
233 .rate = AFE_PROXY_SAMPLING_RATE,
234 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
235 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
236 .format = PCM_FORMAT_S16_LE,
237 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
238 .stop_threshold = INT_MAX,
239 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
240};
241
242#define AFE_PROXY_RECORD_PERIOD_SIZE 768
243#define AFE_PROXY_RECORD_PERIOD_COUNT 4
244
245struct pcm_config pcm_config_afe_proxy_record = {
246 .channels = AFE_PROXY_CHANNEL_COUNT,
247 .rate = AFE_PROXY_SAMPLING_RATE,
248 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
249 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
250 .format = PCM_FORMAT_S16_LE,
251 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
jiabin5d0261e2018-05-25 09:43:59 -0700252 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700253 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
254};
255
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700256const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700257 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
258 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800259 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700260 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700261 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700262 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800263 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700264
Eric Laurentb23d5282013-05-14 15:27:20 -0700265 [USECASE_AUDIO_RECORD] = "audio-record",
266 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800267 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George569b7482017-05-08 14:44:27 -0700268 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700269
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800270 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
271 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700272
Eric Laurentb23d5282013-05-14 15:27:20 -0700273 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700274 [USECASE_VOICE2_CALL] = "voice2-call",
275 [USECASE_VOLTE_CALL] = "volte-call",
276 [USECASE_QCHAT_CALL] = "qchat-call",
277 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800278 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
279 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700280
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700281 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
282 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
283
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700284 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
285 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
vivek mehta781065c2017-04-04 12:55:01 -0700286
287 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
288 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
289 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
290
vivek mehtaa68fea62017-06-08 19:04:02 -0700291 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
292 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Nadav Bar3d72cfc2018-01-07 12:19:24 +0200293
294 [USECASE_INCALL_MUSIC_UPLINK] = "incall-music-uplink",
Aniket Kumar Lata99546312018-03-19 21:38:38 -0700295
296 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700297};
298
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800299
300#define STRING_TO_ENUM(string) { #string, string }
301
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800302struct string_to_enum {
303 const char *name;
304 uint32_t value;
305};
306
Haynes Mathew George569b7482017-05-08 14:44:27 -0700307static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800308 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
309 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
310 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Eric Laurent74b55762017-07-09 17:04:53 -0700311 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
Haynes Mathew George569b7482017-05-08 14:44:27 -0700312 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
Eric Laurent74b55762017-07-09 17:04:53 -0700313 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
314 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
315 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
316 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
317 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
318 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
319 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
320 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
321 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800322};
323
Haynes Mathew George5191a852013-09-11 14:19:36 -0700324static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700325static struct audio_device *adev = NULL;
Andy Hung9e737de2017-05-22 10:51:22 -0700326static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700327static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700328//cache last MBDRC cal step level
329static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700330
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800331static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
332static int set_compr_volume(struct audio_stream_out *stream, float left, float right);
333
Haynes Mathew George03c40102016-01-29 17:57:48 -0800334static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
335 int flags __unused)
336{
337 int dir = 0;
338 switch (uc_id) {
339 case USECASE_AUDIO_RECORD_LOW_LATENCY:
340 dir = 1;
341 case USECASE_AUDIO_PLAYBACK_ULL:
342 break;
343 default:
344 return false;
345 }
346
347 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
348 PCM_PLAYBACK : PCM_CAPTURE);
349 if (adev->adm_is_noirq_avail)
350 return adev->adm_is_noirq_avail(adev->adm_data,
351 adev->snd_card, dev_id, dir);
352 return false;
353}
354
355static void register_out_stream(struct stream_out *out)
356{
357 struct audio_device *adev = out->dev;
358 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
359 return;
360
361 if (!adev->adm_register_output_stream)
362 return;
363
364 adev->adm_register_output_stream(adev->adm_data,
365 out->handle,
366 out->flags);
367
368 if (!adev->adm_set_config)
369 return;
370
371 if (out->realtime) {
372 adev->adm_set_config(adev->adm_data,
373 out->handle,
374 out->pcm, &out->config);
375 }
376}
377
378static void register_in_stream(struct stream_in *in)
379{
380 struct audio_device *adev = in->dev;
381 if (!adev->adm_register_input_stream)
382 return;
383
384 adev->adm_register_input_stream(adev->adm_data,
385 in->capture_handle,
386 in->flags);
387
388 if (!adev->adm_set_config)
389 return;
390
391 if (in->realtime) {
392 adev->adm_set_config(adev->adm_data,
393 in->capture_handle,
394 in->pcm,
395 &in->config);
396 }
397}
398
399static void request_out_focus(struct stream_out *out, long ns)
400{
401 struct audio_device *adev = out->dev;
402
Haynes Mathew George03c40102016-01-29 17:57:48 -0800403 if (adev->adm_request_focus_v2) {
404 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
405 } else if (adev->adm_request_focus) {
406 adev->adm_request_focus(adev->adm_data, out->handle);
407 }
408}
409
410static void request_in_focus(struct stream_in *in, long ns)
411{
412 struct audio_device *adev = in->dev;
413
Haynes Mathew George03c40102016-01-29 17:57:48 -0800414 if (adev->adm_request_focus_v2) {
415 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
416 } else if (adev->adm_request_focus) {
417 adev->adm_request_focus(adev->adm_data, in->capture_handle);
418 }
419}
420
421static void release_out_focus(struct stream_out *out, long ns __unused)
422{
423 struct audio_device *adev = out->dev;
424
425 if (adev->adm_abandon_focus)
426 adev->adm_abandon_focus(adev->adm_data, out->handle);
427}
428
429static void release_in_focus(struct stream_in *in, long ns __unused)
430{
431 struct audio_device *adev = in->dev;
432 if (adev->adm_abandon_focus)
433 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
434}
435
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700436static int parse_snd_card_status(struct str_parms * parms, int * card,
437 card_status_t * status)
438{
439 char value[32]={0};
440 char state[32]={0};
441
442 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
443
444 if (ret < 0)
445 return -1;
446
447 // sscanf should be okay as value is of max length 32.
448 // same as sizeof state.
449 if (sscanf(value, "%d,%s", card, state) < 2)
450 return -1;
451
452 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
453 CARD_STATUS_OFFLINE;
454 return 0;
455}
456
vivek mehta40125092017-08-21 18:48:51 -0700457// always call with adev lock held
458void send_gain_dep_calibration_l() {
459 if (last_known_cal_step >= 0)
460 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
461}
462
vivek mehta1a9b7c02015-06-25 11:49:38 -0700463__attribute__ ((visibility ("default")))
464bool audio_hw_send_gain_dep_calibration(int level) {
465 bool ret_val = false;
466 ALOGV("%s: enter ... ", __func__);
467
468 pthread_mutex_lock(&adev_init_lock);
469
470 if (adev != NULL && adev->platform != NULL) {
471 pthread_mutex_lock(&adev->lock);
vivek mehta40125092017-08-21 18:48:51 -0700472 last_known_cal_step = level;
473 send_gain_dep_calibration_l();
vivek mehta1a9b7c02015-06-25 11:49:38 -0700474 pthread_mutex_unlock(&adev->lock);
475 } else {
476 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
477 }
478
479 pthread_mutex_unlock(&adev_init_lock);
480
481 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
482 return ret_val;
483}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700484
jasmine cha270b7762018-03-30 15:41:33 +0800485#ifdef MAXXAUDIO_QDSP_ENABLED
486bool audio_hw_send_ma_parameter(int stream_type, float vol, bool active)
487{
488 bool ret = false;
489 ALOGV("%s: enter ...", __func__);
490
491 pthread_mutex_lock(&adev_init_lock);
492
493 if (adev != NULL && adev->platform != NULL) {
494 pthread_mutex_lock(&adev->lock);
495 ret = audio_extn_ma_set_state(adev, stream_type, vol, active);
496 pthread_mutex_unlock(&adev->lock);
497 }
498
499 pthread_mutex_unlock(&adev_init_lock);
500
501 ALOGV("%s: exit with ret %d", __func__, ret);
502 return ret;
503}
504#else
505#define audio_hw_send_ma_parameter(stream_type, vol, active) (0)
506#endif
507
vivek mehtaa8d7c922016-05-25 14:40:44 -0700508__attribute__ ((visibility ("default")))
509int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
510 int table_size) {
511 int ret_val = 0;
512 ALOGV("%s: enter ... ", __func__);
513
514 pthread_mutex_lock(&adev_init_lock);
515 if (adev == NULL) {
516 ALOGW("%s: adev is NULL .... ", __func__);
517 goto done;
518 }
519
520 pthread_mutex_lock(&adev->lock);
521 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
522 pthread_mutex_unlock(&adev->lock);
523done:
524 pthread_mutex_unlock(&adev_init_lock);
525 ALOGV("%s: exit ... ", __func__);
526 return ret_val;
527}
528
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700529static bool is_supported_format(audio_format_t format)
530{
Eric Laurent8251ac82014-07-23 11:00:25 -0700531 switch (format) {
532 case AUDIO_FORMAT_MP3:
533 case AUDIO_FORMAT_AAC_LC:
534 case AUDIO_FORMAT_AAC_HE_V1:
535 case AUDIO_FORMAT_AAC_HE_V2:
536 return true;
537 default:
538 break;
539 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700540 return false;
541}
542
Haynes Mathew George03c40102016-01-29 17:57:48 -0800543static inline bool is_mmap_usecase(audio_usecase_t uc_id)
544{
545 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
546 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
547}
548
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700549static int get_snd_codec_id(audio_format_t format)
550{
551 int id = 0;
552
Eric Laurent8251ac82014-07-23 11:00:25 -0700553 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700554 case AUDIO_FORMAT_MP3:
555 id = SND_AUDIOCODEC_MP3;
556 break;
557 case AUDIO_FORMAT_AAC:
558 id = SND_AUDIOCODEC_AAC;
559 break;
560 default:
561 ALOGE("%s: Unsupported audio format", __func__);
562 }
563
564 return id;
565}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800566
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800567static int audio_ssr_status(struct audio_device *adev)
568{
569 int ret = 0;
570 struct mixer_ctl *ctl;
571 const char *mixer_ctl_name = "Audio SSR Status";
572
573 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
574 ret = mixer_ctl_get_value(ctl, 0);
575 ALOGD("%s: value: %d", __func__, ret);
576 return ret;
577}
578
vivek mehta4a824772017-06-08 19:05:49 -0700579static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
580{
581 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
582}
583
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800584static bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
585{
586 return out_snd_device == SND_DEVICE_OUT_BT_SCO ||
587 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
588 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
589 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
590 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
591 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC;
592
593}
594
595static bool is_a2dp_device(snd_device_t out_snd_device)
596{
597 return out_snd_device == SND_DEVICE_OUT_BT_A2DP;
598}
599
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800600int enable_audio_route(struct audio_device *adev,
601 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800602{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700603 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800604 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800605
606 if (usecase == NULL)
607 return -EINVAL;
608
609 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
610
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800611 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700612 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800613 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700614 snd_device = usecase->out_snd_device;
Yamit Mehtae3b99562016-09-16 22:44:00 +0530615 audio_extn_utils_send_app_type_cfg(adev, usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800616 audio_extn_utils_send_audio_calibration(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800617 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500618 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000619 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700620 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700621 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800622
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800623 ALOGV("%s: exit", __func__);
624 return 0;
625}
626
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800627int disable_audio_route(struct audio_device *adev,
628 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800629{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700630 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800631 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800632
633 if (usecase == NULL)
634 return -EINVAL;
635
636 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700637 if (usecase->type == PCM_CAPTURE)
638 snd_device = usecase->in_snd_device;
639 else
640 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800641 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500642 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700643 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700644 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000645 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800646
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800647 ALOGV("%s: exit", __func__);
648 return 0;
649}
650
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800651int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700652 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800653{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700654 int i, num_devices = 0;
655 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800656 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800657 if (snd_device < SND_DEVICE_MIN ||
658 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800659 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800660 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800661 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700662
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700663 platform_send_audio_calibration(adev->platform, snd_device);
664
vivek mehtade4849c2016-03-03 17:23:38 -0800665 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700666 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700667 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800668 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700669 }
670
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700671 /* due to the possibility of calibration overwrite between listen
672 and audio, notify sound trigger hal before audio calibration is sent */
673 audio_extn_sound_trigger_update_device_status(snd_device,
674 ST_EVENT_SND_DEVICE_BUSY);
675
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700676 if (audio_extn_spkr_prot_is_enabled())
677 audio_extn_spkr_prot_calib_cancel(adev);
678
zhaoyang yin4211fad2015-06-04 21:13:25 +0800679 audio_extn_dsm_feedback_enable(adev, snd_device, true);
680
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700681 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800682 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
juyuchen1d05ba32018-03-31 16:03:51 +0800683 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700684 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
685 audio_extn_spkr_prot_is_enabled()) {
Aniket Kumar Lata9d6679a2018-04-11 18:13:23 -0700686 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800687 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700688 }
689 if (audio_extn_spkr_prot_start_processing(snd_device)) {
690 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800691 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700692 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700693 } else if (platform_can_split_snd_device(snd_device,
694 &num_devices,
695 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700696 for (i = 0; i < num_devices; i++) {
697 enable_snd_device(adev, new_snd_devices[i]);
698 }
vivek mehtab6506412015-08-07 16:55:17 -0700699 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700700 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800701 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
702 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
703 ALOGE(" %s: Invalid sound device returned", __func__);
704 goto on_error;
705 }
Ed Tam70b5c142016-03-21 19:14:29 -0700706
Eric Laurent2e140aa2016-06-30 17:14:46 -0700707 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Aniket Kumar Lataa158e862018-05-11 17:28:40 -0700708
709 if (is_a2dp_device(snd_device) &&
710 (audio_extn_a2dp_start_playback() < 0)) {
711 ALOGE("%s: failed to configure A2DP control path", __func__);
712 goto on_error;
713 }
714
vivek mehtade4849c2016-03-03 17:23:38 -0800715 audio_route_apply_and_update_path(adev->audio_route, device_name);
716 }
717on_success:
718 adev->snd_dev_ref_cnt[snd_device]++;
719 ret_val = 0;
720on_error:
721 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800722}
723
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800724int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700725 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800726{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700727 int i, num_devices = 0;
728 snd_device_t new_snd_devices[2];
729
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800730 if (snd_device < SND_DEVICE_MIN ||
731 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800732 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800733 return -EINVAL;
734 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700735 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
736 ALOGE("%s: device ref cnt is already 0", __func__);
737 return -EINVAL;
738 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800739 audio_extn_tfa_98xx_disable_speaker(snd_device);
740
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700741 adev->snd_dev_ref_cnt[snd_device]--;
742 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800743 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800744
745 if (is_a2dp_device(snd_device))
746 audio_extn_a2dp_stop_playback();
747
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700748 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800749 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700750 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700751 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
752 audio_extn_spkr_prot_is_enabled()) {
753 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700754
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700755 // FIXME b/65363602: bullhead is the only Nexus with audio_extn_spkr_prot_is_enabled()
756 // and does not use speaker swap. As this code causes a problem with device enable ref
757 // counting we remove it for now.
vivek mehtae59cfb22017-06-16 15:57:11 -0700758 // when speaker device is disabled, reset swap.
759 // will be renabled on usecase start
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700760 // platform_set_swap_channels(adev, false);
vivek mehtae59cfb22017-06-16 15:57:11 -0700761
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700762 } else if (platform_can_split_snd_device(snd_device,
763 &num_devices,
764 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700765 for (i = 0; i < num_devices; i++) {
766 disable_snd_device(adev, new_snd_devices[i]);
767 }
vivek mehtab6506412015-08-07 16:55:17 -0700768 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700769 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800770 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
771 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
772 ALOGE(" %s: Invalid sound device returned", __func__);
773 return -EINVAL;
774 }
775
Eric Laurent2e140aa2016-06-30 17:14:46 -0700776 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800777 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700778 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700779 audio_extn_sound_trigger_update_device_status(snd_device,
780 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700781 }
vivek mehtab6506412015-08-07 16:55:17 -0700782
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800783 return 0;
784}
785
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700786/*
787 legend:
788 uc - existing usecase
789 new_uc - new usecase
790 d1, d11, d2 - SND_DEVICE enums
791 a1, a2 - corresponding ANDROID device enums
792 B, B1, B2 - backend strings
793
794case 1
795 uc->dev d1 (a1) B1
796 new_uc->dev d1 (a1), d2 (a2) B1, B2
797
798 resolution: disable and enable uc->dev on d1
799
800case 2
801 uc->dev d1 (a1) B1
802 new_uc->dev d11 (a1) B1
803
804 resolution: need to switch uc since d1 and d11 are related
805 (e.g. speaker and voice-speaker)
806 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
807
808case 3
809 uc->dev d1 (a1) B1
810 new_uc->dev d2 (a2) B2
811
812 resolution: no need to switch uc
813
814case 4
815 uc->dev d1 (a1) B
816 new_uc->dev d2 (a2) B
817
818 resolution: disable enable uc-dev on d2 since backends match
819 we cannot enable two streams on two different devices if they
820 share the same backend. e.g. if offload is on speaker device using
821 QUAD_MI2S backend and a low-latency stream is started on voice-handset
822 using the same backend, offload must also be switched to voice-handset.
823
824case 5
825 uc->dev d1 (a1) B
826 new_uc->dev d1 (a1), d2 (a2) B
827
828 resolution: disable enable uc-dev on d2 since backends match
829 we cannot enable two streams on two different devices if they
830 share the same backend.
831
832case 6
833 uc->dev d1 a1 B1
834 new_uc->dev d2 a1 B2
835
836 resolution: no need to switch
837
838case 7
839
840 uc->dev d1 (a1), d2 (a2) B1, B2
841 new_uc->dev d1 B1
842
843 resolution: no need to switch
844
845*/
846static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
847 struct audio_usecase *new_uc,
848 snd_device_t new_snd_device)
849{
850 audio_devices_t a1 = uc->stream.out->devices;
851 audio_devices_t a2 = new_uc->stream.out->devices;
852
853 snd_device_t d1 = uc->out_snd_device;
854 snd_device_t d2 = new_snd_device;
855
856 // Treat as a special case when a1 and a2 are not disjoint
857 if ((a1 != a2) && (a1 & a2)) {
858 snd_device_t d3[2];
859 int num_devices = 0;
860 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
861 &num_devices,
862 d3);
863 if (ret < 0) {
864 if (ret != -ENOSYS) {
865 ALOGW("%s failed to split snd_device %d",
866 __func__,
867 popcount(a1) > 1 ? d1 : d2);
868 }
869 goto end;
870 }
871
872 // NB: case 7 is hypothetical and isn't a practical usecase yet.
873 // But if it does happen, we need to give priority to d2 if
874 // the combo devices active on the existing usecase share a backend.
875 // This is because we cannot have a usecase active on a combo device
876 // and a new usecase requests one device in this combo pair.
877 if (platform_check_backends_match(d3[0], d3[1])) {
878 return d2; // case 5
879 } else {
880 return d1; // case 1
881 }
882 } else {
883 if (platform_check_backends_match(d1, d2)) {
884 return d2; // case 2, 4
885 } else {
886 return d1; // case 6, 3
887 }
888 }
889
890end:
891 return d2; // return whatever was calculated before.
892}
893
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700894static void check_and_route_playback_usecases(struct audio_device *adev,
895 struct audio_usecase *uc_info,
896 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700897{
898 struct listnode *node;
899 struct audio_usecase *usecase;
900 bool switch_device[AUDIO_USECASE_MAX];
901 int i, num_uc_to_switch = 0;
902
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700903 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
904 uc_info,
905 snd_device);
David Linee3fe402017-03-13 10:00:42 -0700906
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800907 /* For a2dp device reconfigure all active sessions
908 * with new AFE encoder format based on a2dp state
909 */
910 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Aniket Kumar Lata9723a962018-05-16 17:41:55 -0700911 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
912 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800913 audio_extn_a2dp_is_force_device_switch()) {
914 force_routing = true;
915 }
916
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700917 /*
918 * This function is to make sure that all the usecases that are active on
919 * the hardware codec backend are always routed to any one device that is
920 * handled by the hardware codec.
921 * For example, if low-latency and deep-buffer usecases are currently active
922 * on speaker and out_set_parameters(headset) is received on low-latency
923 * output, then we have to make sure deep-buffer is also switched to headset,
924 * because of the limitation that both the devices cannot be enabled
925 * at the same time as they share the same backend.
926 */
927 /* Disable all the usecases on the shared backend other than the
928 specified usecase */
929 for (i = 0; i < AUDIO_USECASE_MAX; i++)
930 switch_device[i] = false;
931
932 list_for_each(node, &adev->usecase_list) {
933 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700934 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
935 continue;
936
937 if (force_routing ||
938 (usecase->out_snd_device != snd_device &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -0700939 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
940 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700941 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700942 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
943 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700944 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700945 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700946 switch_device[usecase->id] = true;
947 num_uc_to_switch++;
948 }
949 }
950
951 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700952 list_for_each(node, &adev->usecase_list) {
953 usecase = node_to_item(node, struct audio_usecase, list);
954 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700955 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900956 }
957 }
958
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700959 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900960 list_for_each(node, &adev->usecase_list) {
961 usecase = node_to_item(node, struct audio_usecase, list);
962 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700963 d_device = derive_playback_snd_device(usecase, uc_info,
964 snd_device);
965 enable_snd_device(adev, d_device);
966 /* Update the out_snd_device before enabling the audio route */
967 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700968 }
969 }
970
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700971 /* Re-route all the usecases on the shared backend other than the
972 specified usecase to new snd devices */
973 list_for_each(node, &adev->usecase_list) {
974 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700975 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700976 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700977 }
978 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700979 }
980}
981
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700982static void check_and_route_capture_usecases(struct audio_device *adev,
983 struct audio_usecase *uc_info,
984 snd_device_t snd_device)
985{
986 struct listnode *node;
987 struct audio_usecase *usecase;
988 bool switch_device[AUDIO_USECASE_MAX];
989 int i, num_uc_to_switch = 0;
990
vivek mehta4ed66e62016-04-15 23:33:34 -0700991 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
992
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700993 /*
994 * This function is to make sure that all the active capture usecases
995 * are always routed to the same input sound device.
996 * For example, if audio-record and voice-call usecases are currently
997 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
998 * is received for voice call then we have to make sure that audio-record
999 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1000 * because of the limitation that two devices cannot be enabled
1001 * at the same time if they share the same backend.
1002 */
1003 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1004 switch_device[i] = false;
1005
1006 list_for_each(node, &adev->usecase_list) {
1007 usecase = node_to_item(node, struct audio_usecase, list);
1008 if (usecase->type != PCM_PLAYBACK &&
1009 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -07001010 usecase->in_snd_device != snd_device &&
1011 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001012 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1013 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001014 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001015 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001016 switch_device[usecase->id] = true;
1017 num_uc_to_switch++;
1018 }
1019 }
1020
1021 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001022 list_for_each(node, &adev->usecase_list) {
1023 usecase = node_to_item(node, struct audio_usecase, list);
1024 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001025 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001026 }
1027 }
1028
1029 list_for_each(node, &adev->usecase_list) {
1030 usecase = node_to_item(node, struct audio_usecase, list);
1031 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001032 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001033 }
1034 }
1035
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001036 /* Re-route all the usecases on the shared backend other than the
1037 specified usecase to new snd devices */
1038 list_for_each(node, &adev->usecase_list) {
1039 usecase = node_to_item(node, struct audio_usecase, list);
1040 /* Update the in_snd_device only before enabling the audio route */
1041 if (switch_device[usecase->id] ) {
1042 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001043 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001044 }
1045 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001046 }
1047}
1048
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001049/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001050static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001051{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001052 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001053 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001054
1055 switch (channels) {
1056 /*
1057 * Do not handle stereo output in Multi-channel cases
1058 * Stereo case is handled in normal playback path
1059 */
1060 case 6:
1061 ALOGV("%s: HDMI supports 5.1", __func__);
1062 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1063 break;
1064 case 8:
1065 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
1066 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1067 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
1068 break;
1069 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001070 ALOGE("HDMI does not support multi channel playback");
1071 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001072 break;
1073 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001074 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001075}
1076
Andy Hung18859412017-08-09 11:47:21 -07001077static ssize_t read_usb_sup_sample_rates(bool is_playback,
1078 uint32_t *supported_sample_rates,
1079 uint32_t max_rates)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001080{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001081 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1082 supported_sample_rates,
1083 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001084#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001085 for (ssize_t i=0; i<count; i++) {
1086 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1087 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001088 }
1089#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001090 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001091}
1092
Haynes Mathew George569b7482017-05-08 14:44:27 -07001093static int read_usb_sup_channel_masks(bool is_playback,
1094 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001095 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001096{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001097 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001098 int channel_count;
1099 uint32_t num_masks = 0;
1100 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1101 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001102 }
Eric Laurent74b55762017-07-09 17:04:53 -07001103 if (is_playback) {
Andy Hung6c1afb12017-12-22 11:34:41 -08001104 // start from 2 channels as framework currently doesn't support mono.
1105 // TODO: consider only supporting channel index masks beyond stereo here.
1106 for (channel_count = FCC_2;
1107 channel_count <= channels && num_masks < max_masks;
1108 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001109 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1110 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001111 for (channel_count = FCC_2;
1112 channel_count <= channels && num_masks < max_masks;
1113 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001114 supported_channel_masks[num_masks++] =
1115 audio_channel_mask_for_index_assignment_from_count(channel_count);
1116 }
1117 } else {
1118 // For capture we report all supported channel masks from 1 channel up.
1119 channel_count = MIN_CHANNEL_COUNT;
1120 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1121 // indexed mask
1122 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1123 supported_channel_masks[num_masks++] =
1124 audio_channel_in_mask_from_count(channel_count);
1125 }
1126 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001127#ifdef NDEBUG
1128 for (size_t i = 0; i < num_masks; ++i) {
1129 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1130 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
1131 }
1132#endif
Eric Laurent74b55762017-07-09 17:04:53 -07001133 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001134}
1135
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001136static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001137 audio_format_t *supported_formats,
1138 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001139{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001140 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001141 switch (bitwidth) {
1142 case 24:
1143 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001144 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001145 break;
1146 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001147 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001148 break;
1149 case 16:
1150 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001151 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001152 break;
1153 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001154 ALOGV("%s: %s supported format %d", __func__,
1155 is_playback ? "P" : "C", bitwidth);
1156 return 1;
1157}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001158
Haynes Mathew George569b7482017-05-08 14:44:27 -07001159static int read_usb_sup_params_and_compare(bool is_playback,
1160 audio_format_t *format,
1161 audio_format_t *supported_formats,
1162 uint32_t max_formats,
1163 audio_channel_mask_t *mask,
1164 audio_channel_mask_t *supported_channel_masks,
1165 uint32_t max_masks,
1166 uint32_t *rate,
1167 uint32_t *supported_sample_rates,
1168 uint32_t max_rates) {
1169 int ret = 0;
1170 int num_formats;
1171 int num_masks;
1172 int num_rates;
1173 int i;
1174
1175 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1176 max_formats);
1177 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1178 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001179
Haynes Mathew George569b7482017-05-08 14:44:27 -07001180 num_rates = read_usb_sup_sample_rates(is_playback,
1181 supported_sample_rates, max_rates);
1182
1183#define LUT(table, len, what, dflt) \
1184 for (i=0; i<len && (table[i] != what); i++); \
1185 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1186
1187 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1188 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1189 LUT(supported_sample_rates, num_rates, *rate, 0);
1190
1191#undef LUT
1192 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001193}
1194
Andy Hungd9653bd2017-08-01 19:31:39 -07001195static bool is_usb_ready(struct audio_device *adev, bool is_playback)
1196{
1197 // Check if usb is ready.
1198 // The usb device may have been removed quickly after insertion and hence
1199 // no longer available. This will show up as empty channel masks, or rates.
1200
1201 pthread_mutex_lock(&adev->lock);
1202 uint32_t supported_sample_rate;
1203
1204 // we consider usb ready if we can fetch at least one sample rate.
1205 const bool ready = read_usb_sup_sample_rates(
1206 is_playback, &supported_sample_rate, 1 /* max_rates */) > 0;
1207 pthread_mutex_unlock(&adev->lock);
1208 return ready;
1209}
1210
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001211static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1212{
1213 struct audio_usecase *usecase;
1214 struct listnode *node;
1215
1216 list_for_each(node, &adev->usecase_list) {
1217 usecase = node_to_item(node, struct audio_usecase, list);
1218 if (usecase->type == VOICE_CALL) {
1219 ALOGV("%s: usecase id %d", __func__, usecase->id);
1220 return usecase->id;
1221 }
1222 }
1223 return USECASE_INVALID;
1224}
1225
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001226struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1227 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001228{
1229 struct audio_usecase *usecase;
1230 struct listnode *node;
1231
1232 list_for_each(node, &adev->usecase_list) {
1233 usecase = node_to_item(node, struct audio_usecase, list);
1234 if (usecase->id == uc_id)
1235 return usecase;
1236 }
1237 return NULL;
1238}
1239
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001240static bool force_device_switch(struct audio_usecase *usecase)
1241{
1242 if (usecase->stream.out == NULL) {
1243 ALOGE("%s: stream.out is NULL", __func__);
1244 return false;
1245 }
1246
1247 // Force all A2DP output devices to reconfigure for proper AFE encode format
1248 // Also handle a case where in earlier A2DP start failed as A2DP stream was
1249 // in suspended state, hence try to trigger a retry when we again get a routing request.
1250 if ((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
1251 audio_extn_a2dp_is_force_device_switch()) {
1252 ALOGD("%s: Force A2DP device switch to update new encoder config", __func__);
1253 return true;
1254 }
1255
1256 return false;
1257}
1258
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001259int select_devices(struct audio_device *adev,
1260 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001261{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001262 snd_device_t out_snd_device = SND_DEVICE_NONE;
1263 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001264 struct audio_usecase *usecase = NULL;
1265 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001266 struct audio_usecase *hfp_usecase = NULL;
1267 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001268 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001269 int status = 0;
Eric Laurentf4520b02017-09-20 18:31:58 -07001270 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1271 USECASE_AUDIO_PLAYBACK_VOIP);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001272
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001273 usecase = get_usecase_from_list(adev, uc_id);
1274 if (usecase == NULL) {
1275 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1276 return -EINVAL;
1277 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001278
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001279 if ((usecase->type == VOICE_CALL) ||
1280 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001281 out_snd_device = platform_get_output_snd_device(adev->platform,
1282 usecase->stream.out->devices);
1283 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001284 usecase->devices = usecase->stream.out->devices;
1285 } else {
1286 /*
1287 * If the voice call is active, use the sound devices of voice call usecase
1288 * so that it would not result any device switch. All the usecases will
1289 * be switched to new device when select_devices() is called for voice call
1290 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001291 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001292 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001293 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001294 vc_usecase = get_usecase_from_list(adev,
1295 get_voice_usecase_id_from_list(adev));
1296 if ((vc_usecase != NULL) &&
1297 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1298 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001299 in_snd_device = vc_usecase->in_snd_device;
1300 out_snd_device = vc_usecase->out_snd_device;
1301 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001302 } else if (audio_extn_hfp_is_active(adev)) {
1303 hfp_ucid = audio_extn_hfp_get_usecase();
1304 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1305 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1306 in_snd_device = hfp_usecase->in_snd_device;
1307 out_snd_device = hfp_usecase->out_snd_device;
1308 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001309 }
1310 if (usecase->type == PCM_PLAYBACK) {
1311 usecase->devices = usecase->stream.out->devices;
1312 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001313 if (out_snd_device == SND_DEVICE_NONE) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001314 struct stream_out *voip_out = adev->primary_output;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001315
Eric Laurentb23d5282013-05-14 15:27:20 -07001316 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001317 usecase->stream.out->devices);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001318
1319 if (voip_usecase)
1320 voip_out = voip_usecase->stream.out;
1321
1322 if (usecase->stream.out == voip_out &&
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001323 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001324 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001325 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001326 select_devices(adev, adev->active_input->usecase);
1327 }
1328 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001329 } else if (usecase->type == PCM_CAPTURE) {
1330 usecase->devices = usecase->stream.in->device;
1331 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001332 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001333 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001334 if (adev->active_input &&
1335 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1336 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001337
1338 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1339 USECASE_AUDIO_PLAYBACK_VOIP);
1340
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001341 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001342 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1343 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001344 } else if (voip_usecase) {
1345 out_device = voip_usecase->stream.out->devices;
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001346 } else if (adev->primary_output) {
1347 out_device = adev->primary_output->devices;
1348 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001349 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001350 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001351 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001352 }
1353 }
1354
1355 if (out_snd_device == usecase->out_snd_device &&
1356 in_snd_device == usecase->in_snd_device) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001357 if (!force_device_switch(usecase))
1358 return 0;
1359 }
1360
1361 if (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready()) {
1362 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1363 return 0;
1364 }
1365
Aniket Kumar Lata9723a962018-05-16 17:41:55 -07001366 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
1367 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001368 (!audio_extn_a2dp_is_ready())) {
1369 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
juyuchen9baad392018-06-05 19:02:10 +08001370 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
1371 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
1372 else
1373 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001374 }
1375
Eric Laurent2bafff12016-03-17 12:17:23 -07001376 if (out_snd_device != SND_DEVICE_NONE &&
1377 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1378 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1379 __func__,
1380 use_case_table[uc_id],
1381 adev->last_logged_snd_device[uc_id][0],
1382 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1383 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1384 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1385 -1,
1386 out_snd_device,
1387 platform_get_snd_device_name(out_snd_device),
1388 platform_get_snd_device_acdb_id(out_snd_device));
1389 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1390 }
1391 if (in_snd_device != SND_DEVICE_NONE &&
1392 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1393 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1394 __func__,
1395 use_case_table[uc_id],
1396 adev->last_logged_snd_device[uc_id][1],
1397 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1398 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1399 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1400 -1,
1401 in_snd_device,
1402 platform_get_snd_device_name(in_snd_device),
1403 platform_get_snd_device_acdb_id(in_snd_device));
1404 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1405 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001406
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001407 /*
1408 * Limitation: While in call, to do a device switch we need to disable
1409 * and enable both RX and TX devices though one of them is same as current
1410 * device.
1411 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001412 if ((usecase->type == VOICE_CALL) &&
1413 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1414 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001415 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001416 /* Disable sidetone only if voice call already exists */
1417 if (voice_is_call_state_active(adev))
1418 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001419 }
1420
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001421 /* Disable current sound devices */
1422 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001423 disable_audio_route(adev, usecase);
1424 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001425 }
1426
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001427 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001428 disable_audio_route(adev, usecase);
1429 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001430 }
1431
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001432 /* Applicable only on the targets that has external modem.
1433 * New device information should be sent to modem before enabling
1434 * the devices to reduce in-call device switch time.
1435 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001436 if ((usecase->type == VOICE_CALL) &&
1437 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1438 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001439 status = platform_switch_voice_call_enable_device_config(adev->platform,
1440 out_snd_device,
1441 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001442 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001443
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001444 /* Enable new sound devices */
1445 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001446 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001447 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) ||
1448 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001449 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001450 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001451 }
1452
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001453 if (in_snd_device != SND_DEVICE_NONE) {
1454 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001455 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001456 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001457
Eric Laurentb23d5282013-05-14 15:27:20 -07001458 if (usecase->type == VOICE_CALL)
1459 status = platform_switch_voice_call_device_post(adev->platform,
1460 out_snd_device,
1461 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001462
sangwoo170731f2013-06-08 15:36:36 +09001463 usecase->in_snd_device = in_snd_device;
1464 usecase->out_snd_device = out_snd_device;
1465
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001466 audio_extn_tfa_98xx_set_mode();
1467
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001468 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001469
Jasmine Cha70771b62018-05-15 15:02:43 +08001470 audio_extn_ma_set_device(usecase);
jasmine cha270b7762018-03-30 15:41:33 +08001471
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001472 /* Applicable only on the targets that has external modem.
1473 * Enable device command should be sent to modem only after
1474 * enabling voice call mixer controls
1475 */
vivek mehta765eb642015-08-07 19:46:06 -07001476 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001477 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1478 out_snd_device,
1479 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001480 /* Enable sidetone only if voice call already exists */
1481 if (voice_is_call_state_active(adev))
1482 voice_set_sidetone(adev, out_snd_device, true);
1483 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001484
Eric Laurentf4520b02017-09-20 18:31:58 -07001485 if (usecase == voip_usecase) {
1486 struct stream_out *voip_out = voip_usecase->stream.out;
1487 audio_extn_utils_send_app_type_gain(adev,
1488 voip_out->app_type_cfg.app_type,
1489 &voip_out->app_type_cfg.gain[0]);
1490 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001491 return status;
1492}
1493
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001494static int stop_input_stream(struct stream_in *in)
1495{
1496 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001497 struct audio_usecase *uc_info;
1498 struct audio_device *adev = in->dev;
1499
Eric Laurent994a6932013-07-17 11:51:42 -07001500 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001501 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001502
1503 if (adev->active_input) {
1504 if (adev->active_input->usecase == in->usecase) {
1505 adev->active_input = NULL;
1506 } else {
1507 ALOGW("%s adev->active_input->usecase %s, v/s in->usecase %s",
1508 __func__,
1509 use_case_table[adev->active_input->usecase],
1510 use_case_table[in->usecase]);
1511 }
1512 }
1513
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001514 uc_info = get_usecase_from_list(adev, in->usecase);
1515 if (uc_info == NULL) {
1516 ALOGE("%s: Could not find the usecase (%d) in the list",
1517 __func__, in->usecase);
1518 return -EINVAL;
1519 }
1520
vivek mehta781065c2017-04-04 12:55:01 -07001521 /* Close in-call recording streams */
1522 voice_check_and_stop_incall_rec_usecase(adev, in);
1523
Eric Laurent150dbfe2013-02-27 14:31:02 -08001524 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001525 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001526
1527 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001528 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001529
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001530 list_remove(&uc_info->list);
1531 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001532
Eric Laurent994a6932013-07-17 11:51:42 -07001533 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001534 return ret;
1535}
1536
1537int start_input_stream(struct stream_in *in)
1538{
1539 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001540 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001541 struct audio_usecase *uc_info;
1542 struct audio_device *adev = in->dev;
1543
Eric Laurent994a6932013-07-17 11:51:42 -07001544 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001545
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001546 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1547 return -EIO;
1548
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001549 if (in->card_status == CARD_STATUS_OFFLINE ||
1550 adev->card_status == CARD_STATUS_OFFLINE) {
1551 ALOGW("in->card_status or adev->card_status offline, try again");
1552 ret = -EAGAIN;
1553 goto error_config;
1554 }
1555
vivek mehta781065c2017-04-04 12:55:01 -07001556 /* Check if source matches incall recording usecase criteria */
1557 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1558 if (ret)
1559 goto error_config;
1560 else
1561 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1562
Eric Laurentb23d5282013-05-14 15:27:20 -07001563 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001564 if (in->pcm_device_id < 0) {
1565 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1566 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001567 ret = -EINVAL;
1568 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001569 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001570
1571 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001572 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1573 uc_info->id = in->usecase;
1574 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001575 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001576 uc_info->devices = in->device;
1577 uc_info->in_snd_device = SND_DEVICE_NONE;
1578 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001579
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001580 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001581
Wei Wangf4837d52017-11-21 14:51:20 -08001582 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001583 audio_extn_perf_lock_acquire();
1584
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001585 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001586
Eric Laurent0e46adf2016-12-16 12:49:24 -08001587 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001588 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001589 ALOGE("%s: pcm stream not ready", __func__);
1590 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001591 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001592 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001593 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001594 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1595 goto error_open;
1596 }
1597 } else {
1598 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1599 unsigned int pcm_open_retry_count = 0;
1600
1601 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1602 flags |= PCM_MMAP | PCM_NOIRQ;
1603 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1604 } else if (in->realtime) {
1605 flags |= PCM_MMAP | PCM_NOIRQ;
1606 }
1607
1608 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1609 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1610
1611 while (1) {
1612 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1613 flags, &in->config);
1614 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1615 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1616 if (in->pcm != NULL) {
1617 pcm_close(in->pcm);
1618 in->pcm = NULL;
1619 }
1620 if (pcm_open_retry_count-- == 0) {
1621 ret = -EIO;
1622 goto error_open;
1623 }
1624 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1625 continue;
1626 }
1627 break;
1628 }
1629
1630 ALOGV("%s: pcm_prepare", __func__);
1631 ret = pcm_prepare(in->pcm);
1632 if (ret < 0) {
1633 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001634 pcm_close(in->pcm);
1635 in->pcm = NULL;
1636 goto error_open;
1637 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001638 if (in->realtime) {
1639 ret = pcm_start(in->pcm);
1640 if (ret < 0) {
1641 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1642 pcm_close(in->pcm);
1643 in->pcm = NULL;
1644 goto error_open;
1645 }
1646 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001647 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001648 register_in_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001649 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001650 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001651 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001652
Eric Laurent0e46adf2016-12-16 12:49:24 -08001653 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001654
1655error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001656 stop_input_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001657 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001658 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001659
1660error_config:
1661 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001662 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001663 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001664}
1665
Eric Laurenta1478072015-09-21 17:21:52 -07001666void lock_input_stream(struct stream_in *in)
1667{
1668 pthread_mutex_lock(&in->pre_lock);
1669 pthread_mutex_lock(&in->lock);
1670 pthread_mutex_unlock(&in->pre_lock);
1671}
1672
1673void lock_output_stream(struct stream_out *out)
1674{
1675 pthread_mutex_lock(&out->pre_lock);
1676 pthread_mutex_lock(&out->lock);
1677 pthread_mutex_unlock(&out->pre_lock);
1678}
1679
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001680/* must be called with out->lock locked */
1681static int send_offload_cmd_l(struct stream_out* out, int command)
1682{
1683 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1684
1685 ALOGVV("%s %d", __func__, command);
1686
1687 cmd->cmd = command;
1688 list_add_tail(&out->offload_cmd_list, &cmd->node);
1689 pthread_cond_signal(&out->offload_cond);
1690 return 0;
1691}
1692
1693/* must be called iwth out->lock locked */
1694static void stop_compressed_output_l(struct stream_out *out)
1695{
1696 out->offload_state = OFFLOAD_STATE_IDLE;
1697 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001698 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001699 if (out->compr != NULL) {
1700 compress_stop(out->compr);
1701 while (out->offload_thread_blocked) {
1702 pthread_cond_wait(&out->cond, &out->lock);
1703 }
1704 }
1705}
1706
1707static void *offload_thread_loop(void *context)
1708{
1709 struct stream_out *out = (struct stream_out *) context;
1710 struct listnode *item;
1711
1712 out->offload_state = OFFLOAD_STATE_IDLE;
1713 out->playback_started = 0;
1714
1715 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1716 set_sched_policy(0, SP_FOREGROUND);
1717 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1718
1719 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001720 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001721 for (;;) {
1722 struct offload_cmd *cmd = NULL;
1723 stream_callback_event_t event;
1724 bool send_callback = false;
1725
1726 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1727 __func__, list_empty(&out->offload_cmd_list),
1728 out->offload_state);
1729 if (list_empty(&out->offload_cmd_list)) {
1730 ALOGV("%s SLEEPING", __func__);
1731 pthread_cond_wait(&out->offload_cond, &out->lock);
1732 ALOGV("%s RUNNING", __func__);
1733 continue;
1734 }
1735
1736 item = list_head(&out->offload_cmd_list);
1737 cmd = node_to_item(item, struct offload_cmd, node);
1738 list_remove(item);
1739
1740 ALOGVV("%s STATE %d CMD %d out->compr %p",
1741 __func__, out->offload_state, cmd->cmd, out->compr);
1742
1743 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1744 free(cmd);
1745 break;
1746 }
1747
1748 if (out->compr == NULL) {
1749 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001750 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001751 pthread_cond_signal(&out->cond);
1752 continue;
1753 }
1754 out->offload_thread_blocked = true;
1755 pthread_mutex_unlock(&out->lock);
1756 send_callback = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001757 switch (cmd->cmd) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001758 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1759 compress_wait(out->compr, -1);
1760 send_callback = true;
1761 event = STREAM_CBK_EVENT_WRITE_READY;
1762 break;
1763 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001764 compress_next_track(out->compr);
1765 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001766 send_callback = true;
1767 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001768 /* Resend the metadata for next iteration */
1769 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001770 break;
1771 case OFFLOAD_CMD_DRAIN:
1772 compress_drain(out->compr);
1773 send_callback = true;
1774 event = STREAM_CBK_EVENT_DRAIN_READY;
1775 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001776 case OFFLOAD_CMD_ERROR:
1777 send_callback = true;
1778 event = STREAM_CBK_EVENT_ERROR;
1779 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001780 default:
1781 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1782 break;
1783 }
Eric Laurenta1478072015-09-21 17:21:52 -07001784 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001785 out->offload_thread_blocked = false;
1786 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001787 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001788 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001789 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001790 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001791 free(cmd);
1792 }
1793
1794 pthread_cond_signal(&out->cond);
1795 while (!list_empty(&out->offload_cmd_list)) {
1796 item = list_head(&out->offload_cmd_list);
1797 list_remove(item);
1798 free(node_to_item(item, struct offload_cmd, node));
1799 }
1800 pthread_mutex_unlock(&out->lock);
1801
1802 return NULL;
1803}
1804
1805static int create_offload_callback_thread(struct stream_out *out)
1806{
1807 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1808 list_init(&out->offload_cmd_list);
1809 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1810 offload_thread_loop, out);
1811 return 0;
1812}
1813
1814static int destroy_offload_callback_thread(struct stream_out *out)
1815{
Eric Laurenta1478072015-09-21 17:21:52 -07001816 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001817 stop_compressed_output_l(out);
1818 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1819
1820 pthread_mutex_unlock(&out->lock);
1821 pthread_join(out->offload_thread, (void **) NULL);
1822 pthread_cond_destroy(&out->offload_cond);
1823
1824 return 0;
1825}
1826
Eric Laurent07eeafd2013-10-06 12:52:49 -07001827static bool allow_hdmi_channel_config(struct audio_device *adev)
1828{
1829 struct listnode *node;
1830 struct audio_usecase *usecase;
1831 bool ret = true;
1832
1833 list_for_each(node, &adev->usecase_list) {
1834 usecase = node_to_item(node, struct audio_usecase, list);
1835 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1836 /*
1837 * If voice call is already existing, do not proceed further to avoid
1838 * disabling/enabling both RX and TX devices, CSD calls, etc.
1839 * Once the voice call done, the HDMI channels can be configured to
1840 * max channels of remaining use cases.
1841 */
1842 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001843 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001844 __func__);
1845 ret = false;
1846 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001847 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1848 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001849 "no change in HDMI channels", __func__);
1850 ret = false;
1851 break;
1852 }
1853 }
1854 }
1855 return ret;
1856}
1857
1858static int check_and_set_hdmi_channels(struct audio_device *adev,
1859 unsigned int channels)
1860{
1861 struct listnode *node;
1862 struct audio_usecase *usecase;
1863
1864 /* Check if change in HDMI channel config is allowed */
1865 if (!allow_hdmi_channel_config(adev))
1866 return 0;
1867
1868 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001869 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001870 return 0;
1871 }
1872
1873 platform_set_hdmi_channels(adev->platform, channels);
1874 adev->cur_hdmi_channels = channels;
1875
1876 /*
1877 * Deroute all the playback streams routed to HDMI so that
1878 * the back end is deactivated. Note that backend will not
1879 * be deactivated if any one stream is connected to it.
1880 */
1881 list_for_each(node, &adev->usecase_list) {
1882 usecase = node_to_item(node, struct audio_usecase, list);
1883 if (usecase->type == PCM_PLAYBACK &&
1884 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001885 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001886 }
1887 }
1888
1889 /*
1890 * Enable all the streams disabled above. Now the HDMI backend
1891 * will be activated with new channel configuration
1892 */
1893 list_for_each(node, &adev->usecase_list) {
1894 usecase = node_to_item(node, struct audio_usecase, list);
1895 if (usecase->type == PCM_PLAYBACK &&
1896 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001897 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001898 }
1899 }
1900
1901 return 0;
1902}
1903
Haynes Mathew George65f6b432018-02-27 17:44:55 -08001904static int check_and_set_usb_service_interval(struct audio_device *adev,
1905 struct audio_usecase *uc_info,
1906 bool min)
1907{
1908 struct listnode *node;
1909 struct audio_usecase *usecase;
1910 bool switch_usecases = false;
1911 bool reconfig = false;
1912
1913 if ((uc_info->id != USECASE_AUDIO_PLAYBACK_MMAP) &&
1914 (uc_info->id != USECASE_AUDIO_PLAYBACK_ULL))
1915 return -1;
1916
1917 /* set if the valid usecase do not already exist */
1918 list_for_each(node, &adev->usecase_list) {
1919 usecase = node_to_item(node, struct audio_usecase, list);
1920 if (usecase->type == PCM_PLAYBACK &&
1921 (audio_is_usb_out_device(usecase->devices & AUDIO_DEVICE_OUT_ALL_USB))) {
1922 switch (usecase->id) {
1923 case USECASE_AUDIO_PLAYBACK_MMAP:
1924 case USECASE_AUDIO_PLAYBACK_ULL:
1925 // cannot reconfig while mmap/ull is present.
1926 return -1;
1927 default:
1928 switch_usecases = true;
1929 break;
1930 }
1931 }
1932 if (switch_usecases)
1933 break;
1934 }
1935 /*
1936 * client can try to set service interval in start_output_stream
1937 * to min or to 0 (i.e reset) in stop_output_stream .
1938 */
1939 unsigned long service_interval =
1940 audio_extn_usb_find_service_interval(min, true /*playback*/);
1941 int ret = platform_set_usb_service_interval(adev->platform,
1942 true /*playback*/,
1943 service_interval,
1944 &reconfig);
1945 /* no change or not supported or no active usecases */
1946 if (ret || !reconfig || !switch_usecases)
1947 return -1;
1948 return 0;
1949#undef VALID_USECASE
1950}
1951
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001952static int stop_output_stream(struct stream_out *out)
1953{
1954 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001955 struct audio_usecase *uc_info;
1956 struct audio_device *adev = out->dev;
HW Lee88512e92018-06-12 15:26:09 +08001957 bool has_voip_usecase =
1958 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001959
Eric Laurent994a6932013-07-17 11:51:42 -07001960 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001961 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001962 uc_info = get_usecase_from_list(adev, out->usecase);
1963 if (uc_info == NULL) {
1964 ALOGE("%s: Could not find the usecase (%d) in the list",
1965 __func__, out->usecase);
1966 return -EINVAL;
1967 }
1968
Haynes Mathew George41f86652014-06-17 14:22:15 -07001969 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1970 if (adev->visualizer_stop_output != NULL)
1971 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1972 if (adev->offload_effects_stop_output != NULL)
1973 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08001974 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
1975 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
1976 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07001977 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001978
Eric Laurent150dbfe2013-02-27 14:31:02 -08001979 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001980 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001981
1982 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001983 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001984
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001985 list_remove(&uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001986
Eric Laurent0499d4f2014-08-25 22:39:29 -05001987 audio_extn_extspk_update(adev->extspk);
1988
Eric Laurent07eeafd2013-10-06 12:52:49 -07001989 /* Must be called after removing the usecase from list */
1990 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1991 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
HW Lee88512e92018-06-12 15:26:09 +08001992 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
Haynes Mathew George65f6b432018-02-27 17:44:55 -08001993 ret = check_and_set_usb_service_interval(adev, uc_info, false /*min*/);
1994 if (ret == 0) {
1995 /* default service interval was successfully updated,
1996 reopen USB backend with new service interval */
1997 check_and_route_playback_usecases(adev, uc_info, uc_info->out_snd_device);
1998 }
1999 ret = 0;
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07002000 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002001
HW Lee88512e92018-06-12 15:26:09 +08002002 if (has_voip_usecase ||
2003 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
2004 struct listnode *node;
2005 struct audio_usecase *usecase;
2006 list_for_each(node, &adev->usecase_list) {
2007 usecase = node_to_item(node, struct audio_usecase, list);
2008 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
2009 continue;
2010
2011 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
2012 __func__, usecase->id, use_case_table[usecase->id],
2013 out->usecase, use_case_table[out->usecase]);
2014 select_devices(adev, usecase->id);
2015 }
2016 }
2017
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002018 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07002019 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002020 return ret;
2021}
2022
2023int start_output_stream(struct stream_out *out)
2024{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002025 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002026 struct audio_usecase *uc_info;
2027 struct audio_device *adev = out->dev;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002028 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002029
Eric Laurent994a6932013-07-17 11:51:42 -07002030 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002031 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002032
2033 if (out->card_status == CARD_STATUS_OFFLINE ||
2034 adev->card_status == CARD_STATUS_OFFLINE) {
2035 ALOGW("out->card_status or adev->card_status offline, try again");
2036 ret = -EAGAIN;
2037 goto error_config;
2038 }
2039
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002040 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2041 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002042 if (out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002043 a2dp_combo = true;
2044 } else {
2045 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2046 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2047 ret = -EAGAIN;
2048 goto error_config;
2049 }
2050 }
2051 }
2052 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002053 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002054 if (out->pcm_device_id < 0) {
2055 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2056 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002057 ret = -EINVAL;
2058 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002059 }
2060
2061 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
2062 uc_info->id = out->usecase;
2063 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002064 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002065 uc_info->devices = out->devices;
2066 uc_info->in_snd_device = SND_DEVICE_NONE;
2067 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002068
Eric Laurent07eeafd2013-10-06 12:52:49 -07002069 /* This must be called before adding this usecase to the list */
2070 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2071 check_and_set_hdmi_channels(adev, out->config.channels);
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002072 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
2073 check_and_set_usb_service_interval(adev, uc_info, true /*min*/);
2074 /* USB backend is not reopened immediately.
2075 This is eventually done as part of select_devices */
2076 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002077
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002078 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002079
Wei Wangf4837d52017-11-21 14:51:20 -08002080 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002081 audio_extn_perf_lock_acquire();
2082
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002083 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2084 (!audio_extn_a2dp_is_ready())) {
2085 if (!a2dp_combo) {
2086 check_a2dp_restore_l(adev, out, false);
2087 } else {
2088 audio_devices_t dev = out->devices;
juyuchen9baad392018-06-05 19:02:10 +08002089 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2090 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2091 else
2092 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002093 select_devices(adev, out->usecase);
2094 out->devices = dev;
2095 }
2096 } else {
2097 select_devices(adev, out->usecase);
2098 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002099
Eric Laurent0499d4f2014-08-25 22:39:29 -05002100 audio_extn_extspk_update(adev->extspk);
2101
Andy Hung31aca912014-03-20 17:14:59 -07002102 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002103 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002104 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2105 out->pcm = NULL;
2106 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
2107 COMPRESS_IN, &out->compr_config);
2108 if (out->compr && !is_compress_ready(out->compr)) {
2109 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2110 compress_close(out->compr);
2111 out->compr = NULL;
2112 ret = -EIO;
2113 goto error_open;
2114 }
2115 if (out->offload_callback)
2116 compress_nonblock(out->compr, out->non_blocking);
2117
2118 if (adev->visualizer_start_output != NULL)
2119 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2120 if (adev->offload_effects_start_output != NULL)
2121 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
2122 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002123 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002124 ALOGE("%s: pcm stream not ready", __func__);
2125 goto error_open;
2126 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002127 ret = pcm_start(out->pcm);
2128 if (ret < 0) {
2129 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2130 goto error_open;
2131 }
2132 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07002133 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002134 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002135
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002136 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2137 flags |= PCM_MMAP | PCM_NOIRQ;
2138 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002139 } else if (out->realtime) {
2140 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07002141 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002142
2143 while (1) {
2144 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2145 flags, &out->config);
2146 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2147 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2148 if (out->pcm != NULL) {
2149 pcm_close(out->pcm);
2150 out->pcm = NULL;
2151 }
2152 if (pcm_open_retry_count-- == 0) {
2153 ret = -EIO;
2154 goto error_open;
2155 }
2156 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2157 continue;
2158 }
2159 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002160 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002161 ALOGV("%s: pcm_prepare", __func__);
2162 if (pcm_is_ready(out->pcm)) {
2163 ret = pcm_prepare(out->pcm);
2164 if (ret < 0) {
2165 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2166 pcm_close(out->pcm);
2167 out->pcm = NULL;
2168 goto error_open;
2169 }
2170 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002171 if (out->realtime) {
2172 ret = pcm_start(out->pcm);
2173 if (ret < 0) {
2174 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
2175 pcm_close(out->pcm);
2176 out->pcm = NULL;
2177 goto error_open;
2178 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002179 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002180 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002181 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08002182 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002183 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002184 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07002185
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002186 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2187 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2188 audio_low_latency_hint_start();
2189 }
2190
vivek mehtae59cfb22017-06-16 15:57:11 -07002191 // consider a scenario where on pause lower layers are tear down.
2192 // so on resume, swap mixer control need to be sent only when
2193 // backend is active, hence rather than sending from enable device
2194 // sending it from start of streamtream
2195
2196 platform_set_swap_channels(adev, true);
2197
Eric Laurent994a6932013-07-17 11:51:42 -07002198 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002199 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002200error_open:
Wei Wangf4837d52017-11-21 14:51:20 -08002201 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002202 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002203 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002204error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002205 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002206}
2207
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002208static int check_input_parameters(uint32_t sample_rate,
2209 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07002210 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002211{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002212 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2213 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002214 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2215 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002216 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2217 return -EINVAL;
2218 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002219
Eric Laurent74b55762017-07-09 17:04:53 -07002220 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2221 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002222 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002223 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002224 return -EINVAL;
2225 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002226
2227 switch (sample_rate) {
2228 case 8000:
2229 case 11025:
2230 case 12000:
2231 case 16000:
2232 case 22050:
2233 case 24000:
2234 case 32000:
2235 case 44100:
2236 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002237 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002238 break;
2239 default:
vivek mehtadae44712015-07-27 14:13:18 -07002240 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002241 return -EINVAL;
2242 }
2243
2244 return 0;
2245}
2246
Kevin Rocarda325aa22018-04-03 09:15:52 -07002247/** Add a value in a list if not already present.
2248 * @return true if value was successfully inserted or already present,
2249 * false if the list is full and does not contain the value.
2250 */
2251static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
2252 for (size_t i = 0; i < list_length; i++) {
2253 if (list[i] == value) return true; // value is already present
2254 if (list[i] == 0) { // no values in this slot
2255 list[i] = value;
2256 return true; // value inserted
2257 }
2258 }
2259 return false; // could not insert value
2260}
2261
2262/** Add channel_mask in supported_channel_masks if not already present.
2263 * @return true if channel_mask was successfully inserted or already present,
2264 * false if supported_channel_masks is full and does not contain channel_mask.
2265 */
2266static void register_channel_mask(audio_channel_mask_t channel_mask,
2267 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
2268 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
2269 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
2270}
2271
2272/** Add format in supported_formats if not already present.
2273 * @return true if format was successfully inserted or already present,
2274 * false if supported_formats is full and does not contain format.
2275 */
2276static void register_format(audio_format_t format,
2277 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
2278 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
2279 "%s: stream can not declare supporting its format %x", __func__, format);
2280}
2281/** Add sample_rate in supported_sample_rates if not already present.
2282 * @return true if sample_rate was successfully inserted or already present,
2283 * false if supported_sample_rates is full and does not contain sample_rate.
2284 */
2285static void register_sample_rate(uint32_t sample_rate,
2286 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
2287 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
2288 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
2289}
2290
vivek mehtaa68fea62017-06-08 19:04:02 -07002291static size_t get_stream_buffer_size(size_t duration_ms,
2292 uint32_t sample_rate,
2293 audio_format_t format,
2294 int channel_count,
2295 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002296{
2297 size_t size = 0;
2298
vivek mehtaa68fea62017-06-08 19:04:02 -07002299 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002300 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002301 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002302
2303 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002304
Glenn Kasten4f993392014-05-14 07:30:48 -07002305 /* make sure the size is multiple of 32 bytes
2306 * At 48 kHz mono 16-bit PCM:
2307 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2308 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2309 */
2310 size += 0x1f;
2311 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002312
2313 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002314}
2315
2316static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2317{
2318 struct stream_out *out = (struct stream_out *)stream;
2319
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002320 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002321}
2322
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002323static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002324{
2325 return -ENOSYS;
2326}
2327
2328static size_t out_get_buffer_size(const struct audio_stream *stream)
2329{
2330 struct stream_out *out = (struct stream_out *)stream;
2331
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002332 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2333 return out->compr_config.fragment_size;
2334 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002335 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002336 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002337}
2338
2339static uint32_t out_get_channels(const struct audio_stream *stream)
2340{
2341 struct stream_out *out = (struct stream_out *)stream;
2342
2343 return out->channel_mask;
2344}
2345
2346static audio_format_t out_get_format(const struct audio_stream *stream)
2347{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002348 struct stream_out *out = (struct stream_out *)stream;
2349
2350 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002351}
2352
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002353static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002354{
2355 return -ENOSYS;
2356}
2357
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002358/* must be called with out->lock locked */
2359static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002360{
2361 struct stream_out *out = (struct stream_out *)stream;
2362 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002363 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002364
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002365 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002366 if (adev->adm_deregister_stream)
2367 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002368 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002369 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002370 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2371 if (out->pcm) {
2372 pcm_close(out->pcm);
2373 out->pcm = NULL;
2374 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002375 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002376 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002377 out->playback_started = false;
2378 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002379 } else {
2380 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002381 out->gapless_mdata.encoder_delay = 0;
2382 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002383 if (out->compr != NULL) {
2384 compress_close(out->compr);
2385 out->compr = NULL;
2386 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002387 }
Phil Burkbc991042017-02-24 08:06:44 -08002388 if (do_stop) {
2389 stop_output_stream(out);
2390 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002391 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002392 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002393 return 0;
2394}
2395
2396static int out_standby(struct audio_stream *stream)
2397{
2398 struct stream_out *out = (struct stream_out *)stream;
2399
2400 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2401 out->usecase, use_case_table[out->usecase]);
2402
2403 lock_output_stream(out);
2404 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002405 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002406 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002407 return 0;
2408}
2409
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002410static int out_on_error(struct audio_stream *stream)
2411{
2412 struct stream_out *out = (struct stream_out *)stream;
2413 struct audio_device *adev = out->dev;
2414 bool do_standby = false;
2415
2416 lock_output_stream(out);
2417 if (!out->standby) {
2418 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2419 stop_compressed_output_l(out);
2420 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2421 } else
2422 do_standby = true;
2423 }
2424 pthread_mutex_unlock(&out->lock);
2425
2426 if (do_standby)
2427 return out_standby(&out->stream.common);
2428
2429 return 0;
2430}
2431
Andy Hung7401c7c2016-09-21 12:41:21 -07002432static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002433{
Andy Hung7401c7c2016-09-21 12:41:21 -07002434 struct stream_out *out = (struct stream_out *)stream;
2435
2436 // We try to get the lock for consistency,
2437 // but it isn't necessary for these variables.
2438 // If we're not in standby, we may be blocked on a write.
2439 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2440 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2441 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2442
2443 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002444 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002445 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002446
2447 // dump error info
2448 (void)error_log_dump(
2449 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002450
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002451 return 0;
2452}
2453
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002454static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2455{
2456 int ret = 0;
2457 char value[32];
2458 struct compr_gapless_mdata tmp_mdata;
2459
2460 if (!out || !parms) {
2461 return -EINVAL;
2462 }
2463
2464 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2465 if (ret >= 0) {
2466 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2467 } else {
2468 return -EINVAL;
2469 }
2470
2471 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2472 if (ret >= 0) {
2473 tmp_mdata.encoder_padding = atoi(value);
2474 } else {
2475 return -EINVAL;
2476 }
2477
2478 out->gapless_mdata = tmp_mdata;
2479 out->send_new_metadata = 1;
2480 ALOGV("%s new encoder delay %u and padding %u", __func__,
2481 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2482
2483 return 0;
2484}
2485
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002486static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2487{
2488 return out == adev->primary_output || out == adev->voice_tx_output;
2489}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002490
Kevin Rocard1e02c882017-08-09 15:26:07 -07002491static int get_alive_usb_card(struct str_parms* parms) {
2492 int card;
2493 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2494 !audio_extn_usb_alive(card)) {
2495 return card;
2496 }
2497 return -ENODEV;
2498}
2499
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002500static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2501{
2502 struct stream_out *out = (struct stream_out *)stream;
2503 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002504 struct audio_usecase *usecase;
2505 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002506 struct str_parms *parms;
2507 char value[32];
2508 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002509 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002510 int status = 0;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002511 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002512
Eric Laurent2e140aa2016-06-30 17:14:46 -07002513 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002514 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002515 parms = str_parms_create_str(kvpairs);
2516 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2517 if (ret >= 0) {
2518 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002519
Eric Laurenta1478072015-09-21 17:21:52 -07002520 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002521
2522 // The usb driver needs to be closed after usb device disconnection
2523 // otherwise audio is no longer played on the new usb devices.
2524 // By forcing the stream in standby, the usb stack refcount drops to 0
2525 // and the driver is closed.
2526 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD && val == AUDIO_DEVICE_NONE &&
2527 audio_is_usb_out_device(out->devices)) {
2528 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2529 out_standby_l(&out->stream.common);
2530 }
2531
Eric Laurent150dbfe2013-02-27 14:31:02 -08002532 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002533
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002534 /*
2535 * When HDMI cable is unplugged the music playback is paused and
2536 * the policy manager sends routing=0. But the audioflinger
2537 * continues to write data until standby time (3sec).
2538 * As the HDMI core is turned off, the write gets blocked.
2539 * Avoid this by routing audio to speaker until standby.
2540 */
2541 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2542 val == AUDIO_DEVICE_NONE) {
2543 val = AUDIO_DEVICE_OUT_SPEAKER;
2544 }
2545
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002546 /*
2547 * When A2DP is disconnected the
2548 * music playback is paused and the policy manager sends routing=0
2549 * But the audioflingercontinues to write data until standby time
2550 * (3sec). As BT is turned off, the write gets blocked.
2551 * Avoid this by routing audio to speaker until standby.
2552 */
2553 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2554 (val == AUDIO_DEVICE_NONE) &&
2555 !audio_extn_a2dp_is_ready()) {
2556 val = AUDIO_DEVICE_OUT_SPEAKER;
2557 }
2558
2559 /* To avoid a2dp to sco overlapping / BT device improper state
2560 * check with BT lib about a2dp streaming support before routing
2561 */
2562 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2563 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002564 if (val & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002565 //combo usecase just by pass a2dp
2566 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2567 bypass_a2dp = true;
2568 } else {
2569 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2570 /* update device to a2dp and don't route as BT returned error
2571 * However it is still possible a2dp routing called because
2572 * of current active device disconnection (like wired headset)
2573 */
2574 out->devices = val;
2575 pthread_mutex_unlock(&out->lock);
2576 pthread_mutex_unlock(&adev->lock);
2577 status = -ENOSYS;
2578 goto routing_fail;
2579 }
2580 }
2581 }
2582
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002583 audio_devices_t new_dev = val;
2584
2585 // Workaround: If routing to an non existing usb device, fail gracefully
2586 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002587 int card;
2588 if (audio_is_usb_out_device(new_dev) &&
2589 (card = get_alive_usb_card(parms)) >= 0) {
2590
2591 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002592 pthread_mutex_unlock(&adev->lock);
2593 pthread_mutex_unlock(&out->lock);
2594 status = -ENOSYS;
2595 goto routing_fail;
2596 }
2597
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002598 /*
2599 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002600 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002601 * the select_devices(). But how do we undo this?
2602 *
2603 * For example, music playback is active on headset (deep-buffer usecase)
2604 * and if we go to ringtones and select a ringtone, low-latency usecase
2605 * will be started on headset+speaker. As we can't enable headset+speaker
2606 * and headset devices at the same time, select_devices() switches the music
2607 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2608 * So when the ringtone playback is completed, how do we undo the same?
2609 *
2610 * We are relying on the out_set_parameters() call on deep-buffer output,
2611 * once the ringtone playback is ended.
2612 * NOTE: We should not check if the current devices are same as new devices.
2613 * Because select_devices() must be called to switch back the music
2614 * playback to headset.
2615 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002616 if (new_dev != AUDIO_DEVICE_NONE) {
2617 bool same_dev = out->devices == new_dev;
2618 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002619
Eric Laurenta7657192014-10-09 21:09:33 -07002620 if (output_drives_call(adev, out)) {
Vignesh Kulothungana5c9da12017-11-10 11:41:24 -08002621 if (!voice_is_call_state_active(adev)) {
Eric Laurenta7657192014-10-09 21:09:33 -07002622 if (adev->mode == AUDIO_MODE_IN_CALL) {
2623 adev->current_call_output = out;
2624 ret = voice_start_call(adev);
2625 }
2626 } else {
2627 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002628 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002629 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002630 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002631
2632 if (!out->standby) {
2633 if (!same_dev) {
2634 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002635 // inform adm before actual routing to prevent glitches.
2636 if (adev->adm_on_routing_change) {
2637 adev->adm_on_routing_change(adev->adm_data,
2638 out->handle);
2639 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002640 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002641 if (!bypass_a2dp) {
2642 select_devices(adev, out->usecase);
2643 } else {
juyuchen9baad392018-06-05 19:02:10 +08002644 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2645 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2646 else
2647 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002648 select_devices(adev, out->usecase);
2649 out->devices = new_dev;
2650 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002651 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002652
2653 // on device switch force swap, lower functions will make sure
2654 // to check if swap is allowed or not.
2655
2656 if (!same_dev)
2657 platform_set_swap_channels(adev, true);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002658
2659 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2660 out->a2dp_compress_mute &&
2661 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
2662 pthread_mutex_lock(&out->compr_mute_lock);
2663 out->a2dp_compress_mute = false;
2664 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
2665 pthread_mutex_unlock(&out->compr_mute_lock);
2666 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002667 }
2668
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002669 }
2670
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002671 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002672 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002673
2674 /*handles device and call state changes*/
2675 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002676 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002677 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002678
2679 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2680 parse_compress_metadata(out, parms);
2681 }
2682
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002683 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002684 ALOGV("%s: exit: code(%d)", __func__, status);
2685 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002686}
2687
Haynes Mathew George569b7482017-05-08 14:44:27 -07002688static bool stream_get_parameter_channels(struct str_parms *query,
2689 struct str_parms *reply,
2690 audio_channel_mask_t *supported_channel_masks) {
2691 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002692 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002693 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002694 size_t i, j;
2695
2696 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2697 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002698 value[0] = '\0';
2699 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002700 while (supported_channel_masks[i] != 0) {
2701 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2702 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002703 if (!first) {
2704 strcat(value, "|");
2705 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002706 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002707 first = false;
2708 break;
2709 }
2710 }
2711 i++;
2712 }
2713 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002714 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002715 return ret >= 0;
2716}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002717
Haynes Mathew George569b7482017-05-08 14:44:27 -07002718static bool stream_get_parameter_formats(struct str_parms *query,
2719 struct str_parms *reply,
2720 audio_format_t *supported_formats) {
2721 int ret = -1;
2722 char value[256];
2723 int i;
2724
2725 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2726 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002727 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002728 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002729 case AUDIO_FORMAT_PCM_16_BIT:
2730 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2731 break;
2732 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2733 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2734 break;
2735 case AUDIO_FORMAT_PCM_32_BIT:
2736 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2737 break;
2738 default:
2739 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002740 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002741 break;
2742 }
2743 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002744 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002745 return ret >= 0;
2746}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002747
Haynes Mathew George569b7482017-05-08 14:44:27 -07002748static bool stream_get_parameter_rates(struct str_parms *query,
2749 struct str_parms *reply,
2750 uint32_t *supported_sample_rates) {
2751
2752 int i;
2753 char value[256];
2754 int ret = -1;
2755 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2756 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002757 value[0] = '\0';
2758 i=0;
2759 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002760 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002761 int avail = sizeof(value) - cursor;
2762 ret = snprintf(value + cursor, avail, "%s%d",
2763 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002764 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002765 if (ret < 0 || ret >= avail) {
2766 // if cursor is at the last element of the array
2767 // overwrite with \0 is duplicate work as
2768 // snprintf already put a \0 in place.
2769 // else
2770 // we had space to write the '|' at value[cursor]
2771 // (which will be overwritten) or no space to fill
2772 // the first element (=> cursor == 0)
2773 value[cursor] = '\0';
2774 break;
2775 }
2776 cursor += ret;
2777 ++i;
2778 }
2779 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2780 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002781 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002782 return ret >= 0;
2783}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002784
Haynes Mathew George569b7482017-05-08 14:44:27 -07002785static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2786{
2787 struct stream_out *out = (struct stream_out *)stream;
2788 struct str_parms *query = str_parms_create_str(keys);
2789 char *str;
2790 struct str_parms *reply = str_parms_create();
2791 bool replied = false;
2792 ALOGV("%s: enter: keys - %s", __func__, keys);
2793
2794 replied |= stream_get_parameter_channels(query, reply,
2795 &out->supported_channel_masks[0]);
2796 replied |= stream_get_parameter_formats(query, reply,
2797 &out->supported_formats[0]);
2798 replied |= stream_get_parameter_rates(query, reply,
2799 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002800 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002801 str = str_parms_to_str(reply);
2802 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002803 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002804 }
2805 str_parms_destroy(query);
2806 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002807 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002808 return str;
2809}
2810
2811static uint32_t out_get_latency(const struct audio_stream_out *stream)
2812{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002813 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002814 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002815 uint32_t latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002816
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002817 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2818 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002819 else if ((out->realtime) ||
2820 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002821 // since the buffer won't be filled up faster than realtime,
2822 // return a smaller number
2823 period_ms = (out->af_period_multiplier * out->config.period_size *
2824 1000) / (out->config.rate);
2825 hw_delay = platform_render_latency(out->usecase)/1000;
2826 return period_ms + hw_delay;
2827 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002828
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002829 latency = (out->config.period_count * out->config.period_size * 1000) /
2830 (out->config.rate);
2831
2832 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
2833 latency += audio_extn_a2dp_get_encoder_latency();
2834
2835 return latency;
2836}
2837
2838static int set_compr_volume(struct audio_stream_out *stream, float left,
2839 float right)
2840{
2841 struct stream_out *out = (struct stream_out *)stream;
2842 int volume[2];
2843 char mixer_ctl_name[128];
2844 struct audio_device *adev = out->dev;
2845 struct mixer_ctl *ctl;
2846 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2847 PCM_PLAYBACK);
2848
2849 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2850 "Compress Playback %d Volume", pcm_device_id);
2851 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2852 if (!ctl) {
2853 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2854 __func__, mixer_ctl_name);
2855 return -EINVAL;
2856 }
2857 ALOGV("%s: ctl for mixer cmd - %s, left %f, right %f",
2858 __func__, mixer_ctl_name, left, right);
2859 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2860 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2861 mixer_ctl_set_array(ctl, volume, sizeof(volume) / sizeof(volume[0]));
2862
2863 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002864}
2865
2866static int out_set_volume(struct audio_stream_out *stream, float left,
2867 float right)
2868{
Eric Laurenta9024de2013-04-04 09:19:12 -07002869 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002870 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002871
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002872 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002873 /* only take left channel into account: the API is for stereo anyway */
2874 out->muted = (left == 0.0f);
2875 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002876 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002877 pthread_mutex_lock(&out->compr_mute_lock);
2878 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
2879 if (!out->a2dp_compress_mute)
2880 ret = set_compr_volume(stream, left, right);
2881 out->volume_l = left;
2882 out->volume_r = right;
2883 pthread_mutex_unlock(&out->compr_mute_lock);
2884 return ret;
vivek mehtaa68fea62017-06-08 19:04:02 -07002885 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002886 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2887 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2888 if (!out->standby) {
2889 // if in standby, cached volume will be sent after stream is opened
2890 audio_extn_utils_send_app_type_gain(out->dev,
2891 out->app_type_cfg.app_type,
2892 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002893 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002894 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002895 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002896
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002897 return -ENOSYS;
2898}
2899
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002900// note: this call is safe only if the stream_cb is
2901// removed first in close_output_stream (as is done now).
2902static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2903{
2904 if (!stream || !parms)
2905 return;
2906
2907 struct stream_out *out = (struct stream_out *)stream;
2908 struct audio_device *adev = out->dev;
2909
2910 card_status_t status;
2911 int card;
2912 if (parse_snd_card_status(parms, &card, &status) < 0)
2913 return;
2914
2915 pthread_mutex_lock(&adev->lock);
2916 bool valid_cb = (card == adev->snd_card);
2917 pthread_mutex_unlock(&adev->lock);
2918
2919 if (!valid_cb)
2920 return;
2921
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002922 lock_output_stream(out);
2923 if (out->card_status != status)
2924 out->card_status = status;
2925 pthread_mutex_unlock(&out->lock);
2926
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002927 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2928 use_case_table[out->usecase],
2929 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2930
2931 if (status == CARD_STATUS_OFFLINE)
2932 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002933
2934 return;
2935}
2936
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002937#ifdef NO_AUDIO_OUT
2938static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002939 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002940{
2941 struct stream_out *out = (struct stream_out *)stream;
2942
2943 /* No Output device supported other than BT for playback.
2944 * Sleep for the amount of buffer duration
2945 */
Eric Laurenta1478072015-09-21 17:21:52 -07002946 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002947 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2948 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002949 out_get_sample_rate(&out->stream.common));
2950 pthread_mutex_unlock(&out->lock);
2951 return bytes;
2952}
2953#endif
2954
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002955static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2956 size_t bytes)
2957{
2958 struct stream_out *out = (struct stream_out *)stream;
2959 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002960 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002961 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002962
Eric Laurenta1478072015-09-21 17:21:52 -07002963 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002964 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07002965 const size_t frame_size = audio_stream_out_frame_size(stream);
2966 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002967
Eric Laurent0e46adf2016-12-16 12:49:24 -08002968 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2969 error_code = ERROR_CODE_WRITE;
2970 goto exit;
2971 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002972
2973 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2974 (audio_extn_a2dp_is_suspended())) {
juyuchen9baad392018-06-05 19:02:10 +08002975 if (!(out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002976 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2977 ret = -EIO;
2978 goto exit;
2979 }
2980 }
2981 }
2982
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002983 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002984 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002985 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002986 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07002987
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002988 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002989 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002990 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07002991 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002992 goto exit;
2993 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002994
vivek mehta40125092017-08-21 18:48:51 -07002995 // after standby always force set last known cal step
2996 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
2997 ALOGD("%s: retry previous failed cal level set", __func__);
2998 send_gain_dep_calibration_l();
2999 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003000 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003001
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003002 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003003 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003004 if (out->send_new_metadata) {
3005 ALOGVV("send new gapless metadata");
3006 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3007 out->send_new_metadata = 0;
3008 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003009 unsigned int avail;
3010 struct timespec tstamp;
3011 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
3012 /* Do not limit write size if the available frames count is unknown */
3013 if (ret != 0) {
3014 avail = bytes;
3015 }
3016 if (avail == 0) {
3017 ret = 0;
3018 } else {
3019 if (avail > bytes) {
3020 avail = bytes;
3021 }
3022 ret = compress_write(out->compr, buffer, avail);
3023 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
3024 __func__, avail, ret);
3025 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003026
Eric Laurent6e895242013-09-05 16:10:57 -07003027 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003028 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
3029 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003030 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003031 compress_start(out->compr);
3032 out->playback_started = 1;
3033 out->offload_state = OFFLOAD_STATE_PLAYING;
3034 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003035 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07003036 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07003037 } else {
3038 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07003039 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003040 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07003041 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003042 return ret;
3043 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07003044 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003045 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003046 size_t bytes_to_write = bytes;
3047
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003048 if (out->muted)
3049 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07003050 // FIXME: this can be removed once audio flinger mixer supports mono output
Nadav Bar3d72cfc2018-01-07 12:19:24 +02003051 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP || out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003052 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3053 int16_t *src = (int16_t *)buffer;
3054 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003055
Eric Laurentad2dde92017-09-20 18:27:31 -07003056 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
3057 out->format != AUDIO_FORMAT_PCM_16_BIT,
3058 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003059
Eric Laurentad2dde92017-09-20 18:27:31 -07003060 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
3061 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
3062 }
3063 bytes_to_write /= 2;
3064 }
3065 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes_to_write);
3066
Glenn Kasten5a59dff2018-02-22 08:05:35 -08003067 long ns = (frames * (int64_t) NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003068 request_out_focus(out, ns);
3069
3070 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3071 if (use_mmap)
Eric Laurentad2dde92017-09-20 18:27:31 -07003072 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003073 else
Eric Laurentad2dde92017-09-20 18:27:31 -07003074 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003075
Haynes Mathew George03c40102016-01-29 17:57:48 -08003076 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07003077 } else {
3078 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003079 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003080 }
3081
3082exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07003083 // For PCM we always consume the buffer and return #bytes regardless of ret.
3084 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003085 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07003086 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003087 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07003088
Andy Hung7401c7c2016-09-21 12:41:21 -07003089 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07003090 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07003091 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3092 ALOGE_IF(out->pcm != NULL,
3093 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07003094 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003095 // usleep not guaranteed for values over 1 second but we don't limit here.
3096 }
3097 }
Andy Hungda9b56b2016-09-16 20:06:35 -07003098
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003099 pthread_mutex_unlock(&out->lock);
3100
3101 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07003102 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003103 if (sleeptime_us != 0)
3104 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003105 }
3106 return bytes;
3107}
3108
3109static int out_get_render_position(const struct audio_stream_out *stream,
3110 uint32_t *dsp_frames)
3111{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003112 struct stream_out *out = (struct stream_out *)stream;
3113 *dsp_frames = 0;
3114 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07003115 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003116 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003117 unsigned long frames = 0;
3118 // TODO: check return value
3119 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
3120 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003121 ALOGVV("%s rendered frames %d sample_rate %d",
3122 __func__, *dsp_frames, out->sample_rate);
3123 }
3124 pthread_mutex_unlock(&out->lock);
3125 return 0;
3126 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003127 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003128}
3129
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003130static int out_add_audio_effect(const struct audio_stream *stream __unused,
3131 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003132{
3133 return 0;
3134}
3135
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003136static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3137 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003138{
3139 return 0;
3140}
3141
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003142static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3143 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003144{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003145 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003146}
3147
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003148static int out_get_presentation_position(const struct audio_stream_out *stream,
3149 uint64_t *frames, struct timespec *timestamp)
3150{
3151 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003152 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07003153 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003154
Eric Laurenta1478072015-09-21 17:21:52 -07003155 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003156
Eric Laurent949a0892013-09-20 09:20:13 -07003157 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3158 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003159 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07003160 compress_get_tstamp(out->compr, &dsp_frames,
3161 &out->sample_rate);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003162 // Adjustment accounts for A2DP encoder latency with offload usecases
3163 // Note: Encoder latency is returned in ms.
3164 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3165 unsigned long offset =
3166 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3167 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
3168 }
Eric Laurent949a0892013-09-20 09:20:13 -07003169 ALOGVV("%s rendered frames %ld sample_rate %d",
3170 __func__, dsp_frames, out->sample_rate);
3171 *frames = dsp_frames;
3172 ret = 0;
3173 /* this is the best we can do */
3174 clock_gettime(CLOCK_MONOTONIC, timestamp);
3175 }
3176 } else {
3177 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07003178 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003179 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3180 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003181 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003182 // This adjustment accounts for buffering after app processor.
3183 // It is based on estimated DSP latency per use case, rather than exact.
3184 signed_frames -=
3185 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3186
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003187 // Adjustment accounts for A2DP encoder latency with non-offload usecases
3188 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3189 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3190 signed_frames -=
3191 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3192 }
3193
Eric Laurent949a0892013-09-20 09:20:13 -07003194 // It would be unusual for this value to be negative, but check just in case ...
3195 if (signed_frames >= 0) {
3196 *frames = signed_frames;
3197 ret = 0;
3198 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003199 }
3200 }
3201 }
3202
3203 pthread_mutex_unlock(&out->lock);
3204
3205 return ret;
3206}
3207
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003208static int out_set_callback(struct audio_stream_out *stream,
3209 stream_callback_t callback, void *cookie)
3210{
3211 struct stream_out *out = (struct stream_out *)stream;
3212
3213 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003214 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003215 out->offload_callback = callback;
3216 out->offload_cookie = cookie;
3217 pthread_mutex_unlock(&out->lock);
3218 return 0;
3219}
3220
3221static int out_pause(struct audio_stream_out* stream)
3222{
3223 struct stream_out *out = (struct stream_out *)stream;
3224 int status = -ENOSYS;
3225 ALOGV("%s", __func__);
3226 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003227 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003228 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
3229 status = compress_pause(out->compr);
3230 out->offload_state = OFFLOAD_STATE_PAUSED;
3231 }
3232 pthread_mutex_unlock(&out->lock);
3233 }
3234 return status;
3235}
3236
3237static int out_resume(struct audio_stream_out* stream)
3238{
3239 struct stream_out *out = (struct stream_out *)stream;
3240 int status = -ENOSYS;
3241 ALOGV("%s", __func__);
3242 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3243 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07003244 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003245 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
3246 status = compress_resume(out->compr);
3247 out->offload_state = OFFLOAD_STATE_PLAYING;
3248 }
3249 pthread_mutex_unlock(&out->lock);
3250 }
3251 return status;
3252}
3253
3254static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3255{
3256 struct stream_out *out = (struct stream_out *)stream;
3257 int status = -ENOSYS;
3258 ALOGV("%s", __func__);
3259 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003260 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003261 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3262 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3263 else
3264 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3265 pthread_mutex_unlock(&out->lock);
3266 }
3267 return status;
3268}
3269
3270static int out_flush(struct audio_stream_out* stream)
3271{
3272 struct stream_out *out = (struct stream_out *)stream;
3273 ALOGV("%s", __func__);
3274 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003275 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003276 stop_compressed_output_l(out);
3277 pthread_mutex_unlock(&out->lock);
3278 return 0;
3279 }
3280 return -ENOSYS;
3281}
3282
Eric Laurent0e46adf2016-12-16 12:49:24 -08003283static int out_stop(const struct audio_stream_out* stream)
3284{
3285 struct stream_out *out = (struct stream_out *)stream;
3286 struct audio_device *adev = out->dev;
3287 int ret = -ENOSYS;
3288
3289 ALOGV("%s", __func__);
3290 pthread_mutex_lock(&adev->lock);
3291 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3292 out->playback_started && out->pcm != NULL) {
3293 pcm_stop(out->pcm);
3294 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08003295 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003296 }
3297 pthread_mutex_unlock(&adev->lock);
3298 return ret;
3299}
3300
3301static int out_start(const struct audio_stream_out* stream)
3302{
3303 struct stream_out *out = (struct stream_out *)stream;
3304 struct audio_device *adev = out->dev;
3305 int ret = -ENOSYS;
3306
3307 ALOGV("%s", __func__);
3308 pthread_mutex_lock(&adev->lock);
3309 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3310 !out->playback_started && out->pcm != NULL) {
3311 ret = start_output_stream(out);
3312 if (ret == 0) {
3313 out->playback_started = true;
3314 }
3315 }
3316 pthread_mutex_unlock(&adev->lock);
3317 return ret;
3318}
3319
Phil Burkbc991042017-02-24 08:06:44 -08003320/*
3321 * Modify config->period_count based on min_size_frames
3322 */
3323static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
3324{
3325 int periodCountRequested = (min_size_frames + config->period_size - 1)
3326 / config->period_size;
3327 int periodCount = MMAP_PERIOD_COUNT_MIN;
3328
3329 ALOGV("%s original config.period_size = %d config.period_count = %d",
3330 __func__, config->period_size, config->period_count);
3331
3332 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
3333 periodCount *= 2;
3334 }
3335 config->period_count = periodCount;
3336
3337 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
3338}
3339
Eric Laurent0e46adf2016-12-16 12:49:24 -08003340static int out_create_mmap_buffer(const struct audio_stream_out *stream,
3341 int32_t min_size_frames,
3342 struct audio_mmap_buffer_info *info)
3343{
3344 struct stream_out *out = (struct stream_out *)stream;
3345 struct audio_device *adev = out->dev;
3346 int ret = 0;
3347 unsigned int offset1;
3348 unsigned int frames1;
3349 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003350 uint32_t mmap_size;
3351 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003352
3353 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003354 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003355 pthread_mutex_lock(&adev->lock);
3356
3357 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003358 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003359 ret = -EINVAL;
3360 goto exit;
3361 }
3362 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003363 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003364 ret = -ENOSYS;
3365 goto exit;
3366 }
3367 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3368 if (out->pcm_device_id < 0) {
3369 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3370 __func__, out->pcm_device_id, out->usecase);
3371 ret = -EINVAL;
3372 goto exit;
3373 }
Phil Burkbc991042017-02-24 08:06:44 -08003374
3375 adjust_mmap_period_count(&out->config, min_size_frames);
3376
Eric Laurent0e46adf2016-12-16 12:49:24 -08003377 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3378 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3379 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3380 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3381 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3382 step = "open";
3383 ret = -ENODEV;
3384 goto exit;
3385 }
3386 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3387 if (ret < 0) {
3388 step = "begin";
3389 goto exit;
3390 }
3391 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003392 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003393 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003394 ret = platform_get_mmap_data_fd(adev->platform,
3395 out->pcm_device_id, 0 /*playback*/,
3396 &info->shared_memory_fd,
3397 &mmap_size);
3398 if (ret < 0) {
3399 // Fall back to non exclusive mode
3400 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3401 } else {
3402 if (mmap_size < buffer_size) {
3403 step = "mmap";
3404 goto exit;
3405 }
3406 // FIXME: indicate exclusive mode support by returning a negative buffer size
3407 info->buffer_size_frames *= -1;
3408 }
3409 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003410
3411 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3412 if (ret < 0) {
3413 step = "commit";
3414 goto exit;
3415 }
Phil Burkbc991042017-02-24 08:06:44 -08003416
3417 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003418 ret = 0;
3419
3420 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3421 __func__, info->shared_memory_address, info->buffer_size_frames);
3422
3423exit:
3424 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003425 if (out->pcm == NULL) {
3426 ALOGE("%s: %s - %d", __func__, step, ret);
3427 } else {
3428 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003429 pcm_close(out->pcm);
3430 out->pcm = NULL;
3431 }
3432 }
3433 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003434 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003435 return ret;
3436}
3437
3438static int out_get_mmap_position(const struct audio_stream_out *stream,
3439 struct audio_mmap_position *position)
3440{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003441 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003442 struct stream_out *out = (struct stream_out *)stream;
3443 ALOGVV("%s", __func__);
3444 if (position == NULL) {
3445 return -EINVAL;
3446 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003447 lock_output_stream(out);
3448 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3449 out->pcm == NULL) {
3450 ret = -ENOSYS;
3451 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003452 }
3453
3454 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003455 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003456 if (ret < 0) {
3457 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003458 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003459 }
Andy Hungfc044e12017-03-20 09:24:22 -07003460 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003461exit:
3462 pthread_mutex_unlock(&out->lock);
3463 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003464}
3465
3466
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003467/** audio_stream_in implementation **/
3468static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3469{
3470 struct stream_in *in = (struct stream_in *)stream;
3471
3472 return in->config.rate;
3473}
3474
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003475static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003476{
3477 return -ENOSYS;
3478}
3479
3480static size_t in_get_buffer_size(const struct audio_stream *stream)
3481{
3482 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003483 return in->config.period_size * in->af_period_multiplier *
3484 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003485}
3486
3487static uint32_t in_get_channels(const struct audio_stream *stream)
3488{
3489 struct stream_in *in = (struct stream_in *)stream;
3490
3491 return in->channel_mask;
3492}
3493
vivek mehta4ed66e62016-04-15 23:33:34 -07003494static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003495{
vivek mehta4ed66e62016-04-15 23:33:34 -07003496 struct stream_in *in = (struct stream_in *)stream;
3497 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003498}
3499
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003500static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003501{
3502 return -ENOSYS;
3503}
3504
3505static int in_standby(struct audio_stream *stream)
3506{
3507 struct stream_in *in = (struct stream_in *)stream;
3508 struct audio_device *adev = in->dev;
3509 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003510 bool do_stop = true;
3511
Eric Laurent994a6932013-07-17 11:51:42 -07003512 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003513
3514 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003515
3516 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003517 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003518 audio_extn_sound_trigger_stop_lab(in);
3519 in->standby = true;
3520 }
3521
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003522 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003523 if (adev->adm_deregister_stream)
3524 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3525
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003526 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003527 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003528 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003529 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003530 in->capture_started = false;
3531 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003532 if (in->pcm) {
3533 pcm_close(in->pcm);
3534 in->pcm = NULL;
3535 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003536 adev->enable_voicerx = false;
3537 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003538 if (do_stop) {
3539 status = stop_input_stream(in);
3540 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003541 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003542 }
3543 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003544 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003545 return status;
3546}
3547
Andy Hungd13f0d32017-06-12 13:58:37 -07003548static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003549{
Andy Hungd13f0d32017-06-12 13:58:37 -07003550 struct stream_in *in = (struct stream_in *)stream;
3551
3552 // We try to get the lock for consistency,
3553 // but it isn't necessary for these variables.
3554 // If we're not in standby, we may be blocked on a read.
3555 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3556 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3557 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3558 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3559
3560 if (locked) {
3561 pthread_mutex_unlock(&in->lock);
3562 }
3563
3564 // dump error info
3565 (void)error_log_dump(
3566 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003567 return 0;
3568}
3569
3570static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3571{
3572 struct stream_in *in = (struct stream_in *)stream;
3573 struct audio_device *adev = in->dev;
3574 struct str_parms *parms;
3575 char *str;
3576 char value[32];
3577 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003578 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003579
Eric Laurent994a6932013-07-17 11:51:42 -07003580 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003581 parms = str_parms_create_str(kvpairs);
3582
3583 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3584
Eric Laurenta1478072015-09-21 17:21:52 -07003585 lock_input_stream(in);
3586
Eric Laurent150dbfe2013-02-27 14:31:02 -08003587 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003588 if (ret >= 0) {
3589 val = atoi(value);
3590 /* no audio source uses val == 0 */
3591 if ((in->source != val) && (val != 0)) {
3592 in->source = val;
3593 }
3594 }
3595
3596 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003597
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003598 if (ret >= 0) {
3599 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003600 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003601
3602 // Workaround: If routing to an non existing usb device, fail gracefully
3603 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003604 int card;
3605 if (audio_is_usb_in_device(val) &&
3606 (card = get_alive_usb_card(parms)) >= 0) {
3607
3608 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003609 status = -ENOSYS;
3610 } else {
3611
3612 in->device = val;
3613 /* If recording is in progress, change the tx device to new device */
3614 if (!in->standby) {
3615 ALOGV("update input routing change");
3616 // inform adm before actual routing to prevent glitches.
3617 if (adev->adm_on_routing_change) {
3618 adev->adm_on_routing_change(adev->adm_data,
3619 in->capture_handle);
3620 }
3621 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003622 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003623 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003624 }
3625 }
3626
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003627 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003628 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003629
3630 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003631 ALOGV("%s: exit: status(%d)", __func__, status);
3632 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003633}
3634
Haynes Mathew George569b7482017-05-08 14:44:27 -07003635static char* in_get_parameters(const struct audio_stream *stream,
3636 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003637{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003638 struct stream_in *in = (struct stream_in *)stream;
3639 struct str_parms *query = str_parms_create_str(keys);
3640 char *str;
3641 struct str_parms *reply = str_parms_create();
3642 bool replied = false;
3643
3644 ALOGV("%s: enter: keys - %s", __func__, keys);
3645 replied |= stream_get_parameter_channels(query, reply,
3646 &in->supported_channel_masks[0]);
3647 replied |= stream_get_parameter_formats(query, reply,
3648 &in->supported_formats[0]);
3649 replied |= stream_get_parameter_rates(query, reply,
3650 &in->supported_sample_rates[0]);
3651 if (replied) {
3652 str = str_parms_to_str(reply);
3653 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003654 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003655 }
3656 str_parms_destroy(query);
3657 str_parms_destroy(reply);
3658 ALOGV("%s: exit: returns - %s", __func__, str);
3659 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003660}
3661
Eric Laurent51f3c662018-04-10 18:21:34 -07003662static int in_set_gain(struct audio_stream_in *stream, float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003663{
Eric Laurent51f3c662018-04-10 18:21:34 -07003664 struct stream_in *in = (struct stream_in *)stream;
3665 char mixer_ctl_name[128];
3666 struct mixer_ctl *ctl;
3667 int ctl_value;
3668
3669 ALOGV("%s: gain %f", __func__, gain);
3670
3671 if (stream == NULL)
3672 return -EINVAL;
3673
3674 /* in_set_gain() only used to silence MMAP capture for now */
3675 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
3676 return -ENOSYS;
3677
3678 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
3679
3680 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
3681 if (!ctl) {
3682 ALOGW("%s: Could not get ctl for mixer cmd - %s",
3683 __func__, mixer_ctl_name);
3684 return -ENOSYS;
3685 }
3686
3687 if (gain < RECORD_GAIN_MIN)
3688 gain = RECORD_GAIN_MIN;
3689 else if (gain > RECORD_GAIN_MAX)
3690 gain = RECORD_GAIN_MAX;
3691 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
3692
3693 mixer_ctl_set_value(ctl, 0, ctl_value);
3694 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003695}
3696
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003697static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3698{
3699 if (!stream || !parms)
3700 return;
3701
3702 struct stream_in *in = (struct stream_in *)stream;
3703 struct audio_device *adev = in->dev;
3704
3705 card_status_t status;
3706 int card;
3707 if (parse_snd_card_status(parms, &card, &status) < 0)
3708 return;
3709
3710 pthread_mutex_lock(&adev->lock);
3711 bool valid_cb = (card == adev->snd_card);
3712 pthread_mutex_unlock(&adev->lock);
3713
3714 if (!valid_cb)
3715 return;
3716
3717 lock_input_stream(in);
3718 if (in->card_status != status)
3719 in->card_status = status;
3720 pthread_mutex_unlock(&in->lock);
3721
3722 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3723 use_case_table[in->usecase],
3724 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3725
3726 // a better solution would be to report error back to AF and let
3727 // it put the stream to standby
3728 if (status == CARD_STATUS_OFFLINE)
3729 in_standby(&in->stream.common);
3730
3731 return;
3732}
3733
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003734static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3735 size_t bytes)
3736{
3737 struct stream_in *in = (struct stream_in *)stream;
3738 struct audio_device *adev = in->dev;
3739 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003740 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003741 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003742
Eric Laurenta1478072015-09-21 17:21:52 -07003743 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003744 const size_t frame_size = audio_stream_in_frame_size(stream);
3745 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003746
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003747 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003748 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003749 /* Read from sound trigger HAL */
3750 audio_extn_sound_trigger_read(in, buffer, bytes);
3751 pthread_mutex_unlock(&in->lock);
3752 return bytes;
3753 }
3754
Eric Laurent0e46adf2016-12-16 12:49:24 -08003755 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3756 ret = -ENOSYS;
3757 goto exit;
3758 }
3759
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003760 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003761 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003762 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003763 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003764 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003765 goto exit;
3766 }
3767 in->standby = 0;
3768 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003769
Andy Hungd13f0d32017-06-12 13:58:37 -07003770 // errors that occur here are read errors.
3771 error_code = ERROR_CODE_READ;
3772
Haynes Mathew George03c40102016-01-29 17:57:48 -08003773 //what's the duration requested by the client?
3774 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3775 in->config.rate;
3776 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003777
Haynes Mathew George03c40102016-01-29 17:57:48 -08003778 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003779 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003780 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003781 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003782 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003783 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003784 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003785 if (ret < 0) {
3786 ALOGE("Failed to read w/err %s", strerror(errno));
3787 ret = -errno;
3788 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003789 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3790 if (bytes % 4 == 0) {
3791 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3792 int_buf_stream = buffer;
3793 for (size_t itt=0; itt < bytes/4 ; itt++) {
3794 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003795 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003796 } else {
3797 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3798 ret = -EINVAL;
3799 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003800 }
3801 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003802 }
3803
Haynes Mathew George03c40102016-01-29 17:57:48 -08003804 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003805
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003806 /*
3807 * Instead of writing zeroes here, we could trust the hardware
3808 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003809 * 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 -08003810 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08003811 if (ret == 0 && adev->mic_muted &&
3812 !voice_is_in_call_rec_stream(in) &&
3813 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003814 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07003815 in->frames_muted += frames;
3816 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003817
3818exit:
3819 pthread_mutex_unlock(&in->lock);
3820
3821 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07003822 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003823 in_standby(&in->stream.common);
3824 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003825 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003826 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07003827 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08003828 }
3829 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003830 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003831 }
3832 return bytes;
3833}
3834
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003835static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003836{
3837 return 0;
3838}
3839
Andy Hung6ebe5962016-01-15 17:46:57 -08003840static int in_get_capture_position(const struct audio_stream_in *stream,
3841 int64_t *frames, int64_t *time)
3842{
3843 if (stream == NULL || frames == NULL || time == NULL) {
3844 return -EINVAL;
3845 }
3846 struct stream_in *in = (struct stream_in *)stream;
3847 int ret = -ENOSYS;
3848
3849 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003850 // note: ST sessions do not close the alsa pcm driver synchronously
3851 // on standby. Therefore, we may return an error even though the
3852 // pcm stream is still opened.
3853 if (in->standby) {
3854 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
3855 "%s stream in standby but pcm not NULL for non ST session", __func__);
3856 goto exit;
3857 }
Andy Hung6ebe5962016-01-15 17:46:57 -08003858 if (in->pcm) {
3859 struct timespec timestamp;
3860 unsigned int avail;
3861 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3862 *frames = in->frames_read + avail;
3863 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3864 ret = 0;
3865 }
3866 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003867exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08003868 pthread_mutex_unlock(&in->lock);
3869 return ret;
3870}
3871
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003872static int add_remove_audio_effect(const struct audio_stream *stream,
3873 effect_handle_t effect,
3874 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003875{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003876 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003877 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003878 int status = 0;
3879 effect_descriptor_t desc;
3880
3881 status = (*effect)->get_descriptor(effect, &desc);
3882 if (status != 0)
3883 return status;
3884
Eric Laurenta1478072015-09-21 17:21:52 -07003885 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003886 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003887 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003888 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003889 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003890 in->enable_aec != enable &&
3891 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3892 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003893 if (!enable)
3894 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003895 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3896 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3897 adev->enable_voicerx = enable;
3898 struct audio_usecase *usecase;
3899 struct listnode *node;
3900 list_for_each(node, &adev->usecase_list) {
3901 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07003902 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07003903 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05003904 }
3905 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003906 if (!in->standby)
3907 select_devices(in->dev, in->usecase);
3908 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003909 if (in->enable_ns != enable &&
3910 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3911 in->enable_ns = enable;
3912 if (!in->standby)
3913 select_devices(in->dev, in->usecase);
3914 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003915 pthread_mutex_unlock(&in->dev->lock);
3916 pthread_mutex_unlock(&in->lock);
3917
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003918 return 0;
3919}
3920
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003921static int in_add_audio_effect(const struct audio_stream *stream,
3922 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003923{
Eric Laurent994a6932013-07-17 11:51:42 -07003924 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003925 return add_remove_audio_effect(stream, effect, true);
3926}
3927
3928static int in_remove_audio_effect(const struct audio_stream *stream,
3929 effect_handle_t effect)
3930{
Eric Laurent994a6932013-07-17 11:51:42 -07003931 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003932 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003933}
3934
Eric Laurent0e46adf2016-12-16 12:49:24 -08003935static int in_stop(const struct audio_stream_in* stream)
3936{
3937 struct stream_in *in = (struct stream_in *)stream;
3938 struct audio_device *adev = in->dev;
3939
3940 int ret = -ENOSYS;
3941 ALOGV("%s", __func__);
3942 pthread_mutex_lock(&adev->lock);
3943 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3944 in->capture_started && in->pcm != NULL) {
3945 pcm_stop(in->pcm);
3946 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003947 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003948 }
3949 pthread_mutex_unlock(&adev->lock);
3950 return ret;
3951}
3952
3953static int in_start(const struct audio_stream_in* stream)
3954{
3955 struct stream_in *in = (struct stream_in *)stream;
3956 struct audio_device *adev = in->dev;
3957 int ret = -ENOSYS;
3958
3959 ALOGV("%s in %p", __func__, in);
3960 pthread_mutex_lock(&adev->lock);
3961 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3962 !in->capture_started && in->pcm != NULL) {
3963 if (!in->capture_started) {
3964 ret = start_input_stream(in);
3965 if (ret == 0) {
3966 in->capture_started = true;
3967 }
3968 }
3969 }
3970 pthread_mutex_unlock(&adev->lock);
3971 return ret;
3972}
3973
3974static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3975 int32_t min_size_frames,
3976 struct audio_mmap_buffer_info *info)
3977{
3978 struct stream_in *in = (struct stream_in *)stream;
3979 struct audio_device *adev = in->dev;
3980 int ret = 0;
3981 unsigned int offset1;
3982 unsigned int frames1;
3983 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003984 uint32_t mmap_size;
3985 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003986
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003987 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003988 pthread_mutex_lock(&adev->lock);
3989 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003990
Eric Laurent0e46adf2016-12-16 12:49:24 -08003991 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003992 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003993 ret = -EINVAL;
3994 goto exit;
3995 }
3996 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003997 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003998 ALOGV("%s in %p", __func__, in);
3999 ret = -ENOSYS;
4000 goto exit;
4001 }
4002 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
4003 if (in->pcm_device_id < 0) {
4004 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4005 __func__, in->pcm_device_id, in->usecase);
4006 ret = -EINVAL;
4007 goto exit;
4008 }
Phil Burkbc991042017-02-24 08:06:44 -08004009
4010 adjust_mmap_period_count(&in->config, min_size_frames);
4011
Eric Laurent0e46adf2016-12-16 12:49:24 -08004012 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4013 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
4014 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
4015 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
4016 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
4017 step = "open";
4018 ret = -ENODEV;
4019 goto exit;
4020 }
4021
4022 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
4023 if (ret < 0) {
4024 step = "begin";
4025 goto exit;
4026 }
4027 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07004028 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004029 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07004030 ret = platform_get_mmap_data_fd(adev->platform,
4031 in->pcm_device_id, 1 /*capture*/,
4032 &info->shared_memory_fd,
4033 &mmap_size);
4034 if (ret < 0) {
4035 // Fall back to non exclusive mode
4036 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
4037 } else {
4038 if (mmap_size < buffer_size) {
4039 step = "mmap";
4040 goto exit;
4041 }
4042 // FIXME: indicate exclusive mode support by returning a negative buffer size
4043 info->buffer_size_frames *= -1;
4044 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08004045
Haynes Mathew George96483a22017-03-28 14:52:47 -07004046 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004047
4048 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4049 if (ret < 0) {
4050 step = "commit";
4051 goto exit;
4052 }
4053
Phil Burkbc991042017-02-24 08:06:44 -08004054 in->standby = false;
4055 ret = 0;
4056
Eric Laurent0e46adf2016-12-16 12:49:24 -08004057 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4058 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004059
4060exit:
4061 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004062 if (in->pcm == NULL) {
4063 ALOGE("%s: %s - %d", __func__, step, ret);
4064 } else {
4065 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08004066 pcm_close(in->pcm);
4067 in->pcm = NULL;
4068 }
4069 }
4070 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004071 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004072 return ret;
4073}
4074
4075static int in_get_mmap_position(const struct audio_stream_in *stream,
4076 struct audio_mmap_position *position)
4077{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004078 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004079 struct stream_in *in = (struct stream_in *)stream;
4080 ALOGVV("%s", __func__);
4081 if (position == NULL) {
4082 return -EINVAL;
4083 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004084 lock_input_stream(in);
4085 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
4086 in->pcm == NULL) {
4087 ret = -ENOSYS;
4088 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004089 }
4090 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004091 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004092 if (ret < 0) {
4093 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004094 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004095 }
Andy Hungfc044e12017-03-20 09:24:22 -07004096 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004097exit:
4098 pthread_mutex_unlock(&in->lock);
4099 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004100}
4101
jiabin8962a4d2018-03-19 18:21:24 -07004102static int in_get_active_microphones(const struct audio_stream_in *stream,
4103 struct audio_microphone_characteristic_t *mic_array,
4104 size_t *mic_count) {
4105 struct stream_in *in = (struct stream_in *)stream;
4106 struct audio_device *adev = in->dev;
4107 ALOGVV("%s", __func__);
4108
4109 lock_input_stream(in);
4110 pthread_mutex_lock(&adev->lock);
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004111 int ret = platform_get_active_microphones(adev->platform,
jiabin8962a4d2018-03-19 18:21:24 -07004112 audio_channel_count_from_in_mask(in->channel_mask),
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004113 in->usecase, mic_array, mic_count);
jiabin8962a4d2018-03-19 18:21:24 -07004114 pthread_mutex_unlock(&adev->lock);
4115 pthread_mutex_unlock(&in->lock);
4116
4117 return ret;
4118}
4119
4120static int adev_get_microphones(const struct audio_hw_device *dev,
4121 struct audio_microphone_characteristic_t *mic_array,
4122 size_t *mic_count) {
4123 struct audio_device *adev = (struct audio_device *)dev;
4124 ALOGVV("%s", __func__);
4125
4126 pthread_mutex_lock(&adev->lock);
4127 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
4128 pthread_mutex_unlock(&adev->lock);
4129
4130 return ret;
4131}
Eric Laurent0e46adf2016-12-16 12:49:24 -08004132
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004133static int adev_open_output_stream(struct audio_hw_device *dev,
4134 audio_io_handle_t handle,
4135 audio_devices_t devices,
4136 audio_output_flags_t flags,
4137 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07004138 struct audio_stream_out **stream_out,
4139 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004140{
4141 struct audio_device *adev = (struct audio_device *)dev;
4142 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004143 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004144 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
4145 bool is_usb_dev = audio_is_usb_out_device(devices) &&
4146 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004147
Andy Hungd9653bd2017-08-01 19:31:39 -07004148 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
4149 return -ENOSYS;
4150 }
4151
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004152 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
4153 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004154 *stream_out = NULL;
4155 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4156
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004157 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
4158
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004159 if (devices == AUDIO_DEVICE_NONE)
4160 devices = AUDIO_DEVICE_OUT_SPEAKER;
4161
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004162 out->flags = flags;
4163 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004164 out->dev = adev;
Eric Laurentc4aef752013-09-12 17:45:53 -07004165 out->handle = handle;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004166 out->a2dp_compress_mute = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004167
4168 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004169 if ((is_hdmi || is_usb_dev) &&
4170 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
4171 (flags == AUDIO_OUTPUT_FLAG_NONE ||
4172 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Eric Laurentab805ee2018-03-30 12:20:38 -07004173 audio_format_t req_format = config->format;
4174 audio_channel_mask_t req_channel_mask = config->channel_mask;
4175 uint32_t req_sample_rate = config->sample_rate;
4176
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004177 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004178 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004179 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004180 if (config->sample_rate == 0)
4181 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Eric Laurentab805ee2018-03-30 12:20:38 -07004182 if (config->channel_mask == AUDIO_CHANNEL_NONE)
Haynes Mathew George569b7482017-05-08 14:44:27 -07004183 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
4184 if (config->format == AUDIO_FORMAT_DEFAULT)
4185 config->format = AUDIO_FORMAT_PCM_16_BIT;
4186 } else if (is_usb_dev) {
4187 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
4188 &config->format,
4189 &out->supported_formats[0],
4190 MAX_SUPPORTED_FORMATS,
4191 &config->channel_mask,
4192 &out->supported_channel_masks[0],
4193 MAX_SUPPORTED_CHANNEL_MASKS,
4194 &config->sample_rate,
4195 &out->supported_sample_rates[0],
4196 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004197 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004198 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004199 pthread_mutex_unlock(&adev->lock);
Eric Laurentab805ee2018-03-30 12:20:38 -07004200 if (ret != 0) {
4201 // For MMAP NO IRQ, allow conversions in ADSP
4202 if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
4203 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004204
Eric Laurentab805ee2018-03-30 12:20:38 -07004205 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
4206 config->sample_rate = req_sample_rate;
4207 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
4208 config->channel_mask = req_channel_mask;
4209 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
4210 config->format = req_format;
4211 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004212
Haynes Mathew George569b7482017-05-08 14:44:27 -07004213 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004214 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004215 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004216 if (is_hdmi) {
4217 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4218 out->config = pcm_config_hdmi_multi;
4219 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
4220 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4221 out->config = pcm_config_mmap_playback;
4222 out->stream.start = out_start;
4223 out->stream.stop = out_stop;
4224 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4225 out->stream.get_mmap_position = out_get_mmap_position;
4226 } else {
4227 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4228 out->config = pcm_config_hifi;
4229 }
4230
4231 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004232 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004233 if (is_hdmi) {
4234 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
4235 audio_bytes_per_sample(out->format));
4236 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004237 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004238 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07004239 pthread_mutex_lock(&adev->lock);
4240 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4241 pthread_mutex_unlock(&adev->lock);
4242
4243 // reject offload during card offline to allow
4244 // fallback to s/w paths
4245 if (offline) {
4246 ret = -ENODEV;
4247 goto error_open;
4248 }
4249
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004250 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4251 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4252 ALOGE("%s: Unsupported Offload information", __func__);
4253 ret = -EINVAL;
4254 goto error_open;
4255 }
4256 if (!is_supported_format(config->offload_info.format)) {
4257 ALOGE("%s: Unsupported audio format", __func__);
4258 ret = -EINVAL;
4259 goto error_open;
4260 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004261 out->sample_rate = config->offload_info.sample_rate;
4262 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
4263 out->channel_mask = config->offload_info.channel_mask;
4264 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
4265 out->channel_mask = config->channel_mask;
4266 else
4267 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4268
4269 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004270
4271 out->compr_config.codec = (struct snd_codec *)
4272 calloc(1, sizeof(struct snd_codec));
4273
4274 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004275
4276 out->stream.set_callback = out_set_callback;
4277 out->stream.pause = out_pause;
4278 out->stream.resume = out_resume;
4279 out->stream.drain = out_drain;
4280 out->stream.flush = out_flush;
4281
4282 out->compr_config.codec->id =
4283 get_snd_codec_id(config->offload_info.format);
4284 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
4285 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004286 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004287 out->compr_config.codec->bit_rate =
4288 config->offload_info.bit_rate;
4289 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004290 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004291 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
4292
4293 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4294 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004295
4296 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004297 create_offload_callback_thread(out);
4298 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4299 __func__, config->offload_info.version,
4300 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02004301 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4302 switch (config->sample_rate) {
4303 case 0:
4304 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4305 break;
4306 case 8000:
4307 case 16000:
4308 case 48000:
4309 out->sample_rate = config->sample_rate;
4310 break;
4311 default:
4312 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
4313 config->sample_rate);
4314 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4315 ret = -EINVAL;
4316 goto error_open;
4317 }
4318 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4319 switch (config->channel_mask) {
4320 case AUDIO_CHANNEL_NONE:
4321 case AUDIO_CHANNEL_OUT_STEREO:
4322 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4323 break;
4324 default:
4325 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
4326 config->channel_mask);
4327 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4328 ret = -EINVAL;
4329 goto error_open;
4330 }
4331 switch (config->format) {
4332 case AUDIO_FORMAT_DEFAULT:
4333 case AUDIO_FORMAT_PCM_16_BIT:
4334 out->format = AUDIO_FORMAT_PCM_16_BIT;
4335 break;
4336 default:
4337 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
4338 config->format);
4339 config->format = AUDIO_FORMAT_PCM_16_BIT;
4340 ret = -EINVAL;
4341 goto error_open;
4342 }
4343
4344 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004345 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004346 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004347 case 0:
4348 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
4349 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07004350 case 8000:
4351 case 16000:
4352 case 48000:
4353 out->sample_rate = config->sample_rate;
4354 break;
4355 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004356 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
4357 config->sample_rate);
4358 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4359 ret = -EINVAL;
4360 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004361 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004362 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4363 switch (config->channel_mask) {
4364 case AUDIO_CHANNEL_NONE:
4365 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4366 break;
4367 case AUDIO_CHANNEL_OUT_STEREO:
4368 out->channel_mask = config->channel_mask;
4369 break;
4370 default:
4371 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
4372 config->channel_mask);
4373 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4374 ret = -EINVAL;
4375 break;
4376 }
4377 switch (config->format) {
4378 case AUDIO_FORMAT_DEFAULT:
4379 out->format = AUDIO_FORMAT_PCM_16_BIT;
4380 break;
4381 case AUDIO_FORMAT_PCM_16_BIT:
4382 out->format = config->format;
4383 break;
4384 default:
4385 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
4386 config->format);
4387 config->format = AUDIO_FORMAT_PCM_16_BIT;
4388 ret = -EINVAL;
4389 break;
4390 }
4391 if (ret != 0)
4392 goto error_open;
4393
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004394 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4395 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004396 out->config.rate = out->sample_rate;
4397 out->config.channels =
4398 audio_channel_count_from_out_mask(out->channel_mask);
4399 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004400 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004401 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
4402 switch (config->sample_rate) {
4403 case 0:
4404 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4405 break;
4406 case 8000:
4407 case 16000:
4408 case 32000:
4409 case 48000:
4410 out->sample_rate = config->sample_rate;
4411 break;
4412 default:
4413 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
4414 config->sample_rate);
4415 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4416 ret = -EINVAL;
4417 break;
4418 }
Eric Laurentad2dde92017-09-20 18:27:31 -07004419 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004420 switch (config->channel_mask) {
4421 case AUDIO_CHANNEL_NONE:
4422 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4423 break;
4424 case AUDIO_CHANNEL_OUT_STEREO:
4425 out->channel_mask = config->channel_mask;
4426 break;
4427 default:
4428 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
4429 config->channel_mask);
4430 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4431 ret = -EINVAL;
4432 break;
4433 }
4434 switch (config->format) {
4435 case AUDIO_FORMAT_DEFAULT:
4436 out->format = AUDIO_FORMAT_PCM_16_BIT;
4437 break;
4438 case AUDIO_FORMAT_PCM_16_BIT:
4439 out->format = config->format;
4440 break;
4441 default:
4442 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
4443 config->format);
4444 config->format = AUDIO_FORMAT_PCM_16_BIT;
4445 ret = -EINVAL;
4446 break;
4447 }
4448 if (ret != 0)
4449 goto error_open;
4450
vivek mehtaa68fea62017-06-08 19:04:02 -07004451 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07004452 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4453 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004454 out->config.rate = out->sample_rate;
4455 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07004456 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004457 out->sample_rate,
4458 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07004459 out->config.channels,
4460 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004461 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07004462 out->config.period_size = buffer_size / frame_size;
4463 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
4464 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004465 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004466 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07004467 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4468 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004469 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07004470 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
4471 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004472 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07004473 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004474 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004475 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004476 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004477 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4478 out->config = pcm_config_mmap_playback;
4479 out->stream.start = out_start;
4480 out->stream.stop = out_stop;
4481 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4482 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004483 } else {
4484 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4485 out->config = pcm_config_low_latency;
4486 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004487
4488 if (config->sample_rate == 0) {
4489 out->sample_rate = out->config.rate;
4490 } else {
4491 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004492 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004493 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
4494 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
4495 } else {
4496 out->channel_mask = config->channel_mask;
4497 }
4498 if (config->format == AUDIO_FORMAT_DEFAULT)
4499 out->format = audio_format_from_pcm_format(out->config.format);
4500 else if (!audio_is_linear_pcm(config->format)) {
4501 config->format = AUDIO_FORMAT_PCM_16_BIT;
4502 ret = -EINVAL;
4503 goto error_open;
4504 } else {
4505 out->format = config->format;
4506 }
4507
4508 out->config.rate = out->sample_rate;
4509 out->config.channels =
4510 audio_channel_count_from_out_mask(out->channel_mask);
4511 if (out->format != audio_format_from_pcm_format(out->config.format)) {
4512 out->config.format = pcm_format_from_audio_format(out->format);
4513 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004514 }
Kevin Rocard50eff892017-05-02 16:52:05 -07004515
4516 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
4517 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004518 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004519 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
4520 __func__, config->sample_rate, config->format, config->channel_mask);
4521 config->sample_rate = out->sample_rate;
4522 config->format = out->format;
4523 config->channel_mask = out->channel_mask;
4524 ret = -EINVAL;
4525 goto error_open;
4526 }
4527
Andy Hung6fcba9c2014-03-18 11:53:32 -07004528 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
4529 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004530
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004531 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004532 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004533 adev->primary_output = out;
4534 else {
4535 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004536 ret = -EEXIST;
4537 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004538 }
4539 }
4540
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004541 /* Check if this usecase is already existing */
4542 pthread_mutex_lock(&adev->lock);
4543 if (get_usecase_from_list(adev, out->usecase) != NULL) {
4544 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004545 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004546 ret = -EEXIST;
4547 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004548 }
4549 pthread_mutex_unlock(&adev->lock);
4550
4551 out->stream.common.get_sample_rate = out_get_sample_rate;
4552 out->stream.common.set_sample_rate = out_set_sample_rate;
4553 out->stream.common.get_buffer_size = out_get_buffer_size;
4554 out->stream.common.get_channels = out_get_channels;
4555 out->stream.common.get_format = out_get_format;
4556 out->stream.common.set_format = out_set_format;
4557 out->stream.common.standby = out_standby;
4558 out->stream.common.dump = out_dump;
4559 out->stream.common.set_parameters = out_set_parameters;
4560 out->stream.common.get_parameters = out_get_parameters;
4561 out->stream.common.add_audio_effect = out_add_audio_effect;
4562 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4563 out->stream.get_latency = out_get_latency;
4564 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004565#ifdef NO_AUDIO_OUT
4566 out->stream.write = out_write_for_no_output;
4567#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004568 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004569#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004570 out->stream.get_render_position = out_get_render_position;
4571 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004572 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004573
Eric Laurent0e46adf2016-12-16 12:49:24 -08004574 if (out->realtime)
4575 out->af_period_multiplier = af_period_multiplier;
4576 else
4577 out->af_period_multiplier = 1;
4578
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004579 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004580 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004581 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004582
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004583 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004584 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004585 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4586
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004587 config->format = out->stream.common.get_format(&out->stream.common);
4588 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4589 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4590
Kevin Rocarda325aa22018-04-03 09:15:52 -07004591 register_format(out->format, out->supported_formats);
4592 register_channel_mask(out->channel_mask, out->supported_channel_masks);
4593 register_sample_rate(out->sample_rate, out->supported_sample_rates);
4594
Andy Hunga452b0a2017-03-15 14:51:15 -07004595 out->error_log = error_log_create(
4596 ERROR_LOG_ENTRIES,
4597 1000000000 /* aggregate consecutive identical errors within one second in ns */);
4598
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004599 /*
4600 By locking output stream before registering, we allow the callback
4601 to update stream's state only after stream's initial state is set to
4602 adev state.
4603 */
4604 lock_output_stream(out);
4605 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4606 pthread_mutex_lock(&adev->lock);
4607 out->card_status = adev->card_status;
4608 pthread_mutex_unlock(&adev->lock);
4609 pthread_mutex_unlock(&out->lock);
4610
vivek mehta4a824772017-06-08 19:05:49 -07004611 stream_app_type_cfg_init(&out->app_type_cfg);
4612
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004613 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004614
Eric Laurent994a6932013-07-17 11:51:42 -07004615 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004616 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004617
4618error_open:
4619 free(out);
4620 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07004621 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004622 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004623}
4624
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004625static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004626 struct audio_stream_out *stream)
4627{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004628 struct stream_out *out = (struct stream_out *)stream;
4629 struct audio_device *adev = out->dev;
4630
Eric Laurent994a6932013-07-17 11:51:42 -07004631 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004632
4633 // must deregister from sndmonitor first to prevent races
4634 // between the callback and close_stream
4635 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004636 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004637 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
4638 destroy_offload_callback_thread(out);
4639
4640 if (out->compr_config.codec != NULL)
4641 free(out->compr_config.codec);
4642 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004643
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004644 out->a2dp_compress_mute = false;
4645
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004646 if (adev->voice_tx_output == out)
4647 adev->voice_tx_output = NULL;
4648
Andy Hunga452b0a2017-03-15 14:51:15 -07004649 error_log_destroy(out->error_log);
4650 out->error_log = NULL;
4651
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004652 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004653 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004654 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004655 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004656 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004657}
4658
4659static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4660{
4661 struct audio_device *adev = (struct audio_device *)dev;
4662 struct str_parms *parms;
4663 char *str;
4664 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004665 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004666 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07004667 int status = 0;
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004668 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004669
Joe Onorato188b6222016-03-01 11:02:27 -08004670 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004671
4672 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004673
4674 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004675 status = voice_set_parameters(adev, parms);
4676 if (status != 0) {
4677 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004678 }
4679
4680 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4681 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07004682 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004683 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4684 adev->bluetooth_nrec = true;
4685 else
4686 adev->bluetooth_nrec = false;
4687 }
4688
4689 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4690 if (ret >= 0) {
4691 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4692 adev->screen_off = false;
4693 else
4694 adev->screen_off = true;
4695 }
4696
jasmine cha270b7762018-03-30 15:41:33 +08004697#ifndef MAXXAUDIO_QDSP_ENABLED
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004698 ret = str_parms_get_int(parms, "rotation", &val);
4699 if (ret >= 0) {
4700 bool reverse_speakers = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004701 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004702 // FIXME: note that the code below assumes that the speakers are in the correct placement
4703 // relative to the user when the device is rotated 90deg from its default rotation. This
4704 // assumption is device-specific, not platform-specific like this code.
4705 case 270:
4706 reverse_speakers = true;
4707 break;
4708 case 0:
4709 case 90:
4710 case 180:
4711 break;
4712 default:
4713 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07004714 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004715 }
Eric Laurent03f09432014-03-25 18:09:11 -07004716 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004717 // check and set swap
4718 // - check if orientation changed and speaker active
4719 // - set rotation and cache the rotation value
4720 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004721 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004722 }
jasmine cha270b7762018-03-30 15:41:33 +08004723#endif
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004724
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004725 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4726 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004727 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004728 }
4729
David Linee3fe402017-03-13 10:00:42 -07004730 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4731 if (ret >= 0) {
4732 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004733 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004734 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4735 if (ret >= 0) {
4736 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004737 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004738 }
Eric Laurent99dab492017-06-17 15:19:08 -07004739 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004740 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4741 if (ret >= 0) {
4742 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004743 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004744 }
4745 }
4746 }
4747
4748 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4749 if (ret >= 0) {
4750 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004751 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004752 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4753 if (ret >= 0) {
4754 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004755 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004756 }
Eric Laurent99dab492017-06-17 15:19:08 -07004757 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004758 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4759 if (ret >= 0) {
4760 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004761 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004762 }
4763 }
4764 }
4765
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004766 audio_extn_hfp_set_parameters(adev, parms);
jasmine cha270b7762018-03-30 15:41:33 +08004767 audio_extn_ma_set_parameters(adev, parms);
4768
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004769 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
4770 if (status >= 0 && a2dp_reconfig) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004771 struct audio_usecase *usecase;
4772 struct listnode *node;
4773 list_for_each(node, &adev->usecase_list) {
4774 usecase = node_to_item(node, struct audio_usecase, list);
4775 if ((usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004776 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004777 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
4778
4779 pthread_mutex_unlock(&adev->lock);
4780 lock_output_stream(usecase->stream.out);
4781 pthread_mutex_lock(&adev->lock);
4782 audio_extn_a2dp_set_handoff_mode(true);
4783 // force device switch to reconfigure encoder
4784 select_devices(adev, usecase->id);
4785 audio_extn_a2dp_set_handoff_mode(false);
4786 pthread_mutex_unlock(&usecase->stream.out->lock);
4787 break;
4788 }
4789 }
4790 }
4791
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004792done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004793 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004794 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004795 ALOGV("%s: exit with code(%d)", __func__, status);
4796 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004797}
4798
4799static char* adev_get_parameters(const struct audio_hw_device *dev,
4800 const char *keys)
4801{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004802 struct audio_device *adev = (struct audio_device *)dev;
4803 struct str_parms *reply = str_parms_create();
4804 struct str_parms *query = str_parms_create_str(keys);
4805 char *str;
4806
4807 pthread_mutex_lock(&adev->lock);
4808
4809 voice_get_parameters(adev, query, reply);
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004810 audio_extn_a2dp_get_parameters(query, reply);
4811
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004812 str = str_parms_to_str(reply);
4813 str_parms_destroy(query);
4814 str_parms_destroy(reply);
4815
4816 pthread_mutex_unlock(&adev->lock);
4817 ALOGV("%s: exit: returns - %s", __func__, str);
4818 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004819}
4820
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004821static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004822{
4823 return 0;
4824}
4825
Haynes Mathew George5191a852013-09-11 14:19:36 -07004826static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4827{
4828 int ret;
4829 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004830
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004831 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4832
Haynes Mathew George5191a852013-09-11 14:19:36 -07004833 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004834 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004835 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004836
Haynes Mathew George5191a852013-09-11 14:19:36 -07004837 return ret;
4838}
4839
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004840static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004841{
4842 return -ENOSYS;
4843}
4844
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004845static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4846 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004847{
4848 return -ENOSYS;
4849}
4850
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004851static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004852{
4853 return -ENOSYS;
4854}
4855
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004856static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004857{
4858 return -ENOSYS;
4859}
4860
4861static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4862{
4863 struct audio_device *adev = (struct audio_device *)dev;
4864
4865 pthread_mutex_lock(&adev->lock);
4866 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004867 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004868 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004869 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4870 voice_is_in_call(adev)) {
4871 voice_stop_call(adev);
4872 adev->current_call_output = NULL;
4873 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004874 }
4875 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004876
4877 audio_extn_extspk_set_mode(adev->extspk, mode);
4878
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004879 return 0;
4880}
4881
4882static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4883{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004884 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004885 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004886
Eric Laurent2bafff12016-03-17 12:17:23 -07004887 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004888 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004889 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4890 ret = audio_extn_hfp_set_mic_mute(adev, state);
4891 } else {
4892 ret = voice_set_mic_mute(adev, state);
4893 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004894 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004895 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004896
4897 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004898}
4899
4900static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4901{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004902 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004903 return 0;
4904}
4905
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004906static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004907 const struct audio_config *config)
4908{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004909 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004910
Eric Laurent74b55762017-07-09 17:04:53 -07004911 /* Don't know if USB HIFI in this context so use true to be conservative */
4912 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4913 true /*is_usb_hifi */) != 0)
4914 return 0;
4915
vivek mehtaa68fea62017-06-08 19:04:02 -07004916 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4917 config->sample_rate, config->format,
4918 channel_count,
4919 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004920}
4921
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004922static bool adev_input_allow_hifi_record(struct audio_device *adev,
4923 audio_devices_t devices,
4924 audio_input_flags_t flags,
4925 audio_source_t source) {
4926 const bool allowed = true;
4927
4928 if (!audio_is_usb_in_device(devices))
4929 return !allowed;
4930
4931 switch (flags) {
4932 case AUDIO_INPUT_FLAG_NONE:
4933 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4934 break;
4935 default:
4936 return !allowed;
4937 }
4938
4939 switch (source) {
4940 case AUDIO_SOURCE_DEFAULT:
4941 case AUDIO_SOURCE_MIC:
4942 case AUDIO_SOURCE_UNPROCESSED:
4943 break;
4944 default:
4945 return !allowed;
4946 }
4947
4948 switch (adev->mode) {
4949 case 0:
4950 break;
4951 default:
4952 return !allowed;
4953 }
4954
4955 return allowed;
4956}
4957
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004958static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004959 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004960 audio_devices_t devices,
4961 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004962 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004963 audio_input_flags_t flags,
4964 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004965 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004966{
4967 struct audio_device *adev = (struct audio_device *)dev;
4968 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004969 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004970 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004971 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004972 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004973 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4974 devices,
4975 flags,
4976 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004977 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004978 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004979
Andy Hungd9653bd2017-08-01 19:31:39 -07004980 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
4981 return -ENOSYS;
4982 }
4983
Eric Laurent74b55762017-07-09 17:04:53 -07004984 if (!(is_usb_dev && may_use_hifi_record)) {
4985 if (config->sample_rate == 0)
4986 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4987 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4988 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4989 if (config->format == AUDIO_FORMAT_DEFAULT)
4990 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004991
Eric Laurent74b55762017-07-09 17:04:53 -07004992 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
4993
4994 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
4995 return -EINVAL;
4996 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004997
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004998 if (audio_extn_tfa_98xx_is_supported() &&
4999 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005000 return -EINVAL;
5001
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005002 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
5003
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005004 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005005 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005006
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005007 in->stream.common.get_sample_rate = in_get_sample_rate;
5008 in->stream.common.set_sample_rate = in_set_sample_rate;
5009 in->stream.common.get_buffer_size = in_get_buffer_size;
5010 in->stream.common.get_channels = in_get_channels;
5011 in->stream.common.get_format = in_get_format;
5012 in->stream.common.set_format = in_set_format;
5013 in->stream.common.standby = in_standby;
5014 in->stream.common.dump = in_dump;
5015 in->stream.common.set_parameters = in_set_parameters;
5016 in->stream.common.get_parameters = in_get_parameters;
5017 in->stream.common.add_audio_effect = in_add_audio_effect;
5018 in->stream.common.remove_audio_effect = in_remove_audio_effect;
5019 in->stream.set_gain = in_set_gain;
5020 in->stream.read = in_read;
5021 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08005022 in->stream.get_capture_position = in_get_capture_position;
jiabin8962a4d2018-03-19 18:21:24 -07005023 in->stream.get_active_microphones = in_get_active_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005024
5025 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005026 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005027 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005028 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005029 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005030 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005031
Arun Mirpuriba2749a2018-04-17 14:32:24 -07005032 ALOGV("%s: source = %d, config->channel_mask = %d", __func__, source, config->channel_mask);
5033 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
5034 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
5035 /* Force channel config requested to mono if incall
5036 record is being requested for only uplink/downlink */
5037 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
5038 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5039 ret = -EINVAL;
5040 goto err_open;
5041 }
5042 }
5043
Haynes Mathew George569b7482017-05-08 14:44:27 -07005044 if (is_usb_dev && may_use_hifi_record) {
5045 /* HiFi record selects an appropriate format, channel, rate combo
5046 depending on sink capabilities*/
5047 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
5048 &config->format,
5049 &in->supported_formats[0],
5050 MAX_SUPPORTED_FORMATS,
5051 &config->channel_mask,
5052 &in->supported_channel_masks[0],
5053 MAX_SUPPORTED_CHANNEL_MASKS,
5054 &config->sample_rate,
5055 &in->supported_sample_rates[0],
5056 MAX_SUPPORTED_SAMPLE_RATES);
5057 if (ret != 0) {
5058 ret = -EINVAL;
5059 goto err_open;
5060 }
Eric Laurent74b55762017-07-09 17:04:53 -07005061 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005062 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07005063 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07005064 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
5065 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
5066 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5067 bool ret_error = false;
5068 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5069 from HAL is 8_24
5070 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5071 8_24 return error indicating supported format is 8_24
5072 *> In case of any other source requesting 24 bit or float return error
5073 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07005074
vivek mehta57ff9b52016-04-28 14:13:08 -07005075 on error flinger will retry with supported format passed
5076 */
5077 if (source != AUDIO_SOURCE_UNPROCESSED) {
5078 config->format = AUDIO_FORMAT_PCM_16_BIT;
5079 ret_error = true;
5080 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
5081 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
5082 ret_error = true;
5083 }
5084
5085 if (ret_error) {
5086 ret = -EINVAL;
5087 goto err_open;
5088 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005089 }
5090
vivek mehta57ff9b52016-04-28 14:13:08 -07005091 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07005092 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07005093
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005094 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005095 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
5096 if (config->sample_rate == 0)
5097 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5098 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5099 config->sample_rate != 8000) {
5100 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5101 ret = -EINVAL;
5102 goto err_open;
5103 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005104
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005105 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5106 config->format = AUDIO_FORMAT_PCM_16_BIT;
5107 ret = -EINVAL;
5108 goto err_open;
5109 }
5110
5111 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5112 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07005113 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005114 } else if (is_usb_dev && may_use_hifi_record) {
5115 in->usecase = USECASE_AUDIO_RECORD_HIFI;
5116 in->config = pcm_config_audio_capture;
5117 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005118 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5119 config->sample_rate,
5120 config->format,
5121 channel_count,
5122 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005123 in->config.period_size = buffer_size / frame_size;
5124 in->config.rate = config->sample_rate;
5125 in->af_period_multiplier = 1;
5126 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005127 } else {
5128 in->usecase = USECASE_AUDIO_RECORD;
5129 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08005130 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005131 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07005132#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005133 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07005134#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08005135 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005136 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08005137 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005138 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005139 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5140 config->sample_rate,
5141 config->format,
5142 channel_count,
5143 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005144 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005145 in->config.rate = config->sample_rate;
5146 in->af_period_multiplier = 1;
5147 } else {
5148 // period size is left untouched for rt mode playback
5149 in->config = pcm_config_audio_capture_rt;
5150 in->af_period_multiplier = af_period_multiplier;
5151 }
5152 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
5153 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005154 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08005155 in->usecase = USECASE_AUDIO_RECORD_MMAP;
5156 in->config = pcm_config_mmap_capture;
5157 in->stream.start = in_start;
5158 in->stream.stop = in_stop;
5159 in->stream.create_mmap_buffer = in_create_mmap_buffer;
5160 in->stream.get_mmap_position = in_get_mmap_position;
5161 in->af_period_multiplier = 1;
5162 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07005163 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07005164 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07005165 (config->sample_rate == 8000 ||
5166 config->sample_rate == 16000 ||
5167 config->sample_rate == 32000 ||
5168 config->sample_rate == 48000) &&
5169 channel_count == 1) {
5170 in->usecase = USECASE_AUDIO_RECORD_VOIP;
5171 in->config = pcm_config_audio_capture;
5172 frame_size = audio_stream_in_frame_size(&in->stream);
5173 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
5174 config->sample_rate,
5175 config->format,
5176 channel_count, false /*is_low_latency*/);
5177 in->config.period_size = buffer_size / frame_size;
5178 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
5179 in->config.rate = config->sample_rate;
5180 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005181 } else {
5182 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005183 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005184 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5185 config->sample_rate,
5186 config->format,
5187 channel_count,
5188 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005189 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005190 in->config.rate = config->sample_rate;
5191 in->af_period_multiplier = 1;
5192 }
5193 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
5194 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005195 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08005196
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005197 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07005198 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005199
Kevin Rocarda325aa22018-04-03 09:15:52 -07005200
5201 register_format(in->format, in->supported_formats);
5202 register_channel_mask(in->channel_mask, in->supported_channel_masks);
5203 register_sample_rate(in->sample_rate, in->supported_sample_rates);
5204
Andy Hungd13f0d32017-06-12 13:58:37 -07005205 in->error_log = error_log_create(
5206 ERROR_LOG_ENTRIES,
5207 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
5208
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005209 /* This stream could be for sound trigger lab,
5210 get sound trigger pcm if present */
5211 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005212
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005213 lock_input_stream(in);
5214 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5215 pthread_mutex_lock(&adev->lock);
5216 in->card_status = adev->card_status;
5217 pthread_mutex_unlock(&adev->lock);
5218 pthread_mutex_unlock(&in->lock);
5219
vivek mehta4a824772017-06-08 19:05:49 -07005220 stream_app_type_cfg_init(&in->app_type_cfg);
5221
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005222 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005223 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005224 return 0;
5225
5226err_open:
5227 free(in);
5228 *stream_in = NULL;
5229 return ret;
5230}
5231
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005232static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005233 struct audio_stream_in *stream)
5234{
Andy Hungd13f0d32017-06-12 13:58:37 -07005235 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005236 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005237
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005238 // must deregister from sndmonitor first to prevent races
5239 // between the callback and close_stream
5240 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005241 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07005242
5243 error_log_destroy(in->error_log);
5244 in->error_log = NULL;
5245
Andy Hung0dbb52b2017-08-09 13:51:38 -07005246 pthread_mutex_destroy(&in->pre_lock);
5247 pthread_mutex_destroy(&in->lock);
5248
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005249 free(stream);
5250
5251 return;
5252}
5253
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005254static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005255{
5256 return 0;
5257}
5258
Andy Hung31aca912014-03-20 17:14:59 -07005259/* verifies input and output devices and their capabilities.
5260 *
5261 * This verification is required when enabling extended bit-depth or
5262 * sampling rates, as not all qcom products support it.
5263 *
5264 * Suitable for calling only on initialization such as adev_open().
5265 * It fills the audio_device use_case_table[] array.
5266 *
5267 * Has a side-effect that it needs to configure audio routing / devices
5268 * in order to power up the devices and read the device parameters.
5269 * It does not acquire any hw device lock. Should restore the devices
5270 * back to "normal state" upon completion.
5271 */
5272static int adev_verify_devices(struct audio_device *adev)
5273{
5274 /* enumeration is a bit difficult because one really wants to pull
5275 * the use_case, device id, etc from the hidden pcm_device_table[].
5276 * In this case there are the following use cases and device ids.
5277 *
5278 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
5279 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005280 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07005281 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
5282 * [USECASE_AUDIO_RECORD] = {0, 0},
5283 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
5284 * [USECASE_VOICE_CALL] = {2, 2},
5285 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005286 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07005287 * USECASE_VOICE_CALL omitted, but possible for either input or output.
5288 */
5289
5290 /* should be the usecases enabled in adev_open_input_stream() */
5291 static const int test_in_usecases[] = {
5292 USECASE_AUDIO_RECORD,
5293 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
5294 };
5295 /* should be the usecases enabled in adev_open_output_stream()*/
5296 static const int test_out_usecases[] = {
5297 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
5298 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
5299 };
5300 static const usecase_type_t usecase_type_by_dir[] = {
5301 PCM_PLAYBACK,
5302 PCM_CAPTURE,
5303 };
5304 static const unsigned flags_by_dir[] = {
5305 PCM_OUT,
5306 PCM_IN,
5307 };
5308
5309 size_t i;
5310 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005311 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07005312 char info[512]; /* for possible debug info */
5313
5314 for (dir = 0; dir < 2; ++dir) {
5315 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
5316 const unsigned flags_dir = flags_by_dir[dir];
5317 const size_t testsize =
5318 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
5319 const int *testcases =
5320 dir ? test_in_usecases : test_out_usecases;
5321 const audio_devices_t audio_device =
5322 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
5323
5324 for (i = 0; i < testsize; ++i) {
5325 const audio_usecase_t audio_usecase = testcases[i];
5326 int device_id;
5327 snd_device_t snd_device;
5328 struct pcm_params **pparams;
5329 struct stream_out out;
5330 struct stream_in in;
5331 struct audio_usecase uc_info;
5332 int retval;
5333
5334 pparams = &adev->use_case_table[audio_usecase];
5335 pcm_params_free(*pparams); /* can accept null input */
5336 *pparams = NULL;
5337
5338 /* find the device ID for the use case (signed, for error) */
5339 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
5340 if (device_id < 0)
5341 continue;
5342
5343 /* prepare structures for device probing */
5344 memset(&uc_info, 0, sizeof(uc_info));
5345 uc_info.id = audio_usecase;
5346 uc_info.type = usecase_type;
5347 if (dir) {
5348 adev->active_input = &in;
5349 memset(&in, 0, sizeof(in));
5350 in.device = audio_device;
5351 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
5352 uc_info.stream.in = &in;
5353 } else {
5354 adev->active_input = NULL;
5355 }
5356 memset(&out, 0, sizeof(out));
5357 out.devices = audio_device; /* only field needed in select_devices */
5358 uc_info.stream.out = &out;
5359 uc_info.devices = audio_device;
5360 uc_info.in_snd_device = SND_DEVICE_NONE;
5361 uc_info.out_snd_device = SND_DEVICE_NONE;
5362 list_add_tail(&adev->usecase_list, &uc_info.list);
5363
5364 /* select device - similar to start_(in/out)put_stream() */
5365 retval = select_devices(adev, audio_usecase);
5366 if (retval >= 0) {
5367 *pparams = pcm_params_get(card_id, device_id, flags_dir);
5368#if LOG_NDEBUG == 0
5369 if (*pparams) {
5370 ALOGV("%s: (%s) card %d device %d", __func__,
5371 dir ? "input" : "output", card_id, device_id);
5372 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07005373 } else {
5374 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
5375 }
5376#endif
5377 }
5378
5379 /* deselect device - similar to stop_(in/out)put_stream() */
5380 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07005381 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07005382 /* 2. Disable the rx device */
5383 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07005384 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07005385 list_remove(&uc_info.list);
5386 }
5387 }
5388 adev->active_input = NULL; /* restore adev state */
5389 return 0;
5390}
5391
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005392static int adev_close(hw_device_t *device)
5393{
Andy Hung31aca912014-03-20 17:14:59 -07005394 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005395 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005396
5397 if (!adev)
5398 return 0;
5399
5400 pthread_mutex_lock(&adev_init_lock);
5401
5402 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005403 audio_extn_snd_mon_unregister_listener(adev);
5404 audio_extn_tfa_98xx_deinit();
jasmine cha270b7762018-03-30 15:41:33 +08005405 audio_extn_ma_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005406 audio_route_free(adev->audio_route);
5407 free(adev->snd_dev_ref_cnt);
5408 platform_deinit(adev->platform);
5409 audio_extn_extspk_deinit(adev->extspk);
5410 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005411 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005412 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
5413 pcm_params_free(adev->use_case_table[i]);
5414 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005415 if (adev->adm_deinit)
5416 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005417 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005418 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07005419 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07005420
5421 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005422
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005423 return 0;
5424}
5425
Glenn Kasten4f993392014-05-14 07:30:48 -07005426/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5427 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5428 * just that it _might_ work.
5429 */
5430static int period_size_is_plausible_for_low_latency(int period_size)
5431{
5432 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005433 case 48:
5434 case 96:
5435 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07005436 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005437 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07005438 case 240:
5439 case 320:
5440 case 480:
5441 return 1;
5442 default:
5443 return 0;
5444 }
5445}
5446
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005447static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
5448{
5449 int card;
5450 card_status_t status;
5451
5452 if (!parms)
5453 return;
5454
5455 if (parse_snd_card_status(parms, &card, &status) < 0)
5456 return;
5457
5458 pthread_mutex_lock(&adev->lock);
5459 bool valid_cb = (card == adev->snd_card);
5460 if (valid_cb) {
5461 if (adev->card_status != status) {
5462 adev->card_status = status;
5463 platform_snd_card_update(adev->platform, status);
5464 }
5465 }
5466 pthread_mutex_unlock(&adev->lock);
5467 return;
5468}
5469
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005470/* out and adev lock held */
5471static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
5472{
5473 struct audio_usecase *uc_info;
5474 float left_p;
5475 float right_p;
5476 audio_devices_t devices;
5477
5478 uc_info = get_usecase_from_list(adev, out->usecase);
5479 if (uc_info == NULL) {
5480 ALOGE("%s: Could not find the usecase (%d) in the list",
5481 __func__, out->usecase);
5482 return -EINVAL;
5483 }
5484
5485 ALOGD("%s: enter: usecase(%d: %s)", __func__,
5486 out->usecase, use_case_table[out->usecase]);
5487
5488 if (restore) {
5489 // restore A2DP device for active usecases and unmute if required
5490 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
5491 !is_a2dp_device(uc_info->out_snd_device)) {
5492 ALOGD("%s: restoring A2DP and unmuting stream", __func__);
5493 select_devices(adev, uc_info->id);
5494 pthread_mutex_lock(&out->compr_mute_lock);
5495 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5496 (out->a2dp_compress_mute)) {
5497 out->a2dp_compress_mute = false;
5498 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5499 }
5500 pthread_mutex_unlock(&out->compr_mute_lock);
5501 }
5502 } else {
5503 // mute compress stream if suspended
5504 pthread_mutex_lock(&out->compr_mute_lock);
5505 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5506 (!out->a2dp_compress_mute)) {
5507 if (!out->standby) {
5508 ALOGD("%s: selecting speaker and muting stream", __func__);
5509 devices = out->devices;
5510 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
5511 left_p = out->volume_l;
5512 right_p = out->volume_r;
5513 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5514 compress_pause(out->compr);
5515 set_compr_volume(&out->stream, 0.0f, 0.0f);
5516 out->a2dp_compress_mute = true;
5517 select_devices(adev, out->usecase);
5518 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5519 compress_resume(out->compr);
5520 out->devices = devices;
5521 out->volume_l = left_p;
5522 out->volume_r = right_p;
5523 }
5524 }
5525 pthread_mutex_unlock(&out->compr_mute_lock);
5526 }
5527 ALOGV("%s: exit", __func__);
5528 return 0;
5529}
5530
5531int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
5532{
5533 int ret = 0;
5534
5535 lock_output_stream(out);
5536 pthread_mutex_lock(&adev->lock);
5537
5538 ret = check_a2dp_restore_l(adev, out, restore);
5539
5540 pthread_mutex_unlock(&adev->lock);
5541 pthread_mutex_unlock(&out->lock);
5542 return ret;
5543}
5544
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005545static int adev_open(const hw_module_t *module, const char *name,
5546 hw_device_t **device)
5547{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005548 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005549
Eric Laurent2bafff12016-03-17 12:17:23 -07005550 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005551 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005552 pthread_mutex_lock(&adev_init_lock);
5553 if (audio_device_ref_count != 0) {
5554 *device = &adev->device.common;
5555 audio_device_ref_count++;
5556 ALOGV("%s: returning existing instance of adev", __func__);
5557 ALOGV("%s: exit", __func__);
5558 pthread_mutex_unlock(&adev_init_lock);
5559 return 0;
5560 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005561 adev = calloc(1, sizeof(struct audio_device));
5562
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005563 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5564
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005565 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5566 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5567 adev->device.common.module = (struct hw_module_t *)module;
5568 adev->device.common.close = adev_close;
5569
5570 adev->device.init_check = adev_init_check;
5571 adev->device.set_voice_volume = adev_set_voice_volume;
5572 adev->device.set_master_volume = adev_set_master_volume;
5573 adev->device.get_master_volume = adev_get_master_volume;
5574 adev->device.set_master_mute = adev_set_master_mute;
5575 adev->device.get_master_mute = adev_get_master_mute;
5576 adev->device.set_mode = adev_set_mode;
5577 adev->device.set_mic_mute = adev_set_mic_mute;
5578 adev->device.get_mic_mute = adev_get_mic_mute;
5579 adev->device.set_parameters = adev_set_parameters;
5580 adev->device.get_parameters = adev_get_parameters;
5581 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5582 adev->device.open_output_stream = adev_open_output_stream;
5583 adev->device.close_output_stream = adev_close_output_stream;
5584 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005585
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005586 adev->device.close_input_stream = adev_close_input_stream;
5587 adev->device.dump = adev_dump;
jiabin8962a4d2018-03-19 18:21:24 -07005588 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005589
5590 /* Set the default route before the PCM stream is opened */
5591 pthread_mutex_lock(&adev->lock);
5592 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005593 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005594 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005595 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005596 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005597 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005598 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005599 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005600 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005601 pthread_mutex_unlock(&adev->lock);
5602
5603 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005604 adev->platform = platform_init(adev);
5605 if (!adev->platform) {
5606 free(adev->snd_dev_ref_cnt);
5607 free(adev);
5608 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5609 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005610 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005611 return -EINVAL;
5612 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05005613 adev->extspk = audio_extn_extspk_init(adev);
5614
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005615 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5616 if (adev->visualizer_lib == NULL) {
5617 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5618 } else {
5619 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5620 adev->visualizer_start_output =
5621 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5622 "visualizer_hal_start_output");
5623 adev->visualizer_stop_output =
5624 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5625 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07005626 }
5627
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005628 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5629 if (adev->offload_effects_lib == NULL) {
5630 ALOGW("%s: DLOPEN failed for %s", __func__,
5631 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5632 } else {
5633 ALOGV("%s: DLOPEN successful for %s", __func__,
5634 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5635 adev->offload_effects_start_output =
5636 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5637 "offload_effects_bundle_hal_start_output");
5638 adev->offload_effects_stop_output =
5639 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5640 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07005641 }
5642
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005643 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5644 if (adev->adm_lib == NULL) {
5645 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5646 } else {
5647 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5648 adev->adm_init = (adm_init_t)
5649 dlsym(adev->adm_lib, "adm_init");
5650 adev->adm_deinit = (adm_deinit_t)
5651 dlsym(adev->adm_lib, "adm_deinit");
5652 adev->adm_register_input_stream = (adm_register_input_stream_t)
5653 dlsym(adev->adm_lib, "adm_register_input_stream");
5654 adev->adm_register_output_stream = (adm_register_output_stream_t)
5655 dlsym(adev->adm_lib, "adm_register_output_stream");
5656 adev->adm_deregister_stream = (adm_deregister_stream_t)
5657 dlsym(adev->adm_lib, "adm_deregister_stream");
5658 adev->adm_request_focus = (adm_request_focus_t)
5659 dlsym(adev->adm_lib, "adm_request_focus");
5660 adev->adm_abandon_focus = (adm_abandon_focus_t)
5661 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08005662 adev->adm_set_config = (adm_set_config_t)
5663 dlsym(adev->adm_lib, "adm_set_config");
5664 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5665 dlsym(adev->adm_lib, "adm_request_focus_v2");
5666 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5667 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5668 adev->adm_on_routing_change = (adm_on_routing_change_t)
5669 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005670 }
5671
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005672 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005673 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005674
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005675 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005676
Andy Hung31aca912014-03-20 17:14:59 -07005677 if (k_enable_extended_precision)
5678 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005679
Glenn Kasten4f993392014-05-14 07:30:48 -07005680 char value[PROPERTY_VALUE_MAX];
5681 int trial;
5682 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5683 trial = atoi(value);
5684 if (period_size_is_plausible_for_low_latency(trial)) {
5685 pcm_config_low_latency.period_size = trial;
5686 pcm_config_low_latency.start_threshold = trial / 4;
5687 pcm_config_low_latency.avail_min = trial / 4;
5688 configured_low_latency_capture_period_size = trial;
5689 }
5690 }
5691 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5692 trial = atoi(value);
5693 if (period_size_is_plausible_for_low_latency(trial)) {
5694 configured_low_latency_capture_period_size = trial;
5695 }
5696 }
5697
Vignesh Kulothunganb6f0a9c2018-03-22 13:50:22 -07005698 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
5699
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005700 // commented as full set of app type cfg is sent from platform
5701 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005702 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005703
5704 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5705 af_period_multiplier = atoi(value);
5706 if (af_period_multiplier < 0) {
5707 af_period_multiplier = 2;
5708 } else if (af_period_multiplier > 4) {
5709 af_period_multiplier = 4;
5710 }
5711 ALOGV("new period_multiplier = %d", af_period_multiplier);
5712 }
5713
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005714 audio_extn_tfa_98xx_init(adev);
jasmine cha270b7762018-03-30 15:41:33 +08005715 audio_extn_ma_init(adev->platform);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005716
vivek mehta1a9b7c02015-06-25 11:49:38 -07005717 pthread_mutex_unlock(&adev_init_lock);
5718
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005719 if (adev->adm_init)
5720 adev->adm_data = adev->adm_init();
5721
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005722 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005723 audio_extn_snd_mon_init();
5724 pthread_mutex_lock(&adev->lock);
5725 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
5726 adev->card_status = CARD_STATUS_ONLINE;
5727 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005728 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005729
Eric Laurent2bafff12016-03-17 12:17:23 -07005730 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005731 return 0;
5732}
5733
5734static struct hw_module_methods_t hal_module_methods = {
5735 .open = adev_open,
5736};
5737
5738struct audio_module HAL_MODULE_INFO_SYM = {
5739 .common = {
5740 .tag = HARDWARE_MODULE_TAG,
5741 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5742 .hal_api_version = HARDWARE_HAL_API_VERSION,
5743 .id = AUDIO_HARDWARE_MODULE_ID,
5744 .name = "QCOM Audio HAL",
5745 .author = "Code Aurora Forum",
5746 .methods = &hal_module_methods,
5747 },
5748};