blob: 0a12cff5c8bba3fffba2313a4e1646fa19be2792 [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;
1957
Eric Laurent994a6932013-07-17 11:51:42 -07001958 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001959 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001960 uc_info = get_usecase_from_list(adev, out->usecase);
1961 if (uc_info == NULL) {
1962 ALOGE("%s: Could not find the usecase (%d) in the list",
1963 __func__, out->usecase);
1964 return -EINVAL;
1965 }
1966
Haynes Mathew George41f86652014-06-17 14:22:15 -07001967 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1968 if (adev->visualizer_stop_output != NULL)
1969 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1970 if (adev->offload_effects_stop_output != NULL)
1971 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08001972 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
1973 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
1974 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07001975 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001976
Eric Laurent150dbfe2013-02-27 14:31:02 -08001977 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001978 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001979
1980 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001981 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001982
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001983 list_remove(&uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001984
Eric Laurent0499d4f2014-08-25 22:39:29 -05001985 audio_extn_extspk_update(adev->extspk);
1986
Eric Laurent07eeafd2013-10-06 12:52:49 -07001987 /* Must be called after removing the usecase from list */
1988 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1989 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07001990 else if (out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
1991 struct listnode *node;
1992 struct audio_usecase *usecase;
1993 list_for_each(node, &adev->usecase_list) {
1994 usecase = node_to_item(node, struct audio_usecase, list);
1995 if (usecase->devices & AUDIO_DEVICE_OUT_SPEAKER)
1996 select_devices(adev, usecase->id);
1997 }
Haynes Mathew George65f6b432018-02-27 17:44:55 -08001998 } else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
1999 ret = check_and_set_usb_service_interval(adev, uc_info, false /*min*/);
2000 if (ret == 0) {
2001 /* default service interval was successfully updated,
2002 reopen USB backend with new service interval */
2003 check_and_route_playback_usecases(adev, uc_info, uc_info->out_snd_device);
2004 }
2005 ret = 0;
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07002006 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002007
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002008 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07002009 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002010 return ret;
2011}
2012
2013int start_output_stream(struct stream_out *out)
2014{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002015 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002016 struct audio_usecase *uc_info;
2017 struct audio_device *adev = out->dev;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002018 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002019
Eric Laurent994a6932013-07-17 11:51:42 -07002020 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002021 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002022
2023 if (out->card_status == CARD_STATUS_OFFLINE ||
2024 adev->card_status == CARD_STATUS_OFFLINE) {
2025 ALOGW("out->card_status or adev->card_status offline, try again");
2026 ret = -EAGAIN;
2027 goto error_config;
2028 }
2029
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002030 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2031 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002032 if (out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002033 a2dp_combo = true;
2034 } else {
2035 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2036 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2037 ret = -EAGAIN;
2038 goto error_config;
2039 }
2040 }
2041 }
2042 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002043 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002044 if (out->pcm_device_id < 0) {
2045 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2046 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002047 ret = -EINVAL;
2048 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002049 }
2050
2051 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
2052 uc_info->id = out->usecase;
2053 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002054 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002055 uc_info->devices = out->devices;
2056 uc_info->in_snd_device = SND_DEVICE_NONE;
2057 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002058
Eric Laurent07eeafd2013-10-06 12:52:49 -07002059 /* This must be called before adding this usecase to the list */
2060 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2061 check_and_set_hdmi_channels(adev, out->config.channels);
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002062 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
2063 check_and_set_usb_service_interval(adev, uc_info, true /*min*/);
2064 /* USB backend is not reopened immediately.
2065 This is eventually done as part of select_devices */
2066 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002067
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002068 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002069
Wei Wangf4837d52017-11-21 14:51:20 -08002070 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002071 audio_extn_perf_lock_acquire();
2072
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002073 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2074 (!audio_extn_a2dp_is_ready())) {
2075 if (!a2dp_combo) {
2076 check_a2dp_restore_l(adev, out, false);
2077 } else {
2078 audio_devices_t dev = out->devices;
juyuchen9baad392018-06-05 19:02:10 +08002079 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2080 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2081 else
2082 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002083 select_devices(adev, out->usecase);
2084 out->devices = dev;
2085 }
2086 } else {
2087 select_devices(adev, out->usecase);
2088 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002089
Eric Laurent0499d4f2014-08-25 22:39:29 -05002090 audio_extn_extspk_update(adev->extspk);
2091
Andy Hung31aca912014-03-20 17:14:59 -07002092 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002093 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002094 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2095 out->pcm = NULL;
2096 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
2097 COMPRESS_IN, &out->compr_config);
2098 if (out->compr && !is_compress_ready(out->compr)) {
2099 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2100 compress_close(out->compr);
2101 out->compr = NULL;
2102 ret = -EIO;
2103 goto error_open;
2104 }
2105 if (out->offload_callback)
2106 compress_nonblock(out->compr, out->non_blocking);
2107
2108 if (adev->visualizer_start_output != NULL)
2109 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2110 if (adev->offload_effects_start_output != NULL)
2111 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
2112 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002113 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002114 ALOGE("%s: pcm stream not ready", __func__);
2115 goto error_open;
2116 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002117 ret = pcm_start(out->pcm);
2118 if (ret < 0) {
2119 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2120 goto error_open;
2121 }
2122 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07002123 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002124 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002125
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002126 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2127 flags |= PCM_MMAP | PCM_NOIRQ;
2128 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002129 } else if (out->realtime) {
2130 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07002131 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002132
2133 while (1) {
2134 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2135 flags, &out->config);
2136 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2137 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2138 if (out->pcm != NULL) {
2139 pcm_close(out->pcm);
2140 out->pcm = NULL;
2141 }
2142 if (pcm_open_retry_count-- == 0) {
2143 ret = -EIO;
2144 goto error_open;
2145 }
2146 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2147 continue;
2148 }
2149 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002150 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002151 ALOGV("%s: pcm_prepare", __func__);
2152 if (pcm_is_ready(out->pcm)) {
2153 ret = pcm_prepare(out->pcm);
2154 if (ret < 0) {
2155 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2156 pcm_close(out->pcm);
2157 out->pcm = NULL;
2158 goto error_open;
2159 }
2160 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002161 if (out->realtime) {
2162 ret = pcm_start(out->pcm);
2163 if (ret < 0) {
2164 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
2165 pcm_close(out->pcm);
2166 out->pcm = NULL;
2167 goto error_open;
2168 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002169 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002170 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002171 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08002172 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002173 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002174 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07002175
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002176 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2177 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2178 audio_low_latency_hint_start();
2179 }
2180
vivek mehtae59cfb22017-06-16 15:57:11 -07002181 // consider a scenario where on pause lower layers are tear down.
2182 // so on resume, swap mixer control need to be sent only when
2183 // backend is active, hence rather than sending from enable device
2184 // sending it from start of streamtream
2185
2186 platform_set_swap_channels(adev, true);
2187
Eric Laurent994a6932013-07-17 11:51:42 -07002188 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002189 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002190error_open:
Wei Wangf4837d52017-11-21 14:51:20 -08002191 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002192 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002193 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002194error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002195 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002196}
2197
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002198static int check_input_parameters(uint32_t sample_rate,
2199 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07002200 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002201{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002202 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2203 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002204 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2205 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002206 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2207 return -EINVAL;
2208 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002209
Eric Laurent74b55762017-07-09 17:04:53 -07002210 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2211 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002212 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002213 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002214 return -EINVAL;
2215 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002216
2217 switch (sample_rate) {
2218 case 8000:
2219 case 11025:
2220 case 12000:
2221 case 16000:
2222 case 22050:
2223 case 24000:
2224 case 32000:
2225 case 44100:
2226 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002227 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002228 break;
2229 default:
vivek mehtadae44712015-07-27 14:13:18 -07002230 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002231 return -EINVAL;
2232 }
2233
2234 return 0;
2235}
2236
Kevin Rocarda325aa22018-04-03 09:15:52 -07002237/** Add a value in a list if not already present.
2238 * @return true if value was successfully inserted or already present,
2239 * false if the list is full and does not contain the value.
2240 */
2241static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
2242 for (size_t i = 0; i < list_length; i++) {
2243 if (list[i] == value) return true; // value is already present
2244 if (list[i] == 0) { // no values in this slot
2245 list[i] = value;
2246 return true; // value inserted
2247 }
2248 }
2249 return false; // could not insert value
2250}
2251
2252/** Add channel_mask in supported_channel_masks if not already present.
2253 * @return true if channel_mask was successfully inserted or already present,
2254 * false if supported_channel_masks is full and does not contain channel_mask.
2255 */
2256static void register_channel_mask(audio_channel_mask_t channel_mask,
2257 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
2258 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
2259 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
2260}
2261
2262/** Add format in supported_formats if not already present.
2263 * @return true if format was successfully inserted or already present,
2264 * false if supported_formats is full and does not contain format.
2265 */
2266static void register_format(audio_format_t format,
2267 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
2268 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
2269 "%s: stream can not declare supporting its format %x", __func__, format);
2270}
2271/** Add sample_rate in supported_sample_rates if not already present.
2272 * @return true if sample_rate was successfully inserted or already present,
2273 * false if supported_sample_rates is full and does not contain sample_rate.
2274 */
2275static void register_sample_rate(uint32_t sample_rate,
2276 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
2277 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
2278 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
2279}
2280
vivek mehtaa68fea62017-06-08 19:04:02 -07002281static size_t get_stream_buffer_size(size_t duration_ms,
2282 uint32_t sample_rate,
2283 audio_format_t format,
2284 int channel_count,
2285 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002286{
2287 size_t size = 0;
2288
vivek mehtaa68fea62017-06-08 19:04:02 -07002289 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002290 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002291 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002292
2293 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002294
Glenn Kasten4f993392014-05-14 07:30:48 -07002295 /* make sure the size is multiple of 32 bytes
2296 * At 48 kHz mono 16-bit PCM:
2297 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2298 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2299 */
2300 size += 0x1f;
2301 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002302
2303 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002304}
2305
2306static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2307{
2308 struct stream_out *out = (struct stream_out *)stream;
2309
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002310 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002311}
2312
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002313static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002314{
2315 return -ENOSYS;
2316}
2317
2318static size_t out_get_buffer_size(const struct audio_stream *stream)
2319{
2320 struct stream_out *out = (struct stream_out *)stream;
2321
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002322 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2323 return out->compr_config.fragment_size;
2324 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002325 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002326 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002327}
2328
2329static uint32_t out_get_channels(const struct audio_stream *stream)
2330{
2331 struct stream_out *out = (struct stream_out *)stream;
2332
2333 return out->channel_mask;
2334}
2335
2336static audio_format_t out_get_format(const struct audio_stream *stream)
2337{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002338 struct stream_out *out = (struct stream_out *)stream;
2339
2340 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002341}
2342
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002343static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002344{
2345 return -ENOSYS;
2346}
2347
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002348/* must be called with out->lock locked */
2349static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002350{
2351 struct stream_out *out = (struct stream_out *)stream;
2352 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002353 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002354
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002355 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002356 if (adev->adm_deregister_stream)
2357 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002358 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002359 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002360 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2361 if (out->pcm) {
2362 pcm_close(out->pcm);
2363 out->pcm = NULL;
2364 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002365 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002366 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002367 out->playback_started = false;
2368 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002369 } else {
2370 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002371 out->gapless_mdata.encoder_delay = 0;
2372 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002373 if (out->compr != NULL) {
2374 compress_close(out->compr);
2375 out->compr = NULL;
2376 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002377 }
Phil Burkbc991042017-02-24 08:06:44 -08002378 if (do_stop) {
2379 stop_output_stream(out);
2380 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002381 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002382 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002383 return 0;
2384}
2385
2386static int out_standby(struct audio_stream *stream)
2387{
2388 struct stream_out *out = (struct stream_out *)stream;
2389
2390 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2391 out->usecase, use_case_table[out->usecase]);
2392
2393 lock_output_stream(out);
2394 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002395 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002396 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002397 return 0;
2398}
2399
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002400static int out_on_error(struct audio_stream *stream)
2401{
2402 struct stream_out *out = (struct stream_out *)stream;
2403 struct audio_device *adev = out->dev;
2404 bool do_standby = false;
2405
2406 lock_output_stream(out);
2407 if (!out->standby) {
2408 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2409 stop_compressed_output_l(out);
2410 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2411 } else
2412 do_standby = true;
2413 }
2414 pthread_mutex_unlock(&out->lock);
2415
2416 if (do_standby)
2417 return out_standby(&out->stream.common);
2418
2419 return 0;
2420}
2421
Andy Hung7401c7c2016-09-21 12:41:21 -07002422static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002423{
Andy Hung7401c7c2016-09-21 12:41:21 -07002424 struct stream_out *out = (struct stream_out *)stream;
2425
2426 // We try to get the lock for consistency,
2427 // but it isn't necessary for these variables.
2428 // If we're not in standby, we may be blocked on a write.
2429 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2430 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2431 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2432
2433 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002434 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002435 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002436
2437 // dump error info
2438 (void)error_log_dump(
2439 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002440
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002441 return 0;
2442}
2443
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002444static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2445{
2446 int ret = 0;
2447 char value[32];
2448 struct compr_gapless_mdata tmp_mdata;
2449
2450 if (!out || !parms) {
2451 return -EINVAL;
2452 }
2453
2454 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2455 if (ret >= 0) {
2456 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2457 } else {
2458 return -EINVAL;
2459 }
2460
2461 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2462 if (ret >= 0) {
2463 tmp_mdata.encoder_padding = atoi(value);
2464 } else {
2465 return -EINVAL;
2466 }
2467
2468 out->gapless_mdata = tmp_mdata;
2469 out->send_new_metadata = 1;
2470 ALOGV("%s new encoder delay %u and padding %u", __func__,
2471 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2472
2473 return 0;
2474}
2475
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002476static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2477{
2478 return out == adev->primary_output || out == adev->voice_tx_output;
2479}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002480
Kevin Rocard1e02c882017-08-09 15:26:07 -07002481static int get_alive_usb_card(struct str_parms* parms) {
2482 int card;
2483 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2484 !audio_extn_usb_alive(card)) {
2485 return card;
2486 }
2487 return -ENODEV;
2488}
2489
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002490static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2491{
2492 struct stream_out *out = (struct stream_out *)stream;
2493 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002494 struct audio_usecase *usecase;
2495 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002496 struct str_parms *parms;
2497 char value[32];
2498 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002499 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002500 int status = 0;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002501 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002502
Eric Laurent2e140aa2016-06-30 17:14:46 -07002503 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002504 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002505 parms = str_parms_create_str(kvpairs);
2506 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2507 if (ret >= 0) {
2508 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002509
Eric Laurenta1478072015-09-21 17:21:52 -07002510 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002511
2512 // The usb driver needs to be closed after usb device disconnection
2513 // otherwise audio is no longer played on the new usb devices.
2514 // By forcing the stream in standby, the usb stack refcount drops to 0
2515 // and the driver is closed.
2516 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD && val == AUDIO_DEVICE_NONE &&
2517 audio_is_usb_out_device(out->devices)) {
2518 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2519 out_standby_l(&out->stream.common);
2520 }
2521
Eric Laurent150dbfe2013-02-27 14:31:02 -08002522 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002523
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002524 /*
2525 * When HDMI cable is unplugged the music playback is paused and
2526 * the policy manager sends routing=0. But the audioflinger
2527 * continues to write data until standby time (3sec).
2528 * As the HDMI core is turned off, the write gets blocked.
2529 * Avoid this by routing audio to speaker until standby.
2530 */
2531 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2532 val == AUDIO_DEVICE_NONE) {
2533 val = AUDIO_DEVICE_OUT_SPEAKER;
2534 }
2535
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002536 /*
2537 * When A2DP is disconnected the
2538 * music playback is paused and the policy manager sends routing=0
2539 * But the audioflingercontinues to write data until standby time
2540 * (3sec). As BT is turned off, the write gets blocked.
2541 * Avoid this by routing audio to speaker until standby.
2542 */
2543 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2544 (val == AUDIO_DEVICE_NONE) &&
2545 !audio_extn_a2dp_is_ready()) {
2546 val = AUDIO_DEVICE_OUT_SPEAKER;
2547 }
2548
2549 /* To avoid a2dp to sco overlapping / BT device improper state
2550 * check with BT lib about a2dp streaming support before routing
2551 */
2552 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2553 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002554 if (val & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002555 //combo usecase just by pass a2dp
2556 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2557 bypass_a2dp = true;
2558 } else {
2559 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2560 /* update device to a2dp and don't route as BT returned error
2561 * However it is still possible a2dp routing called because
2562 * of current active device disconnection (like wired headset)
2563 */
2564 out->devices = val;
2565 pthread_mutex_unlock(&out->lock);
2566 pthread_mutex_unlock(&adev->lock);
2567 status = -ENOSYS;
2568 goto routing_fail;
2569 }
2570 }
2571 }
2572
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002573 audio_devices_t new_dev = val;
2574
2575 // Workaround: If routing to an non existing usb device, fail gracefully
2576 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002577 int card;
2578 if (audio_is_usb_out_device(new_dev) &&
2579 (card = get_alive_usb_card(parms)) >= 0) {
2580
2581 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002582 pthread_mutex_unlock(&adev->lock);
2583 pthread_mutex_unlock(&out->lock);
2584 status = -ENOSYS;
2585 goto routing_fail;
2586 }
2587
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002588 /*
2589 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002590 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002591 * the select_devices(). But how do we undo this?
2592 *
2593 * For example, music playback is active on headset (deep-buffer usecase)
2594 * and if we go to ringtones and select a ringtone, low-latency usecase
2595 * will be started on headset+speaker. As we can't enable headset+speaker
2596 * and headset devices at the same time, select_devices() switches the music
2597 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2598 * So when the ringtone playback is completed, how do we undo the same?
2599 *
2600 * We are relying on the out_set_parameters() call on deep-buffer output,
2601 * once the ringtone playback is ended.
2602 * NOTE: We should not check if the current devices are same as new devices.
2603 * Because select_devices() must be called to switch back the music
2604 * playback to headset.
2605 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002606 if (new_dev != AUDIO_DEVICE_NONE) {
2607 bool same_dev = out->devices == new_dev;
2608 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002609
Eric Laurenta7657192014-10-09 21:09:33 -07002610 if (output_drives_call(adev, out)) {
Vignesh Kulothungana5c9da12017-11-10 11:41:24 -08002611 if (!voice_is_call_state_active(adev)) {
Eric Laurenta7657192014-10-09 21:09:33 -07002612 if (adev->mode == AUDIO_MODE_IN_CALL) {
2613 adev->current_call_output = out;
2614 ret = voice_start_call(adev);
2615 }
2616 } else {
2617 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002618 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002619 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002620 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002621
2622 if (!out->standby) {
2623 if (!same_dev) {
2624 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002625 // inform adm before actual routing to prevent glitches.
2626 if (adev->adm_on_routing_change) {
2627 adev->adm_on_routing_change(adev->adm_data,
2628 out->handle);
2629 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002630 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002631 if (!bypass_a2dp) {
2632 select_devices(adev, out->usecase);
2633 } else {
juyuchen9baad392018-06-05 19:02:10 +08002634 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2635 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2636 else
2637 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002638 select_devices(adev, out->usecase);
2639 out->devices = new_dev;
2640 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002641 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002642
2643 // on device switch force swap, lower functions will make sure
2644 // to check if swap is allowed or not.
2645
2646 if (!same_dev)
2647 platform_set_swap_channels(adev, true);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002648
2649 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2650 out->a2dp_compress_mute &&
2651 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
2652 pthread_mutex_lock(&out->compr_mute_lock);
2653 out->a2dp_compress_mute = false;
2654 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
2655 pthread_mutex_unlock(&out->compr_mute_lock);
2656 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002657 }
2658
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002659 }
2660
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002661 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002662 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002663
2664 /*handles device and call state changes*/
2665 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002666 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002667 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002668
2669 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2670 parse_compress_metadata(out, parms);
2671 }
2672
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002673 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002674 ALOGV("%s: exit: code(%d)", __func__, status);
2675 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002676}
2677
Haynes Mathew George569b7482017-05-08 14:44:27 -07002678static bool stream_get_parameter_channels(struct str_parms *query,
2679 struct str_parms *reply,
2680 audio_channel_mask_t *supported_channel_masks) {
2681 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002682 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002683 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002684 size_t i, j;
2685
2686 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2687 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002688 value[0] = '\0';
2689 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002690 while (supported_channel_masks[i] != 0) {
2691 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2692 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002693 if (!first) {
2694 strcat(value, "|");
2695 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002696 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002697 first = false;
2698 break;
2699 }
2700 }
2701 i++;
2702 }
2703 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002704 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002705 return ret >= 0;
2706}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002707
Haynes Mathew George569b7482017-05-08 14:44:27 -07002708static bool stream_get_parameter_formats(struct str_parms *query,
2709 struct str_parms *reply,
2710 audio_format_t *supported_formats) {
2711 int ret = -1;
2712 char value[256];
2713 int i;
2714
2715 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2716 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002717 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002718 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002719 case AUDIO_FORMAT_PCM_16_BIT:
2720 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2721 break;
2722 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2723 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2724 break;
2725 case AUDIO_FORMAT_PCM_32_BIT:
2726 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2727 break;
2728 default:
2729 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002730 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002731 break;
2732 }
2733 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002734 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002735 return ret >= 0;
2736}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002737
Haynes Mathew George569b7482017-05-08 14:44:27 -07002738static bool stream_get_parameter_rates(struct str_parms *query,
2739 struct str_parms *reply,
2740 uint32_t *supported_sample_rates) {
2741
2742 int i;
2743 char value[256];
2744 int ret = -1;
2745 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2746 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002747 value[0] = '\0';
2748 i=0;
2749 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002750 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002751 int avail = sizeof(value) - cursor;
2752 ret = snprintf(value + cursor, avail, "%s%d",
2753 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002754 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002755 if (ret < 0 || ret >= avail) {
2756 // if cursor is at the last element of the array
2757 // overwrite with \0 is duplicate work as
2758 // snprintf already put a \0 in place.
2759 // else
2760 // we had space to write the '|' at value[cursor]
2761 // (which will be overwritten) or no space to fill
2762 // the first element (=> cursor == 0)
2763 value[cursor] = '\0';
2764 break;
2765 }
2766 cursor += ret;
2767 ++i;
2768 }
2769 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2770 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002771 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002772 return ret >= 0;
2773}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002774
Haynes Mathew George569b7482017-05-08 14:44:27 -07002775static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2776{
2777 struct stream_out *out = (struct stream_out *)stream;
2778 struct str_parms *query = str_parms_create_str(keys);
2779 char *str;
2780 struct str_parms *reply = str_parms_create();
2781 bool replied = false;
2782 ALOGV("%s: enter: keys - %s", __func__, keys);
2783
2784 replied |= stream_get_parameter_channels(query, reply,
2785 &out->supported_channel_masks[0]);
2786 replied |= stream_get_parameter_formats(query, reply,
2787 &out->supported_formats[0]);
2788 replied |= stream_get_parameter_rates(query, reply,
2789 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002790 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002791 str = str_parms_to_str(reply);
2792 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002793 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002794 }
2795 str_parms_destroy(query);
2796 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002797 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002798 return str;
2799}
2800
2801static uint32_t out_get_latency(const struct audio_stream_out *stream)
2802{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002803 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002804 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002805 uint32_t latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002806
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002807 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2808 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002809 else if ((out->realtime) ||
2810 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002811 // since the buffer won't be filled up faster than realtime,
2812 // return a smaller number
2813 period_ms = (out->af_period_multiplier * out->config.period_size *
2814 1000) / (out->config.rate);
2815 hw_delay = platform_render_latency(out->usecase)/1000;
2816 return period_ms + hw_delay;
2817 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002818
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002819 latency = (out->config.period_count * out->config.period_size * 1000) /
2820 (out->config.rate);
2821
2822 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
2823 latency += audio_extn_a2dp_get_encoder_latency();
2824
2825 return latency;
2826}
2827
2828static int set_compr_volume(struct audio_stream_out *stream, float left,
2829 float right)
2830{
2831 struct stream_out *out = (struct stream_out *)stream;
2832 int volume[2];
2833 char mixer_ctl_name[128];
2834 struct audio_device *adev = out->dev;
2835 struct mixer_ctl *ctl;
2836 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2837 PCM_PLAYBACK);
2838
2839 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2840 "Compress Playback %d Volume", pcm_device_id);
2841 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2842 if (!ctl) {
2843 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2844 __func__, mixer_ctl_name);
2845 return -EINVAL;
2846 }
2847 ALOGV("%s: ctl for mixer cmd - %s, left %f, right %f",
2848 __func__, mixer_ctl_name, left, right);
2849 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2850 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2851 mixer_ctl_set_array(ctl, volume, sizeof(volume) / sizeof(volume[0]));
2852
2853 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002854}
2855
2856static int out_set_volume(struct audio_stream_out *stream, float left,
2857 float right)
2858{
Eric Laurenta9024de2013-04-04 09:19:12 -07002859 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002860 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002861
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002862 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002863 /* only take left channel into account: the API is for stereo anyway */
2864 out->muted = (left == 0.0f);
2865 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002866 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002867 pthread_mutex_lock(&out->compr_mute_lock);
2868 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
2869 if (!out->a2dp_compress_mute)
2870 ret = set_compr_volume(stream, left, right);
2871 out->volume_l = left;
2872 out->volume_r = right;
2873 pthread_mutex_unlock(&out->compr_mute_lock);
2874 return ret;
vivek mehtaa68fea62017-06-08 19:04:02 -07002875 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002876 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2877 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2878 if (!out->standby) {
2879 // if in standby, cached volume will be sent after stream is opened
2880 audio_extn_utils_send_app_type_gain(out->dev,
2881 out->app_type_cfg.app_type,
2882 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002883 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002884 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002885 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002886
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002887 return -ENOSYS;
2888}
2889
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002890// note: this call is safe only if the stream_cb is
2891// removed first in close_output_stream (as is done now).
2892static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2893{
2894 if (!stream || !parms)
2895 return;
2896
2897 struct stream_out *out = (struct stream_out *)stream;
2898 struct audio_device *adev = out->dev;
2899
2900 card_status_t status;
2901 int card;
2902 if (parse_snd_card_status(parms, &card, &status) < 0)
2903 return;
2904
2905 pthread_mutex_lock(&adev->lock);
2906 bool valid_cb = (card == adev->snd_card);
2907 pthread_mutex_unlock(&adev->lock);
2908
2909 if (!valid_cb)
2910 return;
2911
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002912 lock_output_stream(out);
2913 if (out->card_status != status)
2914 out->card_status = status;
2915 pthread_mutex_unlock(&out->lock);
2916
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002917 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2918 use_case_table[out->usecase],
2919 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2920
2921 if (status == CARD_STATUS_OFFLINE)
2922 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002923
2924 return;
2925}
2926
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002927#ifdef NO_AUDIO_OUT
2928static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002929 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002930{
2931 struct stream_out *out = (struct stream_out *)stream;
2932
2933 /* No Output device supported other than BT for playback.
2934 * Sleep for the amount of buffer duration
2935 */
Eric Laurenta1478072015-09-21 17:21:52 -07002936 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002937 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2938 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002939 out_get_sample_rate(&out->stream.common));
2940 pthread_mutex_unlock(&out->lock);
2941 return bytes;
2942}
2943#endif
2944
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002945static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2946 size_t bytes)
2947{
2948 struct stream_out *out = (struct stream_out *)stream;
2949 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002950 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002951 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002952
Eric Laurenta1478072015-09-21 17:21:52 -07002953 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002954 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07002955 const size_t frame_size = audio_stream_out_frame_size(stream);
2956 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002957
Eric Laurent0e46adf2016-12-16 12:49:24 -08002958 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2959 error_code = ERROR_CODE_WRITE;
2960 goto exit;
2961 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002962
2963 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2964 (audio_extn_a2dp_is_suspended())) {
juyuchen9baad392018-06-05 19:02:10 +08002965 if (!(out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002966 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2967 ret = -EIO;
2968 goto exit;
2969 }
2970 }
2971 }
2972
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002973 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002974 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002975 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002976 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07002977
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002978 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002979 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002980 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07002981 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002982 goto exit;
2983 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002984
vivek mehta40125092017-08-21 18:48:51 -07002985 // after standby always force set last known cal step
2986 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
2987 ALOGD("%s: retry previous failed cal level set", __func__);
2988 send_gain_dep_calibration_l();
2989 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002990 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002991
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002992 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002993 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002994 if (out->send_new_metadata) {
2995 ALOGVV("send new gapless metadata");
2996 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2997 out->send_new_metadata = 0;
2998 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002999 unsigned int avail;
3000 struct timespec tstamp;
3001 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
3002 /* Do not limit write size if the available frames count is unknown */
3003 if (ret != 0) {
3004 avail = bytes;
3005 }
3006 if (avail == 0) {
3007 ret = 0;
3008 } else {
3009 if (avail > bytes) {
3010 avail = bytes;
3011 }
3012 ret = compress_write(out->compr, buffer, avail);
3013 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
3014 __func__, avail, ret);
3015 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003016
Eric Laurent6e895242013-09-05 16:10:57 -07003017 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003018 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
3019 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003020 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003021 compress_start(out->compr);
3022 out->playback_started = 1;
3023 out->offload_state = OFFLOAD_STATE_PLAYING;
3024 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003025 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07003026 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07003027 } else {
3028 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07003029 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003030 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07003031 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003032 return ret;
3033 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07003034 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003035 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003036 size_t bytes_to_write = bytes;
3037
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003038 if (out->muted)
3039 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07003040 // FIXME: this can be removed once audio flinger mixer supports mono output
Nadav Bar3d72cfc2018-01-07 12:19:24 +02003041 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP || out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003042 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3043 int16_t *src = (int16_t *)buffer;
3044 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003045
Eric Laurentad2dde92017-09-20 18:27:31 -07003046 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
3047 out->format != AUDIO_FORMAT_PCM_16_BIT,
3048 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003049
Eric Laurentad2dde92017-09-20 18:27:31 -07003050 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
3051 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
3052 }
3053 bytes_to_write /= 2;
3054 }
3055 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes_to_write);
3056
Glenn Kasten5a59dff2018-02-22 08:05:35 -08003057 long ns = (frames * (int64_t) NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003058 request_out_focus(out, ns);
3059
3060 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3061 if (use_mmap)
Eric Laurentad2dde92017-09-20 18:27:31 -07003062 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003063 else
Eric Laurentad2dde92017-09-20 18:27:31 -07003064 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003065
Haynes Mathew George03c40102016-01-29 17:57:48 -08003066 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07003067 } else {
3068 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003069 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003070 }
3071
3072exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07003073 // For PCM we always consume the buffer and return #bytes regardless of ret.
3074 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003075 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07003076 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003077 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07003078
Andy Hung7401c7c2016-09-21 12:41:21 -07003079 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07003080 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07003081 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3082 ALOGE_IF(out->pcm != NULL,
3083 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07003084 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003085 // usleep not guaranteed for values over 1 second but we don't limit here.
3086 }
3087 }
Andy Hungda9b56b2016-09-16 20:06:35 -07003088
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003089 pthread_mutex_unlock(&out->lock);
3090
3091 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07003092 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003093 if (sleeptime_us != 0)
3094 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003095 }
3096 return bytes;
3097}
3098
3099static int out_get_render_position(const struct audio_stream_out *stream,
3100 uint32_t *dsp_frames)
3101{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003102 struct stream_out *out = (struct stream_out *)stream;
3103 *dsp_frames = 0;
3104 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07003105 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003106 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003107 unsigned long frames = 0;
3108 // TODO: check return value
3109 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
3110 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003111 ALOGVV("%s rendered frames %d sample_rate %d",
3112 __func__, *dsp_frames, out->sample_rate);
3113 }
3114 pthread_mutex_unlock(&out->lock);
3115 return 0;
3116 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003117 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003118}
3119
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003120static int out_add_audio_effect(const struct audio_stream *stream __unused,
3121 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003122{
3123 return 0;
3124}
3125
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003126static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3127 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003128{
3129 return 0;
3130}
3131
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003132static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3133 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003134{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003135 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003136}
3137
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003138static int out_get_presentation_position(const struct audio_stream_out *stream,
3139 uint64_t *frames, struct timespec *timestamp)
3140{
3141 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003142 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07003143 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003144
Eric Laurenta1478072015-09-21 17:21:52 -07003145 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003146
Eric Laurent949a0892013-09-20 09:20:13 -07003147 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3148 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003149 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07003150 compress_get_tstamp(out->compr, &dsp_frames,
3151 &out->sample_rate);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003152 // Adjustment accounts for A2DP encoder latency with offload usecases
3153 // Note: Encoder latency is returned in ms.
3154 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3155 unsigned long offset =
3156 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3157 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
3158 }
Eric Laurent949a0892013-09-20 09:20:13 -07003159 ALOGVV("%s rendered frames %ld sample_rate %d",
3160 __func__, dsp_frames, out->sample_rate);
3161 *frames = dsp_frames;
3162 ret = 0;
3163 /* this is the best we can do */
3164 clock_gettime(CLOCK_MONOTONIC, timestamp);
3165 }
3166 } else {
3167 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07003168 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003169 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3170 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003171 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003172 // This adjustment accounts for buffering after app processor.
3173 // It is based on estimated DSP latency per use case, rather than exact.
3174 signed_frames -=
3175 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3176
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003177 // Adjustment accounts for A2DP encoder latency with non-offload usecases
3178 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3179 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3180 signed_frames -=
3181 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3182 }
3183
Eric Laurent949a0892013-09-20 09:20:13 -07003184 // It would be unusual for this value to be negative, but check just in case ...
3185 if (signed_frames >= 0) {
3186 *frames = signed_frames;
3187 ret = 0;
3188 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003189 }
3190 }
3191 }
3192
3193 pthread_mutex_unlock(&out->lock);
3194
3195 return ret;
3196}
3197
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003198static int out_set_callback(struct audio_stream_out *stream,
3199 stream_callback_t callback, void *cookie)
3200{
3201 struct stream_out *out = (struct stream_out *)stream;
3202
3203 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003204 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003205 out->offload_callback = callback;
3206 out->offload_cookie = cookie;
3207 pthread_mutex_unlock(&out->lock);
3208 return 0;
3209}
3210
3211static int out_pause(struct audio_stream_out* stream)
3212{
3213 struct stream_out *out = (struct stream_out *)stream;
3214 int status = -ENOSYS;
3215 ALOGV("%s", __func__);
3216 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003217 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003218 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
3219 status = compress_pause(out->compr);
3220 out->offload_state = OFFLOAD_STATE_PAUSED;
3221 }
3222 pthread_mutex_unlock(&out->lock);
3223 }
3224 return status;
3225}
3226
3227static int out_resume(struct audio_stream_out* stream)
3228{
3229 struct stream_out *out = (struct stream_out *)stream;
3230 int status = -ENOSYS;
3231 ALOGV("%s", __func__);
3232 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3233 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07003234 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003235 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
3236 status = compress_resume(out->compr);
3237 out->offload_state = OFFLOAD_STATE_PLAYING;
3238 }
3239 pthread_mutex_unlock(&out->lock);
3240 }
3241 return status;
3242}
3243
3244static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3245{
3246 struct stream_out *out = (struct stream_out *)stream;
3247 int status = -ENOSYS;
3248 ALOGV("%s", __func__);
3249 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003250 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003251 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3252 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3253 else
3254 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3255 pthread_mutex_unlock(&out->lock);
3256 }
3257 return status;
3258}
3259
3260static int out_flush(struct audio_stream_out* stream)
3261{
3262 struct stream_out *out = (struct stream_out *)stream;
3263 ALOGV("%s", __func__);
3264 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003265 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003266 stop_compressed_output_l(out);
3267 pthread_mutex_unlock(&out->lock);
3268 return 0;
3269 }
3270 return -ENOSYS;
3271}
3272
Eric Laurent0e46adf2016-12-16 12:49:24 -08003273static int out_stop(const struct audio_stream_out* stream)
3274{
3275 struct stream_out *out = (struct stream_out *)stream;
3276 struct audio_device *adev = out->dev;
3277 int ret = -ENOSYS;
3278
3279 ALOGV("%s", __func__);
3280 pthread_mutex_lock(&adev->lock);
3281 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3282 out->playback_started && out->pcm != NULL) {
3283 pcm_stop(out->pcm);
3284 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08003285 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003286 }
3287 pthread_mutex_unlock(&adev->lock);
3288 return ret;
3289}
3290
3291static int out_start(const struct audio_stream_out* stream)
3292{
3293 struct stream_out *out = (struct stream_out *)stream;
3294 struct audio_device *adev = out->dev;
3295 int ret = -ENOSYS;
3296
3297 ALOGV("%s", __func__);
3298 pthread_mutex_lock(&adev->lock);
3299 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3300 !out->playback_started && out->pcm != NULL) {
3301 ret = start_output_stream(out);
3302 if (ret == 0) {
3303 out->playback_started = true;
3304 }
3305 }
3306 pthread_mutex_unlock(&adev->lock);
3307 return ret;
3308}
3309
Phil Burkbc991042017-02-24 08:06:44 -08003310/*
3311 * Modify config->period_count based on min_size_frames
3312 */
3313static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
3314{
3315 int periodCountRequested = (min_size_frames + config->period_size - 1)
3316 / config->period_size;
3317 int periodCount = MMAP_PERIOD_COUNT_MIN;
3318
3319 ALOGV("%s original config.period_size = %d config.period_count = %d",
3320 __func__, config->period_size, config->period_count);
3321
3322 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
3323 periodCount *= 2;
3324 }
3325 config->period_count = periodCount;
3326
3327 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
3328}
3329
Eric Laurent0e46adf2016-12-16 12:49:24 -08003330static int out_create_mmap_buffer(const struct audio_stream_out *stream,
3331 int32_t min_size_frames,
3332 struct audio_mmap_buffer_info *info)
3333{
3334 struct stream_out *out = (struct stream_out *)stream;
3335 struct audio_device *adev = out->dev;
3336 int ret = 0;
3337 unsigned int offset1;
3338 unsigned int frames1;
3339 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003340 uint32_t mmap_size;
3341 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003342
3343 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003344 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003345 pthread_mutex_lock(&adev->lock);
3346
3347 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003348 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003349 ret = -EINVAL;
3350 goto exit;
3351 }
3352 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003353 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003354 ret = -ENOSYS;
3355 goto exit;
3356 }
3357 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3358 if (out->pcm_device_id < 0) {
3359 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3360 __func__, out->pcm_device_id, out->usecase);
3361 ret = -EINVAL;
3362 goto exit;
3363 }
Phil Burkbc991042017-02-24 08:06:44 -08003364
3365 adjust_mmap_period_count(&out->config, min_size_frames);
3366
Eric Laurent0e46adf2016-12-16 12:49:24 -08003367 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3368 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3369 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3370 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3371 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3372 step = "open";
3373 ret = -ENODEV;
3374 goto exit;
3375 }
3376 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3377 if (ret < 0) {
3378 step = "begin";
3379 goto exit;
3380 }
3381 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003382 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003383 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003384 ret = platform_get_mmap_data_fd(adev->platform,
3385 out->pcm_device_id, 0 /*playback*/,
3386 &info->shared_memory_fd,
3387 &mmap_size);
3388 if (ret < 0) {
3389 // Fall back to non exclusive mode
3390 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3391 } else {
3392 if (mmap_size < buffer_size) {
3393 step = "mmap";
3394 goto exit;
3395 }
3396 // FIXME: indicate exclusive mode support by returning a negative buffer size
3397 info->buffer_size_frames *= -1;
3398 }
3399 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003400
3401 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3402 if (ret < 0) {
3403 step = "commit";
3404 goto exit;
3405 }
Phil Burkbc991042017-02-24 08:06:44 -08003406
3407 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003408 ret = 0;
3409
3410 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3411 __func__, info->shared_memory_address, info->buffer_size_frames);
3412
3413exit:
3414 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003415 if (out->pcm == NULL) {
3416 ALOGE("%s: %s - %d", __func__, step, ret);
3417 } else {
3418 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003419 pcm_close(out->pcm);
3420 out->pcm = NULL;
3421 }
3422 }
3423 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003424 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003425 return ret;
3426}
3427
3428static int out_get_mmap_position(const struct audio_stream_out *stream,
3429 struct audio_mmap_position *position)
3430{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003431 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003432 struct stream_out *out = (struct stream_out *)stream;
3433 ALOGVV("%s", __func__);
3434 if (position == NULL) {
3435 return -EINVAL;
3436 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003437 lock_output_stream(out);
3438 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3439 out->pcm == NULL) {
3440 ret = -ENOSYS;
3441 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003442 }
3443
3444 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003445 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003446 if (ret < 0) {
3447 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003448 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003449 }
Andy Hungfc044e12017-03-20 09:24:22 -07003450 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003451exit:
3452 pthread_mutex_unlock(&out->lock);
3453 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003454}
3455
3456
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003457/** audio_stream_in implementation **/
3458static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3459{
3460 struct stream_in *in = (struct stream_in *)stream;
3461
3462 return in->config.rate;
3463}
3464
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003465static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003466{
3467 return -ENOSYS;
3468}
3469
3470static size_t in_get_buffer_size(const struct audio_stream *stream)
3471{
3472 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003473 return in->config.period_size * in->af_period_multiplier *
3474 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003475}
3476
3477static uint32_t in_get_channels(const struct audio_stream *stream)
3478{
3479 struct stream_in *in = (struct stream_in *)stream;
3480
3481 return in->channel_mask;
3482}
3483
vivek mehta4ed66e62016-04-15 23:33:34 -07003484static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003485{
vivek mehta4ed66e62016-04-15 23:33:34 -07003486 struct stream_in *in = (struct stream_in *)stream;
3487 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003488}
3489
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003490static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003491{
3492 return -ENOSYS;
3493}
3494
3495static int in_standby(struct audio_stream *stream)
3496{
3497 struct stream_in *in = (struct stream_in *)stream;
3498 struct audio_device *adev = in->dev;
3499 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003500 bool do_stop = true;
3501
Eric Laurent994a6932013-07-17 11:51:42 -07003502 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003503
3504 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003505
3506 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003507 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003508 audio_extn_sound_trigger_stop_lab(in);
3509 in->standby = true;
3510 }
3511
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003512 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003513 if (adev->adm_deregister_stream)
3514 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3515
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003516 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003517 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003518 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003519 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003520 in->capture_started = false;
3521 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003522 if (in->pcm) {
3523 pcm_close(in->pcm);
3524 in->pcm = NULL;
3525 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003526 adev->enable_voicerx = false;
3527 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003528 if (do_stop) {
3529 status = stop_input_stream(in);
3530 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003531 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003532 }
3533 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003534 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003535 return status;
3536}
3537
Andy Hungd13f0d32017-06-12 13:58:37 -07003538static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003539{
Andy Hungd13f0d32017-06-12 13:58:37 -07003540 struct stream_in *in = (struct stream_in *)stream;
3541
3542 // We try to get the lock for consistency,
3543 // but it isn't necessary for these variables.
3544 // If we're not in standby, we may be blocked on a read.
3545 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3546 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3547 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3548 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3549
3550 if (locked) {
3551 pthread_mutex_unlock(&in->lock);
3552 }
3553
3554 // dump error info
3555 (void)error_log_dump(
3556 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003557 return 0;
3558}
3559
3560static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3561{
3562 struct stream_in *in = (struct stream_in *)stream;
3563 struct audio_device *adev = in->dev;
3564 struct str_parms *parms;
3565 char *str;
3566 char value[32];
3567 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003568 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003569
Eric Laurent994a6932013-07-17 11:51:42 -07003570 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003571 parms = str_parms_create_str(kvpairs);
3572
3573 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3574
Eric Laurenta1478072015-09-21 17:21:52 -07003575 lock_input_stream(in);
3576
Eric Laurent150dbfe2013-02-27 14:31:02 -08003577 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003578 if (ret >= 0) {
3579 val = atoi(value);
3580 /* no audio source uses val == 0 */
3581 if ((in->source != val) && (val != 0)) {
3582 in->source = val;
3583 }
3584 }
3585
3586 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003587
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003588 if (ret >= 0) {
3589 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003590 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003591
3592 // Workaround: If routing to an non existing usb device, fail gracefully
3593 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003594 int card;
3595 if (audio_is_usb_in_device(val) &&
3596 (card = get_alive_usb_card(parms)) >= 0) {
3597
3598 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003599 status = -ENOSYS;
3600 } else {
3601
3602 in->device = val;
3603 /* If recording is in progress, change the tx device to new device */
3604 if (!in->standby) {
3605 ALOGV("update input routing change");
3606 // inform adm before actual routing to prevent glitches.
3607 if (adev->adm_on_routing_change) {
3608 adev->adm_on_routing_change(adev->adm_data,
3609 in->capture_handle);
3610 }
3611 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003612 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003613 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003614 }
3615 }
3616
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003617 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003618 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003619
3620 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003621 ALOGV("%s: exit: status(%d)", __func__, status);
3622 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003623}
3624
Haynes Mathew George569b7482017-05-08 14:44:27 -07003625static char* in_get_parameters(const struct audio_stream *stream,
3626 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003627{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003628 struct stream_in *in = (struct stream_in *)stream;
3629 struct str_parms *query = str_parms_create_str(keys);
3630 char *str;
3631 struct str_parms *reply = str_parms_create();
3632 bool replied = false;
3633
3634 ALOGV("%s: enter: keys - %s", __func__, keys);
3635 replied |= stream_get_parameter_channels(query, reply,
3636 &in->supported_channel_masks[0]);
3637 replied |= stream_get_parameter_formats(query, reply,
3638 &in->supported_formats[0]);
3639 replied |= stream_get_parameter_rates(query, reply,
3640 &in->supported_sample_rates[0]);
3641 if (replied) {
3642 str = str_parms_to_str(reply);
3643 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003644 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003645 }
3646 str_parms_destroy(query);
3647 str_parms_destroy(reply);
3648 ALOGV("%s: exit: returns - %s", __func__, str);
3649 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003650}
3651
Eric Laurent51f3c662018-04-10 18:21:34 -07003652static int in_set_gain(struct audio_stream_in *stream, float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003653{
Eric Laurent51f3c662018-04-10 18:21:34 -07003654 struct stream_in *in = (struct stream_in *)stream;
3655 char mixer_ctl_name[128];
3656 struct mixer_ctl *ctl;
3657 int ctl_value;
3658
3659 ALOGV("%s: gain %f", __func__, gain);
3660
3661 if (stream == NULL)
3662 return -EINVAL;
3663
3664 /* in_set_gain() only used to silence MMAP capture for now */
3665 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
3666 return -ENOSYS;
3667
3668 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
3669
3670 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
3671 if (!ctl) {
3672 ALOGW("%s: Could not get ctl for mixer cmd - %s",
3673 __func__, mixer_ctl_name);
3674 return -ENOSYS;
3675 }
3676
3677 if (gain < RECORD_GAIN_MIN)
3678 gain = RECORD_GAIN_MIN;
3679 else if (gain > RECORD_GAIN_MAX)
3680 gain = RECORD_GAIN_MAX;
3681 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
3682
3683 mixer_ctl_set_value(ctl, 0, ctl_value);
3684 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003685}
3686
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003687static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3688{
3689 if (!stream || !parms)
3690 return;
3691
3692 struct stream_in *in = (struct stream_in *)stream;
3693 struct audio_device *adev = in->dev;
3694
3695 card_status_t status;
3696 int card;
3697 if (parse_snd_card_status(parms, &card, &status) < 0)
3698 return;
3699
3700 pthread_mutex_lock(&adev->lock);
3701 bool valid_cb = (card == adev->snd_card);
3702 pthread_mutex_unlock(&adev->lock);
3703
3704 if (!valid_cb)
3705 return;
3706
3707 lock_input_stream(in);
3708 if (in->card_status != status)
3709 in->card_status = status;
3710 pthread_mutex_unlock(&in->lock);
3711
3712 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3713 use_case_table[in->usecase],
3714 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3715
3716 // a better solution would be to report error back to AF and let
3717 // it put the stream to standby
3718 if (status == CARD_STATUS_OFFLINE)
3719 in_standby(&in->stream.common);
3720
3721 return;
3722}
3723
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003724static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3725 size_t bytes)
3726{
3727 struct stream_in *in = (struct stream_in *)stream;
3728 struct audio_device *adev = in->dev;
3729 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003730 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003731 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003732
Eric Laurenta1478072015-09-21 17:21:52 -07003733 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003734 const size_t frame_size = audio_stream_in_frame_size(stream);
3735 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003736
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003737 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003738 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003739 /* Read from sound trigger HAL */
3740 audio_extn_sound_trigger_read(in, buffer, bytes);
3741 pthread_mutex_unlock(&in->lock);
3742 return bytes;
3743 }
3744
Eric Laurent0e46adf2016-12-16 12:49:24 -08003745 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3746 ret = -ENOSYS;
3747 goto exit;
3748 }
3749
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003750 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003751 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003752 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003753 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003754 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003755 goto exit;
3756 }
3757 in->standby = 0;
3758 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003759
Andy Hungd13f0d32017-06-12 13:58:37 -07003760 // errors that occur here are read errors.
3761 error_code = ERROR_CODE_READ;
3762
Haynes Mathew George03c40102016-01-29 17:57:48 -08003763 //what's the duration requested by the client?
3764 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3765 in->config.rate;
3766 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003767
Haynes Mathew George03c40102016-01-29 17:57:48 -08003768 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003769 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003770 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003771 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003772 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003773 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003774 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003775 if (ret < 0) {
3776 ALOGE("Failed to read w/err %s", strerror(errno));
3777 ret = -errno;
3778 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003779 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3780 if (bytes % 4 == 0) {
3781 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3782 int_buf_stream = buffer;
3783 for (size_t itt=0; itt < bytes/4 ; itt++) {
3784 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003785 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003786 } else {
3787 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3788 ret = -EINVAL;
3789 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003790 }
3791 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003792 }
3793
Haynes Mathew George03c40102016-01-29 17:57:48 -08003794 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003795
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003796 /*
3797 * Instead of writing zeroes here, we could trust the hardware
3798 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003799 * 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 -08003800 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08003801 if (ret == 0 && adev->mic_muted &&
3802 !voice_is_in_call_rec_stream(in) &&
3803 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003804 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07003805 in->frames_muted += frames;
3806 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003807
3808exit:
3809 pthread_mutex_unlock(&in->lock);
3810
3811 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07003812 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003813 in_standby(&in->stream.common);
3814 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003815 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003816 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07003817 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08003818 }
3819 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003820 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003821 }
3822 return bytes;
3823}
3824
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003825static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003826{
3827 return 0;
3828}
3829
Andy Hung6ebe5962016-01-15 17:46:57 -08003830static int in_get_capture_position(const struct audio_stream_in *stream,
3831 int64_t *frames, int64_t *time)
3832{
3833 if (stream == NULL || frames == NULL || time == NULL) {
3834 return -EINVAL;
3835 }
3836 struct stream_in *in = (struct stream_in *)stream;
3837 int ret = -ENOSYS;
3838
3839 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003840 // note: ST sessions do not close the alsa pcm driver synchronously
3841 // on standby. Therefore, we may return an error even though the
3842 // pcm stream is still opened.
3843 if (in->standby) {
3844 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
3845 "%s stream in standby but pcm not NULL for non ST session", __func__);
3846 goto exit;
3847 }
Andy Hung6ebe5962016-01-15 17:46:57 -08003848 if (in->pcm) {
3849 struct timespec timestamp;
3850 unsigned int avail;
3851 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3852 *frames = in->frames_read + avail;
3853 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3854 ret = 0;
3855 }
3856 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003857exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08003858 pthread_mutex_unlock(&in->lock);
3859 return ret;
3860}
3861
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003862static int add_remove_audio_effect(const struct audio_stream *stream,
3863 effect_handle_t effect,
3864 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003865{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003866 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003867 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003868 int status = 0;
3869 effect_descriptor_t desc;
3870
3871 status = (*effect)->get_descriptor(effect, &desc);
3872 if (status != 0)
3873 return status;
3874
Eric Laurenta1478072015-09-21 17:21:52 -07003875 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003876 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003877 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003878 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003879 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003880 in->enable_aec != enable &&
3881 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3882 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003883 if (!enable)
3884 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003885 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3886 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3887 adev->enable_voicerx = enable;
3888 struct audio_usecase *usecase;
3889 struct listnode *node;
3890 list_for_each(node, &adev->usecase_list) {
3891 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07003892 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07003893 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05003894 }
3895 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003896 if (!in->standby)
3897 select_devices(in->dev, in->usecase);
3898 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003899 if (in->enable_ns != enable &&
3900 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3901 in->enable_ns = enable;
3902 if (!in->standby)
3903 select_devices(in->dev, in->usecase);
3904 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003905 pthread_mutex_unlock(&in->dev->lock);
3906 pthread_mutex_unlock(&in->lock);
3907
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003908 return 0;
3909}
3910
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003911static int in_add_audio_effect(const struct audio_stream *stream,
3912 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003913{
Eric Laurent994a6932013-07-17 11:51:42 -07003914 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003915 return add_remove_audio_effect(stream, effect, true);
3916}
3917
3918static int in_remove_audio_effect(const struct audio_stream *stream,
3919 effect_handle_t effect)
3920{
Eric Laurent994a6932013-07-17 11:51:42 -07003921 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003922 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003923}
3924
Eric Laurent0e46adf2016-12-16 12:49:24 -08003925static int in_stop(const struct audio_stream_in* stream)
3926{
3927 struct stream_in *in = (struct stream_in *)stream;
3928 struct audio_device *adev = in->dev;
3929
3930 int ret = -ENOSYS;
3931 ALOGV("%s", __func__);
3932 pthread_mutex_lock(&adev->lock);
3933 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3934 in->capture_started && in->pcm != NULL) {
3935 pcm_stop(in->pcm);
3936 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003937 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003938 }
3939 pthread_mutex_unlock(&adev->lock);
3940 return ret;
3941}
3942
3943static int in_start(const struct audio_stream_in* stream)
3944{
3945 struct stream_in *in = (struct stream_in *)stream;
3946 struct audio_device *adev = in->dev;
3947 int ret = -ENOSYS;
3948
3949 ALOGV("%s in %p", __func__, in);
3950 pthread_mutex_lock(&adev->lock);
3951 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3952 !in->capture_started && in->pcm != NULL) {
3953 if (!in->capture_started) {
3954 ret = start_input_stream(in);
3955 if (ret == 0) {
3956 in->capture_started = true;
3957 }
3958 }
3959 }
3960 pthread_mutex_unlock(&adev->lock);
3961 return ret;
3962}
3963
3964static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3965 int32_t min_size_frames,
3966 struct audio_mmap_buffer_info *info)
3967{
3968 struct stream_in *in = (struct stream_in *)stream;
3969 struct audio_device *adev = in->dev;
3970 int ret = 0;
3971 unsigned int offset1;
3972 unsigned int frames1;
3973 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003974 uint32_t mmap_size;
3975 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003976
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003977 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003978 pthread_mutex_lock(&adev->lock);
3979 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003980
Eric Laurent0e46adf2016-12-16 12:49:24 -08003981 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003982 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003983 ret = -EINVAL;
3984 goto exit;
3985 }
3986 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003987 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003988 ALOGV("%s in %p", __func__, in);
3989 ret = -ENOSYS;
3990 goto exit;
3991 }
3992 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3993 if (in->pcm_device_id < 0) {
3994 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3995 __func__, in->pcm_device_id, in->usecase);
3996 ret = -EINVAL;
3997 goto exit;
3998 }
Phil Burkbc991042017-02-24 08:06:44 -08003999
4000 adjust_mmap_period_count(&in->config, min_size_frames);
4001
Eric Laurent0e46adf2016-12-16 12:49:24 -08004002 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4003 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
4004 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
4005 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
4006 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
4007 step = "open";
4008 ret = -ENODEV;
4009 goto exit;
4010 }
4011
4012 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
4013 if (ret < 0) {
4014 step = "begin";
4015 goto exit;
4016 }
4017 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07004018 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004019 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07004020 ret = platform_get_mmap_data_fd(adev->platform,
4021 in->pcm_device_id, 1 /*capture*/,
4022 &info->shared_memory_fd,
4023 &mmap_size);
4024 if (ret < 0) {
4025 // Fall back to non exclusive mode
4026 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
4027 } else {
4028 if (mmap_size < buffer_size) {
4029 step = "mmap";
4030 goto exit;
4031 }
4032 // FIXME: indicate exclusive mode support by returning a negative buffer size
4033 info->buffer_size_frames *= -1;
4034 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08004035
Haynes Mathew George96483a22017-03-28 14:52:47 -07004036 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004037
4038 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4039 if (ret < 0) {
4040 step = "commit";
4041 goto exit;
4042 }
4043
Phil Burkbc991042017-02-24 08:06:44 -08004044 in->standby = false;
4045 ret = 0;
4046
Eric Laurent0e46adf2016-12-16 12:49:24 -08004047 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4048 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004049
4050exit:
4051 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004052 if (in->pcm == NULL) {
4053 ALOGE("%s: %s - %d", __func__, step, ret);
4054 } else {
4055 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08004056 pcm_close(in->pcm);
4057 in->pcm = NULL;
4058 }
4059 }
4060 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004061 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004062 return ret;
4063}
4064
4065static int in_get_mmap_position(const struct audio_stream_in *stream,
4066 struct audio_mmap_position *position)
4067{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004068 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004069 struct stream_in *in = (struct stream_in *)stream;
4070 ALOGVV("%s", __func__);
4071 if (position == NULL) {
4072 return -EINVAL;
4073 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004074 lock_input_stream(in);
4075 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
4076 in->pcm == NULL) {
4077 ret = -ENOSYS;
4078 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004079 }
4080 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004081 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004082 if (ret < 0) {
4083 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004084 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004085 }
Andy Hungfc044e12017-03-20 09:24:22 -07004086 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004087exit:
4088 pthread_mutex_unlock(&in->lock);
4089 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004090}
4091
jiabin8962a4d2018-03-19 18:21:24 -07004092static int in_get_active_microphones(const struct audio_stream_in *stream,
4093 struct audio_microphone_characteristic_t *mic_array,
4094 size_t *mic_count) {
4095 struct stream_in *in = (struct stream_in *)stream;
4096 struct audio_device *adev = in->dev;
4097 ALOGVV("%s", __func__);
4098
4099 lock_input_stream(in);
4100 pthread_mutex_lock(&adev->lock);
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004101 int ret = platform_get_active_microphones(adev->platform,
jiabin8962a4d2018-03-19 18:21:24 -07004102 audio_channel_count_from_in_mask(in->channel_mask),
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004103 in->usecase, mic_array, mic_count);
jiabin8962a4d2018-03-19 18:21:24 -07004104 pthread_mutex_unlock(&adev->lock);
4105 pthread_mutex_unlock(&in->lock);
4106
4107 return ret;
4108}
4109
4110static int adev_get_microphones(const struct audio_hw_device *dev,
4111 struct audio_microphone_characteristic_t *mic_array,
4112 size_t *mic_count) {
4113 struct audio_device *adev = (struct audio_device *)dev;
4114 ALOGVV("%s", __func__);
4115
4116 pthread_mutex_lock(&adev->lock);
4117 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
4118 pthread_mutex_unlock(&adev->lock);
4119
4120 return ret;
4121}
Eric Laurent0e46adf2016-12-16 12:49:24 -08004122
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004123static int adev_open_output_stream(struct audio_hw_device *dev,
4124 audio_io_handle_t handle,
4125 audio_devices_t devices,
4126 audio_output_flags_t flags,
4127 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07004128 struct audio_stream_out **stream_out,
4129 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004130{
4131 struct audio_device *adev = (struct audio_device *)dev;
4132 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004133 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004134 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
4135 bool is_usb_dev = audio_is_usb_out_device(devices) &&
4136 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004137
Andy Hungd9653bd2017-08-01 19:31:39 -07004138 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
4139 return -ENOSYS;
4140 }
4141
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004142 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
4143 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004144 *stream_out = NULL;
4145 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4146
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004147 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
4148
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004149 if (devices == AUDIO_DEVICE_NONE)
4150 devices = AUDIO_DEVICE_OUT_SPEAKER;
4151
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004152 out->flags = flags;
4153 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004154 out->dev = adev;
Eric Laurentc4aef752013-09-12 17:45:53 -07004155 out->handle = handle;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004156 out->a2dp_compress_mute = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004157
4158 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004159 if ((is_hdmi || is_usb_dev) &&
4160 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
4161 (flags == AUDIO_OUTPUT_FLAG_NONE ||
4162 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Eric Laurentab805ee2018-03-30 12:20:38 -07004163 audio_format_t req_format = config->format;
4164 audio_channel_mask_t req_channel_mask = config->channel_mask;
4165 uint32_t req_sample_rate = config->sample_rate;
4166
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004167 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004168 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004169 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004170 if (config->sample_rate == 0)
4171 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Eric Laurentab805ee2018-03-30 12:20:38 -07004172 if (config->channel_mask == AUDIO_CHANNEL_NONE)
Haynes Mathew George569b7482017-05-08 14:44:27 -07004173 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
4174 if (config->format == AUDIO_FORMAT_DEFAULT)
4175 config->format = AUDIO_FORMAT_PCM_16_BIT;
4176 } else if (is_usb_dev) {
4177 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
4178 &config->format,
4179 &out->supported_formats[0],
4180 MAX_SUPPORTED_FORMATS,
4181 &config->channel_mask,
4182 &out->supported_channel_masks[0],
4183 MAX_SUPPORTED_CHANNEL_MASKS,
4184 &config->sample_rate,
4185 &out->supported_sample_rates[0],
4186 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004187 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004188 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004189 pthread_mutex_unlock(&adev->lock);
Eric Laurentab805ee2018-03-30 12:20:38 -07004190 if (ret != 0) {
4191 // For MMAP NO IRQ, allow conversions in ADSP
4192 if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
4193 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004194
Eric Laurentab805ee2018-03-30 12:20:38 -07004195 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
4196 config->sample_rate = req_sample_rate;
4197 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
4198 config->channel_mask = req_channel_mask;
4199 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
4200 config->format = req_format;
4201 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004202
Haynes Mathew George569b7482017-05-08 14:44:27 -07004203 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004204 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004205 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004206 if (is_hdmi) {
4207 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4208 out->config = pcm_config_hdmi_multi;
4209 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
4210 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4211 out->config = pcm_config_mmap_playback;
4212 out->stream.start = out_start;
4213 out->stream.stop = out_stop;
4214 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4215 out->stream.get_mmap_position = out_get_mmap_position;
4216 } else {
4217 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4218 out->config = pcm_config_hifi;
4219 }
4220
4221 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004222 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004223 if (is_hdmi) {
4224 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
4225 audio_bytes_per_sample(out->format));
4226 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004227 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004228 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07004229 pthread_mutex_lock(&adev->lock);
4230 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4231 pthread_mutex_unlock(&adev->lock);
4232
4233 // reject offload during card offline to allow
4234 // fallback to s/w paths
4235 if (offline) {
4236 ret = -ENODEV;
4237 goto error_open;
4238 }
4239
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004240 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4241 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4242 ALOGE("%s: Unsupported Offload information", __func__);
4243 ret = -EINVAL;
4244 goto error_open;
4245 }
4246 if (!is_supported_format(config->offload_info.format)) {
4247 ALOGE("%s: Unsupported audio format", __func__);
4248 ret = -EINVAL;
4249 goto error_open;
4250 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004251 out->sample_rate = config->offload_info.sample_rate;
4252 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
4253 out->channel_mask = config->offload_info.channel_mask;
4254 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
4255 out->channel_mask = config->channel_mask;
4256 else
4257 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4258
4259 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004260
4261 out->compr_config.codec = (struct snd_codec *)
4262 calloc(1, sizeof(struct snd_codec));
4263
4264 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004265
4266 out->stream.set_callback = out_set_callback;
4267 out->stream.pause = out_pause;
4268 out->stream.resume = out_resume;
4269 out->stream.drain = out_drain;
4270 out->stream.flush = out_flush;
4271
4272 out->compr_config.codec->id =
4273 get_snd_codec_id(config->offload_info.format);
4274 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
4275 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004276 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004277 out->compr_config.codec->bit_rate =
4278 config->offload_info.bit_rate;
4279 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004280 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004281 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
4282
4283 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4284 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004285
4286 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004287 create_offload_callback_thread(out);
4288 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4289 __func__, config->offload_info.version,
4290 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02004291 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4292 switch (config->sample_rate) {
4293 case 0:
4294 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4295 break;
4296 case 8000:
4297 case 16000:
4298 case 48000:
4299 out->sample_rate = config->sample_rate;
4300 break;
4301 default:
4302 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
4303 config->sample_rate);
4304 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4305 ret = -EINVAL;
4306 goto error_open;
4307 }
4308 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4309 switch (config->channel_mask) {
4310 case AUDIO_CHANNEL_NONE:
4311 case AUDIO_CHANNEL_OUT_STEREO:
4312 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4313 break;
4314 default:
4315 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
4316 config->channel_mask);
4317 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4318 ret = -EINVAL;
4319 goto error_open;
4320 }
4321 switch (config->format) {
4322 case AUDIO_FORMAT_DEFAULT:
4323 case AUDIO_FORMAT_PCM_16_BIT:
4324 out->format = AUDIO_FORMAT_PCM_16_BIT;
4325 break;
4326 default:
4327 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
4328 config->format);
4329 config->format = AUDIO_FORMAT_PCM_16_BIT;
4330 ret = -EINVAL;
4331 goto error_open;
4332 }
4333
4334 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004335 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004336 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004337 case 0:
4338 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
4339 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07004340 case 8000:
4341 case 16000:
4342 case 48000:
4343 out->sample_rate = config->sample_rate;
4344 break;
4345 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004346 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
4347 config->sample_rate);
4348 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4349 ret = -EINVAL;
4350 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004351 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004352 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4353 switch (config->channel_mask) {
4354 case AUDIO_CHANNEL_NONE:
4355 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4356 break;
4357 case AUDIO_CHANNEL_OUT_STEREO:
4358 out->channel_mask = config->channel_mask;
4359 break;
4360 default:
4361 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
4362 config->channel_mask);
4363 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4364 ret = -EINVAL;
4365 break;
4366 }
4367 switch (config->format) {
4368 case AUDIO_FORMAT_DEFAULT:
4369 out->format = AUDIO_FORMAT_PCM_16_BIT;
4370 break;
4371 case AUDIO_FORMAT_PCM_16_BIT:
4372 out->format = config->format;
4373 break;
4374 default:
4375 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
4376 config->format);
4377 config->format = AUDIO_FORMAT_PCM_16_BIT;
4378 ret = -EINVAL;
4379 break;
4380 }
4381 if (ret != 0)
4382 goto error_open;
4383
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004384 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4385 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004386 out->config.rate = out->sample_rate;
4387 out->config.channels =
4388 audio_channel_count_from_out_mask(out->channel_mask);
4389 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004390 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004391 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
4392 switch (config->sample_rate) {
4393 case 0:
4394 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4395 break;
4396 case 8000:
4397 case 16000:
4398 case 32000:
4399 case 48000:
4400 out->sample_rate = config->sample_rate;
4401 break;
4402 default:
4403 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
4404 config->sample_rate);
4405 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4406 ret = -EINVAL;
4407 break;
4408 }
Eric Laurentad2dde92017-09-20 18:27:31 -07004409 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004410 switch (config->channel_mask) {
4411 case AUDIO_CHANNEL_NONE:
4412 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4413 break;
4414 case AUDIO_CHANNEL_OUT_STEREO:
4415 out->channel_mask = config->channel_mask;
4416 break;
4417 default:
4418 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
4419 config->channel_mask);
4420 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4421 ret = -EINVAL;
4422 break;
4423 }
4424 switch (config->format) {
4425 case AUDIO_FORMAT_DEFAULT:
4426 out->format = AUDIO_FORMAT_PCM_16_BIT;
4427 break;
4428 case AUDIO_FORMAT_PCM_16_BIT:
4429 out->format = config->format;
4430 break;
4431 default:
4432 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
4433 config->format);
4434 config->format = AUDIO_FORMAT_PCM_16_BIT;
4435 ret = -EINVAL;
4436 break;
4437 }
4438 if (ret != 0)
4439 goto error_open;
4440
vivek mehtaa68fea62017-06-08 19:04:02 -07004441 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07004442 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4443 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004444 out->config.rate = out->sample_rate;
4445 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07004446 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004447 out->sample_rate,
4448 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07004449 out->config.channels,
4450 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004451 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07004452 out->config.period_size = buffer_size / frame_size;
4453 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
4454 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004455 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004456 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07004457 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4458 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004459 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07004460 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
4461 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004462 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07004463 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004464 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004465 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004466 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004467 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4468 out->config = pcm_config_mmap_playback;
4469 out->stream.start = out_start;
4470 out->stream.stop = out_stop;
4471 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4472 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004473 } else {
4474 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4475 out->config = pcm_config_low_latency;
4476 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004477
4478 if (config->sample_rate == 0) {
4479 out->sample_rate = out->config.rate;
4480 } else {
4481 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004482 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004483 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
4484 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
4485 } else {
4486 out->channel_mask = config->channel_mask;
4487 }
4488 if (config->format == AUDIO_FORMAT_DEFAULT)
4489 out->format = audio_format_from_pcm_format(out->config.format);
4490 else if (!audio_is_linear_pcm(config->format)) {
4491 config->format = AUDIO_FORMAT_PCM_16_BIT;
4492 ret = -EINVAL;
4493 goto error_open;
4494 } else {
4495 out->format = config->format;
4496 }
4497
4498 out->config.rate = out->sample_rate;
4499 out->config.channels =
4500 audio_channel_count_from_out_mask(out->channel_mask);
4501 if (out->format != audio_format_from_pcm_format(out->config.format)) {
4502 out->config.format = pcm_format_from_audio_format(out->format);
4503 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004504 }
Kevin Rocard50eff892017-05-02 16:52:05 -07004505
4506 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
4507 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004508 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004509 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
4510 __func__, config->sample_rate, config->format, config->channel_mask);
4511 config->sample_rate = out->sample_rate;
4512 config->format = out->format;
4513 config->channel_mask = out->channel_mask;
4514 ret = -EINVAL;
4515 goto error_open;
4516 }
4517
Andy Hung6fcba9c2014-03-18 11:53:32 -07004518 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
4519 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004520
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004521 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004522 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004523 adev->primary_output = out;
4524 else {
4525 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004526 ret = -EEXIST;
4527 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004528 }
4529 }
4530
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004531 /* Check if this usecase is already existing */
4532 pthread_mutex_lock(&adev->lock);
4533 if (get_usecase_from_list(adev, out->usecase) != NULL) {
4534 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004535 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004536 ret = -EEXIST;
4537 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004538 }
4539 pthread_mutex_unlock(&adev->lock);
4540
4541 out->stream.common.get_sample_rate = out_get_sample_rate;
4542 out->stream.common.set_sample_rate = out_set_sample_rate;
4543 out->stream.common.get_buffer_size = out_get_buffer_size;
4544 out->stream.common.get_channels = out_get_channels;
4545 out->stream.common.get_format = out_get_format;
4546 out->stream.common.set_format = out_set_format;
4547 out->stream.common.standby = out_standby;
4548 out->stream.common.dump = out_dump;
4549 out->stream.common.set_parameters = out_set_parameters;
4550 out->stream.common.get_parameters = out_get_parameters;
4551 out->stream.common.add_audio_effect = out_add_audio_effect;
4552 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4553 out->stream.get_latency = out_get_latency;
4554 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004555#ifdef NO_AUDIO_OUT
4556 out->stream.write = out_write_for_no_output;
4557#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004558 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004559#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004560 out->stream.get_render_position = out_get_render_position;
4561 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004562 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004563
Eric Laurent0e46adf2016-12-16 12:49:24 -08004564 if (out->realtime)
4565 out->af_period_multiplier = af_period_multiplier;
4566 else
4567 out->af_period_multiplier = 1;
4568
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004569 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004570 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004571 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004572
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004573 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004574 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004575 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4576
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004577 config->format = out->stream.common.get_format(&out->stream.common);
4578 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4579 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4580
Kevin Rocarda325aa22018-04-03 09:15:52 -07004581 register_format(out->format, out->supported_formats);
4582 register_channel_mask(out->channel_mask, out->supported_channel_masks);
4583 register_sample_rate(out->sample_rate, out->supported_sample_rates);
4584
Andy Hunga452b0a2017-03-15 14:51:15 -07004585 out->error_log = error_log_create(
4586 ERROR_LOG_ENTRIES,
4587 1000000000 /* aggregate consecutive identical errors within one second in ns */);
4588
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004589 /*
4590 By locking output stream before registering, we allow the callback
4591 to update stream's state only after stream's initial state is set to
4592 adev state.
4593 */
4594 lock_output_stream(out);
4595 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4596 pthread_mutex_lock(&adev->lock);
4597 out->card_status = adev->card_status;
4598 pthread_mutex_unlock(&adev->lock);
4599 pthread_mutex_unlock(&out->lock);
4600
vivek mehta4a824772017-06-08 19:05:49 -07004601 stream_app_type_cfg_init(&out->app_type_cfg);
4602
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004603 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004604
Eric Laurent994a6932013-07-17 11:51:42 -07004605 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004606 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004607
4608error_open:
4609 free(out);
4610 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07004611 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004612 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004613}
4614
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004615static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004616 struct audio_stream_out *stream)
4617{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004618 struct stream_out *out = (struct stream_out *)stream;
4619 struct audio_device *adev = out->dev;
4620
Eric Laurent994a6932013-07-17 11:51:42 -07004621 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004622
4623 // must deregister from sndmonitor first to prevent races
4624 // between the callback and close_stream
4625 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004626 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004627 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
4628 destroy_offload_callback_thread(out);
4629
4630 if (out->compr_config.codec != NULL)
4631 free(out->compr_config.codec);
4632 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004633
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004634 out->a2dp_compress_mute = false;
4635
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004636 if (adev->voice_tx_output == out)
4637 adev->voice_tx_output = NULL;
4638
Andy Hunga452b0a2017-03-15 14:51:15 -07004639 error_log_destroy(out->error_log);
4640 out->error_log = NULL;
4641
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004642 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004643 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004644 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004645 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004646 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004647}
4648
4649static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4650{
4651 struct audio_device *adev = (struct audio_device *)dev;
4652 struct str_parms *parms;
4653 char *str;
4654 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004655 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004656 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07004657 int status = 0;
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004658 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004659
Joe Onorato188b6222016-03-01 11:02:27 -08004660 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004661
4662 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004663
4664 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004665 status = voice_set_parameters(adev, parms);
4666 if (status != 0) {
4667 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004668 }
4669
4670 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4671 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07004672 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004673 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4674 adev->bluetooth_nrec = true;
4675 else
4676 adev->bluetooth_nrec = false;
4677 }
4678
4679 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4680 if (ret >= 0) {
4681 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4682 adev->screen_off = false;
4683 else
4684 adev->screen_off = true;
4685 }
4686
jasmine cha270b7762018-03-30 15:41:33 +08004687#ifndef MAXXAUDIO_QDSP_ENABLED
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004688 ret = str_parms_get_int(parms, "rotation", &val);
4689 if (ret >= 0) {
4690 bool reverse_speakers = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004691 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004692 // FIXME: note that the code below assumes that the speakers are in the correct placement
4693 // relative to the user when the device is rotated 90deg from its default rotation. This
4694 // assumption is device-specific, not platform-specific like this code.
4695 case 270:
4696 reverse_speakers = true;
4697 break;
4698 case 0:
4699 case 90:
4700 case 180:
4701 break;
4702 default:
4703 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07004704 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004705 }
Eric Laurent03f09432014-03-25 18:09:11 -07004706 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004707 // check and set swap
4708 // - check if orientation changed and speaker active
4709 // - set rotation and cache the rotation value
4710 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004711 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004712 }
jasmine cha270b7762018-03-30 15:41:33 +08004713#endif
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004714
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004715 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4716 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004717 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004718 }
4719
David Linee3fe402017-03-13 10:00:42 -07004720 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4721 if (ret >= 0) {
4722 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004723 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004724 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4725 if (ret >= 0) {
4726 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004727 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004728 }
Eric Laurent99dab492017-06-17 15:19:08 -07004729 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004730 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4731 if (ret >= 0) {
4732 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004733 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004734 }
4735 }
4736 }
4737
4738 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4739 if (ret >= 0) {
4740 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004741 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004742 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4743 if (ret >= 0) {
4744 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004745 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004746 }
Eric Laurent99dab492017-06-17 15:19:08 -07004747 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004748 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4749 if (ret >= 0) {
4750 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004751 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004752 }
4753 }
4754 }
4755
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004756 audio_extn_hfp_set_parameters(adev, parms);
jasmine cha270b7762018-03-30 15:41:33 +08004757 audio_extn_ma_set_parameters(adev, parms);
4758
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004759 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
4760 if (status >= 0 && a2dp_reconfig) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004761 struct audio_usecase *usecase;
4762 struct listnode *node;
4763 list_for_each(node, &adev->usecase_list) {
4764 usecase = node_to_item(node, struct audio_usecase, list);
4765 if ((usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004766 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004767 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
4768
4769 pthread_mutex_unlock(&adev->lock);
4770 lock_output_stream(usecase->stream.out);
4771 pthread_mutex_lock(&adev->lock);
4772 audio_extn_a2dp_set_handoff_mode(true);
4773 // force device switch to reconfigure encoder
4774 select_devices(adev, usecase->id);
4775 audio_extn_a2dp_set_handoff_mode(false);
4776 pthread_mutex_unlock(&usecase->stream.out->lock);
4777 break;
4778 }
4779 }
4780 }
4781
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004782done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004783 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004784 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004785 ALOGV("%s: exit with code(%d)", __func__, status);
4786 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004787}
4788
4789static char* adev_get_parameters(const struct audio_hw_device *dev,
4790 const char *keys)
4791{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004792 struct audio_device *adev = (struct audio_device *)dev;
4793 struct str_parms *reply = str_parms_create();
4794 struct str_parms *query = str_parms_create_str(keys);
4795 char *str;
4796
4797 pthread_mutex_lock(&adev->lock);
4798
4799 voice_get_parameters(adev, query, reply);
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004800 audio_extn_a2dp_get_parameters(query, reply);
4801
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004802 str = str_parms_to_str(reply);
4803 str_parms_destroy(query);
4804 str_parms_destroy(reply);
4805
4806 pthread_mutex_unlock(&adev->lock);
4807 ALOGV("%s: exit: returns - %s", __func__, str);
4808 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004809}
4810
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004811static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004812{
4813 return 0;
4814}
4815
Haynes Mathew George5191a852013-09-11 14:19:36 -07004816static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4817{
4818 int ret;
4819 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004820
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004821 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4822
Haynes Mathew George5191a852013-09-11 14:19:36 -07004823 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004824 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004825 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004826
Haynes Mathew George5191a852013-09-11 14:19:36 -07004827 return ret;
4828}
4829
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004830static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004831{
4832 return -ENOSYS;
4833}
4834
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004835static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4836 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004837{
4838 return -ENOSYS;
4839}
4840
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004841static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004842{
4843 return -ENOSYS;
4844}
4845
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004846static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004847{
4848 return -ENOSYS;
4849}
4850
4851static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4852{
4853 struct audio_device *adev = (struct audio_device *)dev;
4854
4855 pthread_mutex_lock(&adev->lock);
4856 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004857 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004858 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004859 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4860 voice_is_in_call(adev)) {
4861 voice_stop_call(adev);
4862 adev->current_call_output = NULL;
4863 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004864 }
4865 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004866
4867 audio_extn_extspk_set_mode(adev->extspk, mode);
4868
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004869 return 0;
4870}
4871
4872static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4873{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004874 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004875 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004876
Eric Laurent2bafff12016-03-17 12:17:23 -07004877 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004878 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004879 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4880 ret = audio_extn_hfp_set_mic_mute(adev, state);
4881 } else {
4882 ret = voice_set_mic_mute(adev, state);
4883 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004884 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004885 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004886
4887 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004888}
4889
4890static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4891{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004892 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004893 return 0;
4894}
4895
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004896static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004897 const struct audio_config *config)
4898{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004899 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004900
Eric Laurent74b55762017-07-09 17:04:53 -07004901 /* Don't know if USB HIFI in this context so use true to be conservative */
4902 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4903 true /*is_usb_hifi */) != 0)
4904 return 0;
4905
vivek mehtaa68fea62017-06-08 19:04:02 -07004906 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4907 config->sample_rate, config->format,
4908 channel_count,
4909 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004910}
4911
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004912static bool adev_input_allow_hifi_record(struct audio_device *adev,
4913 audio_devices_t devices,
4914 audio_input_flags_t flags,
4915 audio_source_t source) {
4916 const bool allowed = true;
4917
4918 if (!audio_is_usb_in_device(devices))
4919 return !allowed;
4920
4921 switch (flags) {
4922 case AUDIO_INPUT_FLAG_NONE:
4923 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4924 break;
4925 default:
4926 return !allowed;
4927 }
4928
4929 switch (source) {
4930 case AUDIO_SOURCE_DEFAULT:
4931 case AUDIO_SOURCE_MIC:
4932 case AUDIO_SOURCE_UNPROCESSED:
4933 break;
4934 default:
4935 return !allowed;
4936 }
4937
4938 switch (adev->mode) {
4939 case 0:
4940 break;
4941 default:
4942 return !allowed;
4943 }
4944
4945 return allowed;
4946}
4947
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004948static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004949 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004950 audio_devices_t devices,
4951 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004952 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004953 audio_input_flags_t flags,
4954 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004955 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004956{
4957 struct audio_device *adev = (struct audio_device *)dev;
4958 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004959 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004960 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004961 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004962 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004963 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4964 devices,
4965 flags,
4966 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004967 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004968 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004969
Andy Hungd9653bd2017-08-01 19:31:39 -07004970 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
4971 return -ENOSYS;
4972 }
4973
Eric Laurent74b55762017-07-09 17:04:53 -07004974 if (!(is_usb_dev && may_use_hifi_record)) {
4975 if (config->sample_rate == 0)
4976 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4977 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4978 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4979 if (config->format == AUDIO_FORMAT_DEFAULT)
4980 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004981
Eric Laurent74b55762017-07-09 17:04:53 -07004982 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
4983
4984 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
4985 return -EINVAL;
4986 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004987
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004988 if (audio_extn_tfa_98xx_is_supported() &&
4989 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004990 return -EINVAL;
4991
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004992 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4993
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004994 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004995 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004996
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004997 in->stream.common.get_sample_rate = in_get_sample_rate;
4998 in->stream.common.set_sample_rate = in_set_sample_rate;
4999 in->stream.common.get_buffer_size = in_get_buffer_size;
5000 in->stream.common.get_channels = in_get_channels;
5001 in->stream.common.get_format = in_get_format;
5002 in->stream.common.set_format = in_set_format;
5003 in->stream.common.standby = in_standby;
5004 in->stream.common.dump = in_dump;
5005 in->stream.common.set_parameters = in_set_parameters;
5006 in->stream.common.get_parameters = in_get_parameters;
5007 in->stream.common.add_audio_effect = in_add_audio_effect;
5008 in->stream.common.remove_audio_effect = in_remove_audio_effect;
5009 in->stream.set_gain = in_set_gain;
5010 in->stream.read = in_read;
5011 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08005012 in->stream.get_capture_position = in_get_capture_position;
jiabin8962a4d2018-03-19 18:21:24 -07005013 in->stream.get_active_microphones = in_get_active_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005014
5015 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005016 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005017 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005018 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005019 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005020 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005021
Arun Mirpuriba2749a2018-04-17 14:32:24 -07005022 ALOGV("%s: source = %d, config->channel_mask = %d", __func__, source, config->channel_mask);
5023 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
5024 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
5025 /* Force channel config requested to mono if incall
5026 record is being requested for only uplink/downlink */
5027 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
5028 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5029 ret = -EINVAL;
5030 goto err_open;
5031 }
5032 }
5033
Haynes Mathew George569b7482017-05-08 14:44:27 -07005034 if (is_usb_dev && may_use_hifi_record) {
5035 /* HiFi record selects an appropriate format, channel, rate combo
5036 depending on sink capabilities*/
5037 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
5038 &config->format,
5039 &in->supported_formats[0],
5040 MAX_SUPPORTED_FORMATS,
5041 &config->channel_mask,
5042 &in->supported_channel_masks[0],
5043 MAX_SUPPORTED_CHANNEL_MASKS,
5044 &config->sample_rate,
5045 &in->supported_sample_rates[0],
5046 MAX_SUPPORTED_SAMPLE_RATES);
5047 if (ret != 0) {
5048 ret = -EINVAL;
5049 goto err_open;
5050 }
Eric Laurent74b55762017-07-09 17:04:53 -07005051 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005052 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07005053 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07005054 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
5055 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
5056 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5057 bool ret_error = false;
5058 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5059 from HAL is 8_24
5060 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5061 8_24 return error indicating supported format is 8_24
5062 *> In case of any other source requesting 24 bit or float return error
5063 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07005064
vivek mehta57ff9b52016-04-28 14:13:08 -07005065 on error flinger will retry with supported format passed
5066 */
5067 if (source != AUDIO_SOURCE_UNPROCESSED) {
5068 config->format = AUDIO_FORMAT_PCM_16_BIT;
5069 ret_error = true;
5070 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
5071 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
5072 ret_error = true;
5073 }
5074
5075 if (ret_error) {
5076 ret = -EINVAL;
5077 goto err_open;
5078 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005079 }
5080
vivek mehta57ff9b52016-04-28 14:13:08 -07005081 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07005082 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07005083
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005084 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005085 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
5086 if (config->sample_rate == 0)
5087 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5088 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5089 config->sample_rate != 8000) {
5090 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5091 ret = -EINVAL;
5092 goto err_open;
5093 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005094
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005095 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5096 config->format = AUDIO_FORMAT_PCM_16_BIT;
5097 ret = -EINVAL;
5098 goto err_open;
5099 }
5100
5101 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5102 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07005103 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005104 } else if (is_usb_dev && may_use_hifi_record) {
5105 in->usecase = USECASE_AUDIO_RECORD_HIFI;
5106 in->config = pcm_config_audio_capture;
5107 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005108 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5109 config->sample_rate,
5110 config->format,
5111 channel_count,
5112 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005113 in->config.period_size = buffer_size / frame_size;
5114 in->config.rate = config->sample_rate;
5115 in->af_period_multiplier = 1;
5116 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005117 } else {
5118 in->usecase = USECASE_AUDIO_RECORD;
5119 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08005120 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005121 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07005122#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005123 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07005124#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08005125 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005126 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08005127 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005128 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005129 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5130 config->sample_rate,
5131 config->format,
5132 channel_count,
5133 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005134 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005135 in->config.rate = config->sample_rate;
5136 in->af_period_multiplier = 1;
5137 } else {
5138 // period size is left untouched for rt mode playback
5139 in->config = pcm_config_audio_capture_rt;
5140 in->af_period_multiplier = af_period_multiplier;
5141 }
5142 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
5143 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005144 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08005145 in->usecase = USECASE_AUDIO_RECORD_MMAP;
5146 in->config = pcm_config_mmap_capture;
5147 in->stream.start = in_start;
5148 in->stream.stop = in_stop;
5149 in->stream.create_mmap_buffer = in_create_mmap_buffer;
5150 in->stream.get_mmap_position = in_get_mmap_position;
5151 in->af_period_multiplier = 1;
5152 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07005153 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07005154 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07005155 (config->sample_rate == 8000 ||
5156 config->sample_rate == 16000 ||
5157 config->sample_rate == 32000 ||
5158 config->sample_rate == 48000) &&
5159 channel_count == 1) {
5160 in->usecase = USECASE_AUDIO_RECORD_VOIP;
5161 in->config = pcm_config_audio_capture;
5162 frame_size = audio_stream_in_frame_size(&in->stream);
5163 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
5164 config->sample_rate,
5165 config->format,
5166 channel_count, false /*is_low_latency*/);
5167 in->config.period_size = buffer_size / frame_size;
5168 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
5169 in->config.rate = config->sample_rate;
5170 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005171 } else {
5172 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005173 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005174 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5175 config->sample_rate,
5176 config->format,
5177 channel_count,
5178 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005179 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005180 in->config.rate = config->sample_rate;
5181 in->af_period_multiplier = 1;
5182 }
5183 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
5184 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005185 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08005186
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005187 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07005188 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005189
Kevin Rocarda325aa22018-04-03 09:15:52 -07005190
5191 register_format(in->format, in->supported_formats);
5192 register_channel_mask(in->channel_mask, in->supported_channel_masks);
5193 register_sample_rate(in->sample_rate, in->supported_sample_rates);
5194
Andy Hungd13f0d32017-06-12 13:58:37 -07005195 in->error_log = error_log_create(
5196 ERROR_LOG_ENTRIES,
5197 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
5198
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005199 /* This stream could be for sound trigger lab,
5200 get sound trigger pcm if present */
5201 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005202
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005203 lock_input_stream(in);
5204 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5205 pthread_mutex_lock(&adev->lock);
5206 in->card_status = adev->card_status;
5207 pthread_mutex_unlock(&adev->lock);
5208 pthread_mutex_unlock(&in->lock);
5209
vivek mehta4a824772017-06-08 19:05:49 -07005210 stream_app_type_cfg_init(&in->app_type_cfg);
5211
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005212 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005213 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005214 return 0;
5215
5216err_open:
5217 free(in);
5218 *stream_in = NULL;
5219 return ret;
5220}
5221
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005222static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005223 struct audio_stream_in *stream)
5224{
Andy Hungd13f0d32017-06-12 13:58:37 -07005225 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005226 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005227
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005228 // must deregister from sndmonitor first to prevent races
5229 // between the callback and close_stream
5230 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005231 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07005232
5233 error_log_destroy(in->error_log);
5234 in->error_log = NULL;
5235
Andy Hung0dbb52b2017-08-09 13:51:38 -07005236 pthread_mutex_destroy(&in->pre_lock);
5237 pthread_mutex_destroy(&in->lock);
5238
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005239 free(stream);
5240
5241 return;
5242}
5243
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005244static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005245{
5246 return 0;
5247}
5248
Andy Hung31aca912014-03-20 17:14:59 -07005249/* verifies input and output devices and their capabilities.
5250 *
5251 * This verification is required when enabling extended bit-depth or
5252 * sampling rates, as not all qcom products support it.
5253 *
5254 * Suitable for calling only on initialization such as adev_open().
5255 * It fills the audio_device use_case_table[] array.
5256 *
5257 * Has a side-effect that it needs to configure audio routing / devices
5258 * in order to power up the devices and read the device parameters.
5259 * It does not acquire any hw device lock. Should restore the devices
5260 * back to "normal state" upon completion.
5261 */
5262static int adev_verify_devices(struct audio_device *adev)
5263{
5264 /* enumeration is a bit difficult because one really wants to pull
5265 * the use_case, device id, etc from the hidden pcm_device_table[].
5266 * In this case there are the following use cases and device ids.
5267 *
5268 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
5269 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005270 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07005271 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
5272 * [USECASE_AUDIO_RECORD] = {0, 0},
5273 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
5274 * [USECASE_VOICE_CALL] = {2, 2},
5275 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005276 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07005277 * USECASE_VOICE_CALL omitted, but possible for either input or output.
5278 */
5279
5280 /* should be the usecases enabled in adev_open_input_stream() */
5281 static const int test_in_usecases[] = {
5282 USECASE_AUDIO_RECORD,
5283 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
5284 };
5285 /* should be the usecases enabled in adev_open_output_stream()*/
5286 static const int test_out_usecases[] = {
5287 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
5288 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
5289 };
5290 static const usecase_type_t usecase_type_by_dir[] = {
5291 PCM_PLAYBACK,
5292 PCM_CAPTURE,
5293 };
5294 static const unsigned flags_by_dir[] = {
5295 PCM_OUT,
5296 PCM_IN,
5297 };
5298
5299 size_t i;
5300 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005301 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07005302 char info[512]; /* for possible debug info */
5303
5304 for (dir = 0; dir < 2; ++dir) {
5305 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
5306 const unsigned flags_dir = flags_by_dir[dir];
5307 const size_t testsize =
5308 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
5309 const int *testcases =
5310 dir ? test_in_usecases : test_out_usecases;
5311 const audio_devices_t audio_device =
5312 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
5313
5314 for (i = 0; i < testsize; ++i) {
5315 const audio_usecase_t audio_usecase = testcases[i];
5316 int device_id;
5317 snd_device_t snd_device;
5318 struct pcm_params **pparams;
5319 struct stream_out out;
5320 struct stream_in in;
5321 struct audio_usecase uc_info;
5322 int retval;
5323
5324 pparams = &adev->use_case_table[audio_usecase];
5325 pcm_params_free(*pparams); /* can accept null input */
5326 *pparams = NULL;
5327
5328 /* find the device ID for the use case (signed, for error) */
5329 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
5330 if (device_id < 0)
5331 continue;
5332
5333 /* prepare structures for device probing */
5334 memset(&uc_info, 0, sizeof(uc_info));
5335 uc_info.id = audio_usecase;
5336 uc_info.type = usecase_type;
5337 if (dir) {
5338 adev->active_input = &in;
5339 memset(&in, 0, sizeof(in));
5340 in.device = audio_device;
5341 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
5342 uc_info.stream.in = &in;
5343 } else {
5344 adev->active_input = NULL;
5345 }
5346 memset(&out, 0, sizeof(out));
5347 out.devices = audio_device; /* only field needed in select_devices */
5348 uc_info.stream.out = &out;
5349 uc_info.devices = audio_device;
5350 uc_info.in_snd_device = SND_DEVICE_NONE;
5351 uc_info.out_snd_device = SND_DEVICE_NONE;
5352 list_add_tail(&adev->usecase_list, &uc_info.list);
5353
5354 /* select device - similar to start_(in/out)put_stream() */
5355 retval = select_devices(adev, audio_usecase);
5356 if (retval >= 0) {
5357 *pparams = pcm_params_get(card_id, device_id, flags_dir);
5358#if LOG_NDEBUG == 0
5359 if (*pparams) {
5360 ALOGV("%s: (%s) card %d device %d", __func__,
5361 dir ? "input" : "output", card_id, device_id);
5362 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07005363 } else {
5364 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
5365 }
5366#endif
5367 }
5368
5369 /* deselect device - similar to stop_(in/out)put_stream() */
5370 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07005371 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07005372 /* 2. Disable the rx device */
5373 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07005374 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07005375 list_remove(&uc_info.list);
5376 }
5377 }
5378 adev->active_input = NULL; /* restore adev state */
5379 return 0;
5380}
5381
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005382static int adev_close(hw_device_t *device)
5383{
Andy Hung31aca912014-03-20 17:14:59 -07005384 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005385 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005386
5387 if (!adev)
5388 return 0;
5389
5390 pthread_mutex_lock(&adev_init_lock);
5391
5392 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005393 audio_extn_snd_mon_unregister_listener(adev);
5394 audio_extn_tfa_98xx_deinit();
jasmine cha270b7762018-03-30 15:41:33 +08005395 audio_extn_ma_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005396 audio_route_free(adev->audio_route);
5397 free(adev->snd_dev_ref_cnt);
5398 platform_deinit(adev->platform);
5399 audio_extn_extspk_deinit(adev->extspk);
5400 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005401 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005402 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
5403 pcm_params_free(adev->use_case_table[i]);
5404 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005405 if (adev->adm_deinit)
5406 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005407 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005408 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07005409 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07005410
5411 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005412
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005413 return 0;
5414}
5415
Glenn Kasten4f993392014-05-14 07:30:48 -07005416/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5417 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5418 * just that it _might_ work.
5419 */
5420static int period_size_is_plausible_for_low_latency(int period_size)
5421{
5422 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005423 case 48:
5424 case 96:
5425 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07005426 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005427 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07005428 case 240:
5429 case 320:
5430 case 480:
5431 return 1;
5432 default:
5433 return 0;
5434 }
5435}
5436
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005437static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
5438{
5439 int card;
5440 card_status_t status;
5441
5442 if (!parms)
5443 return;
5444
5445 if (parse_snd_card_status(parms, &card, &status) < 0)
5446 return;
5447
5448 pthread_mutex_lock(&adev->lock);
5449 bool valid_cb = (card == adev->snd_card);
5450 if (valid_cb) {
5451 if (adev->card_status != status) {
5452 adev->card_status = status;
5453 platform_snd_card_update(adev->platform, status);
5454 }
5455 }
5456 pthread_mutex_unlock(&adev->lock);
5457 return;
5458}
5459
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005460/* out and adev lock held */
5461static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
5462{
5463 struct audio_usecase *uc_info;
5464 float left_p;
5465 float right_p;
5466 audio_devices_t devices;
5467
5468 uc_info = get_usecase_from_list(adev, out->usecase);
5469 if (uc_info == NULL) {
5470 ALOGE("%s: Could not find the usecase (%d) in the list",
5471 __func__, out->usecase);
5472 return -EINVAL;
5473 }
5474
5475 ALOGD("%s: enter: usecase(%d: %s)", __func__,
5476 out->usecase, use_case_table[out->usecase]);
5477
5478 if (restore) {
5479 // restore A2DP device for active usecases and unmute if required
5480 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
5481 !is_a2dp_device(uc_info->out_snd_device)) {
5482 ALOGD("%s: restoring A2DP and unmuting stream", __func__);
5483 select_devices(adev, uc_info->id);
5484 pthread_mutex_lock(&out->compr_mute_lock);
5485 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5486 (out->a2dp_compress_mute)) {
5487 out->a2dp_compress_mute = false;
5488 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5489 }
5490 pthread_mutex_unlock(&out->compr_mute_lock);
5491 }
5492 } else {
5493 // mute compress stream if suspended
5494 pthread_mutex_lock(&out->compr_mute_lock);
5495 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5496 (!out->a2dp_compress_mute)) {
5497 if (!out->standby) {
5498 ALOGD("%s: selecting speaker and muting stream", __func__);
5499 devices = out->devices;
5500 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
5501 left_p = out->volume_l;
5502 right_p = out->volume_r;
5503 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5504 compress_pause(out->compr);
5505 set_compr_volume(&out->stream, 0.0f, 0.0f);
5506 out->a2dp_compress_mute = true;
5507 select_devices(adev, out->usecase);
5508 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5509 compress_resume(out->compr);
5510 out->devices = devices;
5511 out->volume_l = left_p;
5512 out->volume_r = right_p;
5513 }
5514 }
5515 pthread_mutex_unlock(&out->compr_mute_lock);
5516 }
5517 ALOGV("%s: exit", __func__);
5518 return 0;
5519}
5520
5521int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
5522{
5523 int ret = 0;
5524
5525 lock_output_stream(out);
5526 pthread_mutex_lock(&adev->lock);
5527
5528 ret = check_a2dp_restore_l(adev, out, restore);
5529
5530 pthread_mutex_unlock(&adev->lock);
5531 pthread_mutex_unlock(&out->lock);
5532 return ret;
5533}
5534
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005535static int adev_open(const hw_module_t *module, const char *name,
5536 hw_device_t **device)
5537{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005538 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005539
Eric Laurent2bafff12016-03-17 12:17:23 -07005540 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005541 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005542 pthread_mutex_lock(&adev_init_lock);
5543 if (audio_device_ref_count != 0) {
5544 *device = &adev->device.common;
5545 audio_device_ref_count++;
5546 ALOGV("%s: returning existing instance of adev", __func__);
5547 ALOGV("%s: exit", __func__);
5548 pthread_mutex_unlock(&adev_init_lock);
5549 return 0;
5550 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005551 adev = calloc(1, sizeof(struct audio_device));
5552
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005553 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5554
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005555 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5556 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5557 adev->device.common.module = (struct hw_module_t *)module;
5558 adev->device.common.close = adev_close;
5559
5560 adev->device.init_check = adev_init_check;
5561 adev->device.set_voice_volume = adev_set_voice_volume;
5562 adev->device.set_master_volume = adev_set_master_volume;
5563 adev->device.get_master_volume = adev_get_master_volume;
5564 adev->device.set_master_mute = adev_set_master_mute;
5565 adev->device.get_master_mute = adev_get_master_mute;
5566 adev->device.set_mode = adev_set_mode;
5567 adev->device.set_mic_mute = adev_set_mic_mute;
5568 adev->device.get_mic_mute = adev_get_mic_mute;
5569 adev->device.set_parameters = adev_set_parameters;
5570 adev->device.get_parameters = adev_get_parameters;
5571 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5572 adev->device.open_output_stream = adev_open_output_stream;
5573 adev->device.close_output_stream = adev_close_output_stream;
5574 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005575
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005576 adev->device.close_input_stream = adev_close_input_stream;
5577 adev->device.dump = adev_dump;
jiabin8962a4d2018-03-19 18:21:24 -07005578 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005579
5580 /* Set the default route before the PCM stream is opened */
5581 pthread_mutex_lock(&adev->lock);
5582 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005583 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005584 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005585 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005586 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005587 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005588 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005589 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005590 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005591 pthread_mutex_unlock(&adev->lock);
5592
5593 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005594 adev->platform = platform_init(adev);
5595 if (!adev->platform) {
5596 free(adev->snd_dev_ref_cnt);
5597 free(adev);
5598 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5599 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005600 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005601 return -EINVAL;
5602 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05005603 adev->extspk = audio_extn_extspk_init(adev);
5604
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005605 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5606 if (adev->visualizer_lib == NULL) {
5607 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5608 } else {
5609 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5610 adev->visualizer_start_output =
5611 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5612 "visualizer_hal_start_output");
5613 adev->visualizer_stop_output =
5614 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5615 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07005616 }
5617
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005618 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5619 if (adev->offload_effects_lib == NULL) {
5620 ALOGW("%s: DLOPEN failed for %s", __func__,
5621 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5622 } else {
5623 ALOGV("%s: DLOPEN successful for %s", __func__,
5624 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5625 adev->offload_effects_start_output =
5626 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5627 "offload_effects_bundle_hal_start_output");
5628 adev->offload_effects_stop_output =
5629 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5630 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07005631 }
5632
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005633 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5634 if (adev->adm_lib == NULL) {
5635 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5636 } else {
5637 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5638 adev->adm_init = (adm_init_t)
5639 dlsym(adev->adm_lib, "adm_init");
5640 adev->adm_deinit = (adm_deinit_t)
5641 dlsym(adev->adm_lib, "adm_deinit");
5642 adev->adm_register_input_stream = (adm_register_input_stream_t)
5643 dlsym(adev->adm_lib, "adm_register_input_stream");
5644 adev->adm_register_output_stream = (adm_register_output_stream_t)
5645 dlsym(adev->adm_lib, "adm_register_output_stream");
5646 adev->adm_deregister_stream = (adm_deregister_stream_t)
5647 dlsym(adev->adm_lib, "adm_deregister_stream");
5648 adev->adm_request_focus = (adm_request_focus_t)
5649 dlsym(adev->adm_lib, "adm_request_focus");
5650 adev->adm_abandon_focus = (adm_abandon_focus_t)
5651 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08005652 adev->adm_set_config = (adm_set_config_t)
5653 dlsym(adev->adm_lib, "adm_set_config");
5654 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5655 dlsym(adev->adm_lib, "adm_request_focus_v2");
5656 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5657 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5658 adev->adm_on_routing_change = (adm_on_routing_change_t)
5659 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005660 }
5661
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005662 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005663 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005664
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005665 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005666
Andy Hung31aca912014-03-20 17:14:59 -07005667 if (k_enable_extended_precision)
5668 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005669
Glenn Kasten4f993392014-05-14 07:30:48 -07005670 char value[PROPERTY_VALUE_MAX];
5671 int trial;
5672 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5673 trial = atoi(value);
5674 if (period_size_is_plausible_for_low_latency(trial)) {
5675 pcm_config_low_latency.period_size = trial;
5676 pcm_config_low_latency.start_threshold = trial / 4;
5677 pcm_config_low_latency.avail_min = trial / 4;
5678 configured_low_latency_capture_period_size = trial;
5679 }
5680 }
5681 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5682 trial = atoi(value);
5683 if (period_size_is_plausible_for_low_latency(trial)) {
5684 configured_low_latency_capture_period_size = trial;
5685 }
5686 }
5687
Vignesh Kulothunganb6f0a9c2018-03-22 13:50:22 -07005688 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
5689
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005690 // commented as full set of app type cfg is sent from platform
5691 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005692 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005693
5694 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5695 af_period_multiplier = atoi(value);
5696 if (af_period_multiplier < 0) {
5697 af_period_multiplier = 2;
5698 } else if (af_period_multiplier > 4) {
5699 af_period_multiplier = 4;
5700 }
5701 ALOGV("new period_multiplier = %d", af_period_multiplier);
5702 }
5703
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005704 audio_extn_tfa_98xx_init(adev);
jasmine cha270b7762018-03-30 15:41:33 +08005705 audio_extn_ma_init(adev->platform);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005706
vivek mehta1a9b7c02015-06-25 11:49:38 -07005707 pthread_mutex_unlock(&adev_init_lock);
5708
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005709 if (adev->adm_init)
5710 adev->adm_data = adev->adm_init();
5711
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005712 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005713 audio_extn_snd_mon_init();
5714 pthread_mutex_lock(&adev->lock);
5715 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
5716 adev->card_status = CARD_STATUS_ONLINE;
5717 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005718 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005719
Eric Laurent2bafff12016-03-17 12:17:23 -07005720 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005721 return 0;
5722}
5723
5724static struct hw_module_methods_t hal_module_methods = {
5725 .open = adev_open,
5726};
5727
5728struct audio_module HAL_MODULE_INFO_SYM = {
5729 .common = {
5730 .tag = HARDWARE_MODULE_TAG,
5731 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5732 .hal_api_version = HARDWARE_HAL_API_VERSION,
5733 .id = AUDIO_HARDWARE_MODULE_ID,
5734 .name = "QCOM Audio HAL",
5735 .author = "Code Aurora Forum",
5736 .methods = &hal_module_methods,
5737 },
5738};