blob: 9559573178e01f02e09b151c00d0ec76bca08dcd [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{
yixuanjiang509f0a72018-09-06 18:37:23 +0800603 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
yixuanjiang509f0a72018-09-06 18:37:23 +0800611 if (usecase->type == PCM_CAPTURE)
612 snd_device = usecase->in_snd_device;
613 else
614 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);
yixuanjiang6c5e87c2018-08-13 11:50:26 +0800617 strcpy(mixer_path, use_case_table[usecase->id]);
yixuanjiang509f0a72018-09-06 18:37:23 +0800618 platform_add_backend_name(adev->platform, mixer_path, snd_device);
619 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{
yixuanjiang509f0a72018-09-06 18:37:23 +0800630 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);
yixuanjiang509f0a72018-09-06 18:37:23 +0800637 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]);
yixuanjiang509f0a72018-09-06 18:37:23 +0800642 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
juyuchen66c4ecf2018-08-06 15:39:34 +08001376 if (usecase->id == USECASE_INCALL_MUSIC_UPLINK) {
1377 out_snd_device = SND_DEVICE_OUT_VOICE_MUSIC_TX;
1378 }
1379
Eric Laurent2bafff12016-03-17 12:17:23 -07001380 if (out_snd_device != SND_DEVICE_NONE &&
1381 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1382 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1383 __func__,
1384 use_case_table[uc_id],
1385 adev->last_logged_snd_device[uc_id][0],
1386 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1387 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1388 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1389 -1,
1390 out_snd_device,
1391 platform_get_snd_device_name(out_snd_device),
1392 platform_get_snd_device_acdb_id(out_snd_device));
1393 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1394 }
1395 if (in_snd_device != SND_DEVICE_NONE &&
1396 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1397 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1398 __func__,
1399 use_case_table[uc_id],
1400 adev->last_logged_snd_device[uc_id][1],
1401 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1402 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1403 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1404 -1,
1405 in_snd_device,
1406 platform_get_snd_device_name(in_snd_device),
1407 platform_get_snd_device_acdb_id(in_snd_device));
1408 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1409 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001410
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001411 /*
1412 * Limitation: While in call, to do a device switch we need to disable
1413 * and enable both RX and TX devices though one of them is same as current
1414 * device.
1415 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001416 if ((usecase->type == VOICE_CALL) &&
1417 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1418 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001419 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001420 /* Disable sidetone only if voice call already exists */
1421 if (voice_is_call_state_active(adev))
1422 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001423 }
1424
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001425 /* Disable current sound devices */
1426 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001427 disable_audio_route(adev, usecase);
1428 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001429 }
1430
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001431 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001432 disable_audio_route(adev, usecase);
1433 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001434 }
1435
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001436 /* Applicable only on the targets that has external modem.
1437 * New device information should be sent to modem before enabling
1438 * the devices to reduce in-call device switch time.
1439 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001440 if ((usecase->type == VOICE_CALL) &&
1441 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1442 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001443 status = platform_switch_voice_call_enable_device_config(adev->platform,
1444 out_snd_device,
1445 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001446 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001447
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001448 /* Enable new sound devices */
1449 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001450 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001451 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) ||
1452 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001453 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001454 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001455 }
1456
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001457 if (in_snd_device != SND_DEVICE_NONE) {
1458 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001459 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001460 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001461
Eric Laurentb23d5282013-05-14 15:27:20 -07001462 if (usecase->type == VOICE_CALL)
1463 status = platform_switch_voice_call_device_post(adev->platform,
1464 out_snd_device,
1465 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001466
sangwoo170731f2013-06-08 15:36:36 +09001467 usecase->in_snd_device = in_snd_device;
1468 usecase->out_snd_device = out_snd_device;
1469
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001470 audio_extn_tfa_98xx_set_mode();
1471
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001472 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001473
Jasmine Cha70771b62018-05-15 15:02:43 +08001474 audio_extn_ma_set_device(usecase);
jasmine cha270b7762018-03-30 15:41:33 +08001475
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001476 /* Applicable only on the targets that has external modem.
1477 * Enable device command should be sent to modem only after
1478 * enabling voice call mixer controls
1479 */
vivek mehta765eb642015-08-07 19:46:06 -07001480 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001481 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1482 out_snd_device,
1483 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001484 /* Enable sidetone only if voice call already exists */
1485 if (voice_is_call_state_active(adev))
1486 voice_set_sidetone(adev, out_snd_device, true);
1487 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001488
Eric Laurentf4520b02017-09-20 18:31:58 -07001489 if (usecase == voip_usecase) {
1490 struct stream_out *voip_out = voip_usecase->stream.out;
1491 audio_extn_utils_send_app_type_gain(adev,
1492 voip_out->app_type_cfg.app_type,
1493 &voip_out->app_type_cfg.gain[0]);
1494 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001495 return status;
1496}
1497
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001498static int stop_input_stream(struct stream_in *in)
1499{
1500 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001501 struct audio_usecase *uc_info;
1502 struct audio_device *adev = in->dev;
1503
Eric Laurent994a6932013-07-17 11:51:42 -07001504 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001505 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001506
1507 if (adev->active_input) {
1508 if (adev->active_input->usecase == in->usecase) {
1509 adev->active_input = NULL;
1510 } else {
1511 ALOGW("%s adev->active_input->usecase %s, v/s in->usecase %s",
1512 __func__,
1513 use_case_table[adev->active_input->usecase],
1514 use_case_table[in->usecase]);
1515 }
1516 }
1517
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001518 uc_info = get_usecase_from_list(adev, in->usecase);
1519 if (uc_info == NULL) {
1520 ALOGE("%s: Could not find the usecase (%d) in the list",
1521 __func__, in->usecase);
1522 return -EINVAL;
1523 }
1524
vivek mehta781065c2017-04-04 12:55:01 -07001525 /* Close in-call recording streams */
1526 voice_check_and_stop_incall_rec_usecase(adev, in);
1527
Eric Laurent150dbfe2013-02-27 14:31:02 -08001528 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001529 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001530
1531 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001532 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001533
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001534 list_remove(&uc_info->list);
1535 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001536
Eric Laurent994a6932013-07-17 11:51:42 -07001537 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001538 return ret;
1539}
1540
1541int start_input_stream(struct stream_in *in)
1542{
1543 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001544 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001545 struct audio_usecase *uc_info;
1546 struct audio_device *adev = in->dev;
1547
Eric Laurent994a6932013-07-17 11:51:42 -07001548 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001549
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001550 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1551 return -EIO;
1552
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001553 if (in->card_status == CARD_STATUS_OFFLINE ||
1554 adev->card_status == CARD_STATUS_OFFLINE) {
1555 ALOGW("in->card_status or adev->card_status offline, try again");
1556 ret = -EAGAIN;
1557 goto error_config;
1558 }
1559
vivek mehta781065c2017-04-04 12:55:01 -07001560 /* Check if source matches incall recording usecase criteria */
1561 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1562 if (ret)
1563 goto error_config;
1564 else
1565 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1566
Eric Laurentb23d5282013-05-14 15:27:20 -07001567 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001568 if (in->pcm_device_id < 0) {
1569 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1570 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001571 ret = -EINVAL;
1572 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001573 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001574
1575 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001576 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1577 uc_info->id = in->usecase;
1578 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001579 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001580 uc_info->devices = in->device;
1581 uc_info->in_snd_device = SND_DEVICE_NONE;
1582 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001583
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001584 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001585
Wei Wangf4837d52017-11-21 14:51:20 -08001586 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001587 audio_extn_perf_lock_acquire();
1588
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001589 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001590
Eric Laurent0e46adf2016-12-16 12:49:24 -08001591 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001592 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001593 ALOGE("%s: pcm stream not ready", __func__);
1594 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001595 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001596 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001597 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001598 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1599 goto error_open;
1600 }
1601 } else {
1602 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1603 unsigned int pcm_open_retry_count = 0;
1604
1605 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1606 flags |= PCM_MMAP | PCM_NOIRQ;
1607 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1608 } else if (in->realtime) {
1609 flags |= PCM_MMAP | PCM_NOIRQ;
1610 }
1611
1612 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1613 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1614
1615 while (1) {
1616 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1617 flags, &in->config);
1618 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1619 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1620 if (in->pcm != NULL) {
1621 pcm_close(in->pcm);
1622 in->pcm = NULL;
1623 }
1624 if (pcm_open_retry_count-- == 0) {
1625 ret = -EIO;
1626 goto error_open;
1627 }
1628 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1629 continue;
1630 }
1631 break;
1632 }
1633
1634 ALOGV("%s: pcm_prepare", __func__);
1635 ret = pcm_prepare(in->pcm);
1636 if (ret < 0) {
1637 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001638 pcm_close(in->pcm);
1639 in->pcm = NULL;
1640 goto error_open;
1641 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001642 if (in->realtime) {
1643 ret = pcm_start(in->pcm);
1644 if (ret < 0) {
1645 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1646 pcm_close(in->pcm);
1647 in->pcm = NULL;
1648 goto error_open;
1649 }
1650 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001651 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001652 register_in_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001653 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001654 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001655 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001656
Eric Laurent0e46adf2016-12-16 12:49:24 -08001657 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001658
1659error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001660 stop_input_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001661 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001662 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001663
1664error_config:
1665 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001666 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001667 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001668}
1669
Eric Laurenta1478072015-09-21 17:21:52 -07001670void lock_input_stream(struct stream_in *in)
1671{
1672 pthread_mutex_lock(&in->pre_lock);
1673 pthread_mutex_lock(&in->lock);
1674 pthread_mutex_unlock(&in->pre_lock);
1675}
1676
1677void lock_output_stream(struct stream_out *out)
1678{
1679 pthread_mutex_lock(&out->pre_lock);
1680 pthread_mutex_lock(&out->lock);
1681 pthread_mutex_unlock(&out->pre_lock);
1682}
1683
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001684/* must be called with out->lock locked */
1685static int send_offload_cmd_l(struct stream_out* out, int command)
1686{
1687 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1688
1689 ALOGVV("%s %d", __func__, command);
1690
1691 cmd->cmd = command;
1692 list_add_tail(&out->offload_cmd_list, &cmd->node);
1693 pthread_cond_signal(&out->offload_cond);
1694 return 0;
1695}
1696
1697/* must be called iwth out->lock locked */
1698static void stop_compressed_output_l(struct stream_out *out)
1699{
1700 out->offload_state = OFFLOAD_STATE_IDLE;
1701 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001702 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001703 if (out->compr != NULL) {
1704 compress_stop(out->compr);
1705 while (out->offload_thread_blocked) {
1706 pthread_cond_wait(&out->cond, &out->lock);
1707 }
1708 }
1709}
1710
1711static void *offload_thread_loop(void *context)
1712{
1713 struct stream_out *out = (struct stream_out *) context;
1714 struct listnode *item;
1715
1716 out->offload_state = OFFLOAD_STATE_IDLE;
1717 out->playback_started = 0;
1718
1719 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1720 set_sched_policy(0, SP_FOREGROUND);
1721 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1722
1723 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001724 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001725 for (;;) {
1726 struct offload_cmd *cmd = NULL;
1727 stream_callback_event_t event;
1728 bool send_callback = false;
1729
1730 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1731 __func__, list_empty(&out->offload_cmd_list),
1732 out->offload_state);
1733 if (list_empty(&out->offload_cmd_list)) {
1734 ALOGV("%s SLEEPING", __func__);
1735 pthread_cond_wait(&out->offload_cond, &out->lock);
1736 ALOGV("%s RUNNING", __func__);
1737 continue;
1738 }
1739
1740 item = list_head(&out->offload_cmd_list);
1741 cmd = node_to_item(item, struct offload_cmd, node);
1742 list_remove(item);
1743
1744 ALOGVV("%s STATE %d CMD %d out->compr %p",
1745 __func__, out->offload_state, cmd->cmd, out->compr);
1746
1747 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1748 free(cmd);
1749 break;
1750 }
1751
1752 if (out->compr == NULL) {
1753 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001754 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001755 pthread_cond_signal(&out->cond);
1756 continue;
1757 }
1758 out->offload_thread_blocked = true;
1759 pthread_mutex_unlock(&out->lock);
1760 send_callback = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001761 switch (cmd->cmd) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001762 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1763 compress_wait(out->compr, -1);
1764 send_callback = true;
1765 event = STREAM_CBK_EVENT_WRITE_READY;
1766 break;
1767 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001768 compress_next_track(out->compr);
1769 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001770 send_callback = true;
1771 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001772 /* Resend the metadata for next iteration */
1773 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001774 break;
1775 case OFFLOAD_CMD_DRAIN:
1776 compress_drain(out->compr);
1777 send_callback = true;
1778 event = STREAM_CBK_EVENT_DRAIN_READY;
1779 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001780 case OFFLOAD_CMD_ERROR:
1781 send_callback = true;
1782 event = STREAM_CBK_EVENT_ERROR;
1783 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001784 default:
1785 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1786 break;
1787 }
Eric Laurenta1478072015-09-21 17:21:52 -07001788 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001789 out->offload_thread_blocked = false;
1790 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001791 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001792 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001793 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001794 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001795 free(cmd);
1796 }
1797
1798 pthread_cond_signal(&out->cond);
1799 while (!list_empty(&out->offload_cmd_list)) {
1800 item = list_head(&out->offload_cmd_list);
1801 list_remove(item);
1802 free(node_to_item(item, struct offload_cmd, node));
1803 }
1804 pthread_mutex_unlock(&out->lock);
1805
1806 return NULL;
1807}
1808
1809static int create_offload_callback_thread(struct stream_out *out)
1810{
1811 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1812 list_init(&out->offload_cmd_list);
1813 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1814 offload_thread_loop, out);
1815 return 0;
1816}
1817
1818static int destroy_offload_callback_thread(struct stream_out *out)
1819{
Eric Laurenta1478072015-09-21 17:21:52 -07001820 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001821 stop_compressed_output_l(out);
1822 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1823
1824 pthread_mutex_unlock(&out->lock);
1825 pthread_join(out->offload_thread, (void **) NULL);
1826 pthread_cond_destroy(&out->offload_cond);
1827
1828 return 0;
1829}
1830
Eric Laurent07eeafd2013-10-06 12:52:49 -07001831static bool allow_hdmi_channel_config(struct audio_device *adev)
1832{
1833 struct listnode *node;
1834 struct audio_usecase *usecase;
1835 bool ret = true;
1836
1837 list_for_each(node, &adev->usecase_list) {
1838 usecase = node_to_item(node, struct audio_usecase, list);
1839 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1840 /*
1841 * If voice call is already existing, do not proceed further to avoid
1842 * disabling/enabling both RX and TX devices, CSD calls, etc.
1843 * Once the voice call done, the HDMI channels can be configured to
1844 * max channels of remaining use cases.
1845 */
1846 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001847 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001848 __func__);
1849 ret = false;
1850 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001851 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1852 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001853 "no change in HDMI channels", __func__);
1854 ret = false;
1855 break;
1856 }
1857 }
1858 }
1859 return ret;
1860}
1861
1862static int check_and_set_hdmi_channels(struct audio_device *adev,
1863 unsigned int channels)
1864{
1865 struct listnode *node;
1866 struct audio_usecase *usecase;
1867
1868 /* Check if change in HDMI channel config is allowed */
1869 if (!allow_hdmi_channel_config(adev))
1870 return 0;
1871
1872 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001873 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001874 return 0;
1875 }
1876
1877 platform_set_hdmi_channels(adev->platform, channels);
1878 adev->cur_hdmi_channels = channels;
1879
1880 /*
1881 * Deroute all the playback streams routed to HDMI so that
1882 * the back end is deactivated. Note that backend will not
1883 * be deactivated if any one stream is connected to it.
1884 */
1885 list_for_each(node, &adev->usecase_list) {
1886 usecase = node_to_item(node, struct audio_usecase, list);
1887 if (usecase->type == PCM_PLAYBACK &&
1888 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001889 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001890 }
1891 }
1892
1893 /*
1894 * Enable all the streams disabled above. Now the HDMI backend
1895 * will be activated with new channel configuration
1896 */
1897 list_for_each(node, &adev->usecase_list) {
1898 usecase = node_to_item(node, struct audio_usecase, list);
1899 if (usecase->type == PCM_PLAYBACK &&
1900 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001901 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001902 }
1903 }
1904
1905 return 0;
1906}
1907
Haynes Mathew George65f6b432018-02-27 17:44:55 -08001908static int check_and_set_usb_service_interval(struct audio_device *adev,
1909 struct audio_usecase *uc_info,
1910 bool min)
1911{
1912 struct listnode *node;
1913 struct audio_usecase *usecase;
1914 bool switch_usecases = false;
1915 bool reconfig = false;
1916
1917 if ((uc_info->id != USECASE_AUDIO_PLAYBACK_MMAP) &&
1918 (uc_info->id != USECASE_AUDIO_PLAYBACK_ULL))
1919 return -1;
1920
1921 /* set if the valid usecase do not already exist */
1922 list_for_each(node, &adev->usecase_list) {
1923 usecase = node_to_item(node, struct audio_usecase, list);
1924 if (usecase->type == PCM_PLAYBACK &&
1925 (audio_is_usb_out_device(usecase->devices & AUDIO_DEVICE_OUT_ALL_USB))) {
1926 switch (usecase->id) {
1927 case USECASE_AUDIO_PLAYBACK_MMAP:
1928 case USECASE_AUDIO_PLAYBACK_ULL:
1929 // cannot reconfig while mmap/ull is present.
1930 return -1;
1931 default:
1932 switch_usecases = true;
1933 break;
1934 }
1935 }
1936 if (switch_usecases)
1937 break;
1938 }
1939 /*
1940 * client can try to set service interval in start_output_stream
1941 * to min or to 0 (i.e reset) in stop_output_stream .
1942 */
1943 unsigned long service_interval =
1944 audio_extn_usb_find_service_interval(min, true /*playback*/);
1945 int ret = platform_set_usb_service_interval(adev->platform,
1946 true /*playback*/,
1947 service_interval,
1948 &reconfig);
1949 /* no change or not supported or no active usecases */
1950 if (ret || !reconfig || !switch_usecases)
1951 return -1;
1952 return 0;
1953#undef VALID_USECASE
1954}
1955
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001956static int stop_output_stream(struct stream_out *out)
1957{
1958 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001959 struct audio_usecase *uc_info;
1960 struct audio_device *adev = out->dev;
HW Lee88512e92018-06-12 15:26:09 +08001961 bool has_voip_usecase =
1962 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001963
Eric Laurent994a6932013-07-17 11:51:42 -07001964 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001965 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001966 uc_info = get_usecase_from_list(adev, out->usecase);
1967 if (uc_info == NULL) {
1968 ALOGE("%s: Could not find the usecase (%d) in the list",
1969 __func__, out->usecase);
1970 return -EINVAL;
1971 }
1972
Haynes Mathew George41f86652014-06-17 14:22:15 -07001973 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1974 if (adev->visualizer_stop_output != NULL)
1975 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1976 if (adev->offload_effects_stop_output != NULL)
1977 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08001978 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
1979 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
1980 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07001981 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001982
Eric Laurent150dbfe2013-02-27 14:31:02 -08001983 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001984 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001985
1986 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001987 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001988
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001989 list_remove(&uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001990
Eric Laurent0499d4f2014-08-25 22:39:29 -05001991 audio_extn_extspk_update(adev->extspk);
1992
Eric Laurent07eeafd2013-10-06 12:52:49 -07001993 /* Must be called after removing the usecase from list */
1994 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1995 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
HW Lee88512e92018-06-12 15:26:09 +08001996 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
Haynes Mathew George65f6b432018-02-27 17:44:55 -08001997 ret = check_and_set_usb_service_interval(adev, uc_info, false /*min*/);
1998 if (ret == 0) {
1999 /* default service interval was successfully updated,
2000 reopen USB backend with new service interval */
2001 check_and_route_playback_usecases(adev, uc_info, uc_info->out_snd_device);
2002 }
2003 ret = 0;
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07002004 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002005
HW Lee88512e92018-06-12 15:26:09 +08002006 if (has_voip_usecase ||
2007 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
2008 struct listnode *node;
2009 struct audio_usecase *usecase;
2010 list_for_each(node, &adev->usecase_list) {
2011 usecase = node_to_item(node, struct audio_usecase, list);
2012 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
2013 continue;
2014
2015 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
2016 __func__, usecase->id, use_case_table[usecase->id],
2017 out->usecase, use_case_table[out->usecase]);
2018 select_devices(adev, usecase->id);
2019 }
2020 }
2021
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002022 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07002023 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002024 return ret;
2025}
2026
2027int start_output_stream(struct stream_out *out)
2028{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002029 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002030 struct audio_usecase *uc_info;
2031 struct audio_device *adev = out->dev;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002032 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002033
Eric Laurent994a6932013-07-17 11:51:42 -07002034 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002035 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002036
2037 if (out->card_status == CARD_STATUS_OFFLINE ||
2038 adev->card_status == CARD_STATUS_OFFLINE) {
2039 ALOGW("out->card_status or adev->card_status offline, try again");
2040 ret = -EAGAIN;
2041 goto error_config;
2042 }
2043
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002044 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2045 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002046 if (out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002047 a2dp_combo = true;
2048 } else {
2049 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2050 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2051 ret = -EAGAIN;
2052 goto error_config;
2053 }
2054 }
2055 }
2056 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002057 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002058 if (out->pcm_device_id < 0) {
2059 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2060 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002061 ret = -EINVAL;
2062 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002063 }
2064
2065 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
2066 uc_info->id = out->usecase;
2067 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002068 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002069 uc_info->devices = out->devices;
2070 uc_info->in_snd_device = SND_DEVICE_NONE;
2071 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002072
Eric Laurent07eeafd2013-10-06 12:52:49 -07002073 /* This must be called before adding this usecase to the list */
2074 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2075 check_and_set_hdmi_channels(adev, out->config.channels);
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002076 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
2077 check_and_set_usb_service_interval(adev, uc_info, true /*min*/);
2078 /* USB backend is not reopened immediately.
2079 This is eventually done as part of select_devices */
2080 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002081
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002082 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002083
Wei Wangf4837d52017-11-21 14:51:20 -08002084 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002085 audio_extn_perf_lock_acquire();
2086
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002087 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2088 (!audio_extn_a2dp_is_ready())) {
2089 if (!a2dp_combo) {
2090 check_a2dp_restore_l(adev, out, false);
2091 } else {
2092 audio_devices_t dev = out->devices;
juyuchen9baad392018-06-05 19:02:10 +08002093 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2094 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2095 else
2096 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002097 select_devices(adev, out->usecase);
2098 out->devices = dev;
2099 }
2100 } else {
2101 select_devices(adev, out->usecase);
2102 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002103
Eric Laurent0499d4f2014-08-25 22:39:29 -05002104 audio_extn_extspk_update(adev->extspk);
2105
Andy Hung31aca912014-03-20 17:14:59 -07002106 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002107 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002108 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2109 out->pcm = NULL;
2110 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
2111 COMPRESS_IN, &out->compr_config);
2112 if (out->compr && !is_compress_ready(out->compr)) {
2113 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2114 compress_close(out->compr);
2115 out->compr = NULL;
2116 ret = -EIO;
2117 goto error_open;
2118 }
2119 if (out->offload_callback)
2120 compress_nonblock(out->compr, out->non_blocking);
2121
Aniket Kumar Lata72a3cea2018-04-06 13:56:37 -07002122 if (adev->visualizer_start_output != NULL) {
2123 int capture_device_id =
2124 platform_get_pcm_device_id(USECASE_AUDIO_RECORD_AFE_PROXY,
2125 PCM_CAPTURE);
2126 adev->visualizer_start_output(out->handle, out->pcm_device_id,
2127 adev->snd_card, capture_device_id);
2128 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002129 if (adev->offload_effects_start_output != NULL)
2130 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
2131 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002132 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002133 ALOGE("%s: pcm stream not ready", __func__);
2134 goto error_open;
2135 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002136 ret = pcm_start(out->pcm);
2137 if (ret < 0) {
2138 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2139 goto error_open;
2140 }
2141 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07002142 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002143 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002144
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002145 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2146 flags |= PCM_MMAP | PCM_NOIRQ;
2147 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002148 } else if (out->realtime) {
2149 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07002150 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002151
2152 while (1) {
2153 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2154 flags, &out->config);
2155 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2156 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2157 if (out->pcm != NULL) {
2158 pcm_close(out->pcm);
2159 out->pcm = NULL;
2160 }
2161 if (pcm_open_retry_count-- == 0) {
2162 ret = -EIO;
2163 goto error_open;
2164 }
2165 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2166 continue;
2167 }
2168 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002169 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002170 ALOGV("%s: pcm_prepare", __func__);
2171 if (pcm_is_ready(out->pcm)) {
2172 ret = pcm_prepare(out->pcm);
2173 if (ret < 0) {
2174 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2175 pcm_close(out->pcm);
2176 out->pcm = NULL;
2177 goto error_open;
2178 }
2179 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002180 if (out->realtime) {
2181 ret = pcm_start(out->pcm);
2182 if (ret < 0) {
2183 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
2184 pcm_close(out->pcm);
2185 out->pcm = NULL;
2186 goto error_open;
2187 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002188 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002189 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002190 register_out_stream(out);
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();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002193 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07002194
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002195 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2196 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2197 audio_low_latency_hint_start();
2198 }
2199
vivek mehtae59cfb22017-06-16 15:57:11 -07002200 // consider a scenario where on pause lower layers are tear down.
2201 // so on resume, swap mixer control need to be sent only when
2202 // backend is active, hence rather than sending from enable device
2203 // sending it from start of streamtream
2204
2205 platform_set_swap_channels(adev, true);
2206
Eric Laurent994a6932013-07-17 11:51:42 -07002207 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002208 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002209error_open:
Wei Wangf4837d52017-11-21 14:51:20 -08002210 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002211 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002212 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002213error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002214 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002215}
2216
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002217static int check_input_parameters(uint32_t sample_rate,
2218 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07002219 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002220{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002221 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2222 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002223 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2224 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002225 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2226 return -EINVAL;
2227 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002228
Eric Laurent74b55762017-07-09 17:04:53 -07002229 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2230 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002231 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002232 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002233 return -EINVAL;
2234 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002235
2236 switch (sample_rate) {
2237 case 8000:
2238 case 11025:
2239 case 12000:
2240 case 16000:
2241 case 22050:
2242 case 24000:
2243 case 32000:
2244 case 44100:
2245 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002246 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002247 break;
2248 default:
vivek mehtadae44712015-07-27 14:13:18 -07002249 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002250 return -EINVAL;
2251 }
2252
2253 return 0;
2254}
2255
Kevin Rocarda325aa22018-04-03 09:15:52 -07002256/** Add a value in a list if not already present.
2257 * @return true if value was successfully inserted or already present,
2258 * false if the list is full and does not contain the value.
2259 */
2260static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
2261 for (size_t i = 0; i < list_length; i++) {
2262 if (list[i] == value) return true; // value is already present
2263 if (list[i] == 0) { // no values in this slot
2264 list[i] = value;
2265 return true; // value inserted
2266 }
2267 }
2268 return false; // could not insert value
2269}
2270
2271/** Add channel_mask in supported_channel_masks if not already present.
2272 * @return true if channel_mask was successfully inserted or already present,
2273 * false if supported_channel_masks is full and does not contain channel_mask.
2274 */
2275static void register_channel_mask(audio_channel_mask_t channel_mask,
2276 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
2277 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
2278 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
2279}
2280
2281/** Add format in supported_formats if not already present.
2282 * @return true if format was successfully inserted or already present,
2283 * false if supported_formats is full and does not contain format.
2284 */
2285static void register_format(audio_format_t format,
2286 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
2287 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
2288 "%s: stream can not declare supporting its format %x", __func__, format);
2289}
2290/** Add sample_rate in supported_sample_rates if not already present.
2291 * @return true if sample_rate was successfully inserted or already present,
2292 * false if supported_sample_rates is full and does not contain sample_rate.
2293 */
2294static void register_sample_rate(uint32_t sample_rate,
2295 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
2296 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
2297 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
2298}
2299
vivek mehtaa68fea62017-06-08 19:04:02 -07002300static size_t get_stream_buffer_size(size_t duration_ms,
2301 uint32_t sample_rate,
2302 audio_format_t format,
2303 int channel_count,
2304 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002305{
2306 size_t size = 0;
2307
vivek mehtaa68fea62017-06-08 19:04:02 -07002308 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002309 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002310 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002311
2312 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002313
Glenn Kasten4f993392014-05-14 07:30:48 -07002314 /* make sure the size is multiple of 32 bytes
2315 * At 48 kHz mono 16-bit PCM:
2316 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2317 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2318 */
2319 size += 0x1f;
2320 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002321
2322 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002323}
2324
2325static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2326{
2327 struct stream_out *out = (struct stream_out *)stream;
2328
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002329 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002330}
2331
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002332static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002333{
2334 return -ENOSYS;
2335}
2336
2337static size_t out_get_buffer_size(const struct audio_stream *stream)
2338{
2339 struct stream_out *out = (struct stream_out *)stream;
2340
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002341 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2342 return out->compr_config.fragment_size;
2343 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002344 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002345 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002346}
2347
2348static uint32_t out_get_channels(const struct audio_stream *stream)
2349{
2350 struct stream_out *out = (struct stream_out *)stream;
2351
2352 return out->channel_mask;
2353}
2354
2355static audio_format_t out_get_format(const struct audio_stream *stream)
2356{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002357 struct stream_out *out = (struct stream_out *)stream;
2358
2359 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002360}
2361
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002362static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002363{
2364 return -ENOSYS;
2365}
2366
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002367/* must be called with out->lock locked */
2368static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002369{
2370 struct stream_out *out = (struct stream_out *)stream;
2371 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002372 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002373
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002374 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002375 if (adev->adm_deregister_stream)
2376 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002377 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002378 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002379 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2380 if (out->pcm) {
2381 pcm_close(out->pcm);
2382 out->pcm = NULL;
2383 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002384 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002385 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002386 out->playback_started = false;
2387 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002388 } else {
2389 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002390 out->gapless_mdata.encoder_delay = 0;
2391 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002392 if (out->compr != NULL) {
2393 compress_close(out->compr);
2394 out->compr = NULL;
2395 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002396 }
Phil Burkbc991042017-02-24 08:06:44 -08002397 if (do_stop) {
2398 stop_output_stream(out);
2399 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002400 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002401 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002402 return 0;
2403}
2404
2405static int out_standby(struct audio_stream *stream)
2406{
2407 struct stream_out *out = (struct stream_out *)stream;
2408
2409 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2410 out->usecase, use_case_table[out->usecase]);
2411
2412 lock_output_stream(out);
2413 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002414 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002415 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002416 return 0;
2417}
2418
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002419static int out_on_error(struct audio_stream *stream)
2420{
2421 struct stream_out *out = (struct stream_out *)stream;
2422 struct audio_device *adev = out->dev;
2423 bool do_standby = false;
2424
2425 lock_output_stream(out);
2426 if (!out->standby) {
2427 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2428 stop_compressed_output_l(out);
2429 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2430 } else
2431 do_standby = true;
2432 }
2433 pthread_mutex_unlock(&out->lock);
2434
2435 if (do_standby)
2436 return out_standby(&out->stream.common);
2437
2438 return 0;
2439}
2440
Andy Hung7401c7c2016-09-21 12:41:21 -07002441static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002442{
Andy Hung7401c7c2016-09-21 12:41:21 -07002443 struct stream_out *out = (struct stream_out *)stream;
2444
2445 // We try to get the lock for consistency,
2446 // but it isn't necessary for these variables.
2447 // If we're not in standby, we may be blocked on a write.
2448 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2449 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2450 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2451
2452 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002453 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002454 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002455
2456 // dump error info
2457 (void)error_log_dump(
2458 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002459
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002460 return 0;
2461}
2462
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002463static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2464{
2465 int ret = 0;
2466 char value[32];
2467 struct compr_gapless_mdata tmp_mdata;
2468
2469 if (!out || !parms) {
2470 return -EINVAL;
2471 }
2472
2473 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2474 if (ret >= 0) {
2475 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2476 } else {
2477 return -EINVAL;
2478 }
2479
2480 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2481 if (ret >= 0) {
2482 tmp_mdata.encoder_padding = atoi(value);
2483 } else {
2484 return -EINVAL;
2485 }
2486
2487 out->gapless_mdata = tmp_mdata;
2488 out->send_new_metadata = 1;
2489 ALOGV("%s new encoder delay %u and padding %u", __func__,
2490 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2491
2492 return 0;
2493}
2494
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002495static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2496{
2497 return out == adev->primary_output || out == adev->voice_tx_output;
2498}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002499
Kevin Rocard1e02c882017-08-09 15:26:07 -07002500static int get_alive_usb_card(struct str_parms* parms) {
2501 int card;
2502 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2503 !audio_extn_usb_alive(card)) {
2504 return card;
2505 }
2506 return -ENODEV;
2507}
2508
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002509static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2510{
2511 struct stream_out *out = (struct stream_out *)stream;
2512 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002513 struct audio_usecase *usecase;
2514 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002515 struct str_parms *parms;
2516 char value[32];
2517 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002518 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002519 int status = 0;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002520 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002521
Eric Laurent2e140aa2016-06-30 17:14:46 -07002522 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002523 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002524 parms = str_parms_create_str(kvpairs);
2525 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2526 if (ret >= 0) {
2527 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002528
Eric Laurenta1478072015-09-21 17:21:52 -07002529 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002530
2531 // The usb driver needs to be closed after usb device disconnection
2532 // otherwise audio is no longer played on the new usb devices.
2533 // By forcing the stream in standby, the usb stack refcount drops to 0
2534 // and the driver is closed.
2535 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD && val == AUDIO_DEVICE_NONE &&
2536 audio_is_usb_out_device(out->devices)) {
2537 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2538 out_standby_l(&out->stream.common);
2539 }
2540
Eric Laurent150dbfe2013-02-27 14:31:02 -08002541 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002542
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002543 /*
2544 * When HDMI cable is unplugged the music playback is paused and
2545 * the policy manager sends routing=0. But the audioflinger
2546 * continues to write data until standby time (3sec).
2547 * As the HDMI core is turned off, the write gets blocked.
2548 * Avoid this by routing audio to speaker until standby.
2549 */
2550 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2551 val == AUDIO_DEVICE_NONE) {
2552 val = AUDIO_DEVICE_OUT_SPEAKER;
2553 }
2554
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002555 /*
2556 * When A2DP is disconnected the
2557 * music playback is paused and the policy manager sends routing=0
2558 * But the audioflingercontinues to write data until standby time
2559 * (3sec). As BT is turned off, the write gets blocked.
2560 * Avoid this by routing audio to speaker until standby.
2561 */
2562 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2563 (val == AUDIO_DEVICE_NONE) &&
2564 !audio_extn_a2dp_is_ready()) {
2565 val = AUDIO_DEVICE_OUT_SPEAKER;
2566 }
2567
2568 /* To avoid a2dp to sco overlapping / BT device improper state
2569 * check with BT lib about a2dp streaming support before routing
2570 */
2571 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2572 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002573 if (val & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002574 //combo usecase just by pass a2dp
2575 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2576 bypass_a2dp = true;
2577 } else {
2578 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2579 /* update device to a2dp and don't route as BT returned error
2580 * However it is still possible a2dp routing called because
2581 * of current active device disconnection (like wired headset)
2582 */
2583 out->devices = val;
2584 pthread_mutex_unlock(&out->lock);
2585 pthread_mutex_unlock(&adev->lock);
2586 status = -ENOSYS;
2587 goto routing_fail;
2588 }
2589 }
2590 }
2591
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002592 audio_devices_t new_dev = val;
2593
2594 // Workaround: If routing to an non existing usb device, fail gracefully
2595 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002596 int card;
2597 if (audio_is_usb_out_device(new_dev) &&
2598 (card = get_alive_usb_card(parms)) >= 0) {
2599
2600 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002601 pthread_mutex_unlock(&adev->lock);
2602 pthread_mutex_unlock(&out->lock);
2603 status = -ENOSYS;
2604 goto routing_fail;
2605 }
2606
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002607 /*
2608 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002609 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002610 * the select_devices(). But how do we undo this?
2611 *
2612 * For example, music playback is active on headset (deep-buffer usecase)
2613 * and if we go to ringtones and select a ringtone, low-latency usecase
2614 * will be started on headset+speaker. As we can't enable headset+speaker
2615 * and headset devices at the same time, select_devices() switches the music
2616 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2617 * So when the ringtone playback is completed, how do we undo the same?
2618 *
2619 * We are relying on the out_set_parameters() call on deep-buffer output,
2620 * once the ringtone playback is ended.
2621 * NOTE: We should not check if the current devices are same as new devices.
2622 * Because select_devices() must be called to switch back the music
2623 * playback to headset.
2624 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002625 if (new_dev != AUDIO_DEVICE_NONE) {
2626 bool same_dev = out->devices == new_dev;
2627 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002628
Eric Laurenta7657192014-10-09 21:09:33 -07002629 if (output_drives_call(adev, out)) {
Vignesh Kulothungana5c9da12017-11-10 11:41:24 -08002630 if (!voice_is_call_state_active(adev)) {
Eric Laurenta7657192014-10-09 21:09:33 -07002631 if (adev->mode == AUDIO_MODE_IN_CALL) {
2632 adev->current_call_output = out;
2633 ret = voice_start_call(adev);
2634 }
2635 } else {
2636 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002637 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002638 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002639 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002640
2641 if (!out->standby) {
2642 if (!same_dev) {
2643 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002644 // inform adm before actual routing to prevent glitches.
2645 if (adev->adm_on_routing_change) {
2646 adev->adm_on_routing_change(adev->adm_data,
2647 out->handle);
2648 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002649 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002650 if (!bypass_a2dp) {
2651 select_devices(adev, out->usecase);
2652 } else {
juyuchen9baad392018-06-05 19:02:10 +08002653 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2654 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2655 else
2656 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002657 select_devices(adev, out->usecase);
2658 out->devices = new_dev;
2659 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002660 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002661
2662 // on device switch force swap, lower functions will make sure
2663 // to check if swap is allowed or not.
2664
2665 if (!same_dev)
2666 platform_set_swap_channels(adev, true);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002667
2668 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2669 out->a2dp_compress_mute &&
2670 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
2671 pthread_mutex_lock(&out->compr_mute_lock);
2672 out->a2dp_compress_mute = false;
2673 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
2674 pthread_mutex_unlock(&out->compr_mute_lock);
2675 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002676 }
2677
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002678 }
2679
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002680 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002681 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002682
2683 /*handles device and call state changes*/
2684 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002685 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002686 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002687
2688 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2689 parse_compress_metadata(out, parms);
2690 }
2691
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002692 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002693 ALOGV("%s: exit: code(%d)", __func__, status);
2694 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002695}
2696
Haynes Mathew George569b7482017-05-08 14:44:27 -07002697static bool stream_get_parameter_channels(struct str_parms *query,
2698 struct str_parms *reply,
2699 audio_channel_mask_t *supported_channel_masks) {
2700 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002701 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002702 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002703 size_t i, j;
2704
2705 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2706 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002707 value[0] = '\0';
2708 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002709 while (supported_channel_masks[i] != 0) {
2710 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2711 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002712 if (!first) {
2713 strcat(value, "|");
2714 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002715 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002716 first = false;
2717 break;
2718 }
2719 }
2720 i++;
2721 }
2722 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002723 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002724 return ret >= 0;
2725}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002726
Haynes Mathew George569b7482017-05-08 14:44:27 -07002727static bool stream_get_parameter_formats(struct str_parms *query,
2728 struct str_parms *reply,
2729 audio_format_t *supported_formats) {
2730 int ret = -1;
2731 char value[256];
2732 int i;
2733
2734 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2735 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002736 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002737 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002738 case AUDIO_FORMAT_PCM_16_BIT:
2739 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2740 break;
2741 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2742 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2743 break;
2744 case AUDIO_FORMAT_PCM_32_BIT:
2745 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2746 break;
2747 default:
2748 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002749 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002750 break;
2751 }
2752 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002753 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002754 return ret >= 0;
2755}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002756
Haynes Mathew George569b7482017-05-08 14:44:27 -07002757static bool stream_get_parameter_rates(struct str_parms *query,
2758 struct str_parms *reply,
2759 uint32_t *supported_sample_rates) {
2760
2761 int i;
2762 char value[256];
2763 int ret = -1;
2764 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2765 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002766 value[0] = '\0';
2767 i=0;
2768 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002769 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002770 int avail = sizeof(value) - cursor;
2771 ret = snprintf(value + cursor, avail, "%s%d",
2772 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002773 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002774 if (ret < 0 || ret >= avail) {
2775 // if cursor is at the last element of the array
2776 // overwrite with \0 is duplicate work as
2777 // snprintf already put a \0 in place.
2778 // else
2779 // we had space to write the '|' at value[cursor]
2780 // (which will be overwritten) or no space to fill
2781 // the first element (=> cursor == 0)
2782 value[cursor] = '\0';
2783 break;
2784 }
2785 cursor += ret;
2786 ++i;
2787 }
2788 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2789 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002790 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002791 return ret >= 0;
2792}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002793
Haynes Mathew George569b7482017-05-08 14:44:27 -07002794static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2795{
2796 struct stream_out *out = (struct stream_out *)stream;
2797 struct str_parms *query = str_parms_create_str(keys);
2798 char *str;
2799 struct str_parms *reply = str_parms_create();
2800 bool replied = false;
2801 ALOGV("%s: enter: keys - %s", __func__, keys);
2802
2803 replied |= stream_get_parameter_channels(query, reply,
2804 &out->supported_channel_masks[0]);
2805 replied |= stream_get_parameter_formats(query, reply,
2806 &out->supported_formats[0]);
2807 replied |= stream_get_parameter_rates(query, reply,
2808 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002809 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002810 str = str_parms_to_str(reply);
2811 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002812 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002813 }
2814 str_parms_destroy(query);
2815 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002816 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002817 return str;
2818}
2819
2820static uint32_t out_get_latency(const struct audio_stream_out *stream)
2821{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002822 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002823 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002824 uint32_t latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002825
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002826 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2827 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002828 else if ((out->realtime) ||
2829 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002830 // since the buffer won't be filled up faster than realtime,
2831 // return a smaller number
2832 period_ms = (out->af_period_multiplier * out->config.period_size *
2833 1000) / (out->config.rate);
2834 hw_delay = platform_render_latency(out->usecase)/1000;
2835 return period_ms + hw_delay;
2836 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002837
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002838 latency = (out->config.period_count * out->config.period_size * 1000) /
2839 (out->config.rate);
2840
2841 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
2842 latency += audio_extn_a2dp_get_encoder_latency();
2843
2844 return latency;
2845}
2846
2847static int set_compr_volume(struct audio_stream_out *stream, float left,
2848 float right)
2849{
2850 struct stream_out *out = (struct stream_out *)stream;
2851 int volume[2];
2852 char mixer_ctl_name[128];
2853 struct audio_device *adev = out->dev;
2854 struct mixer_ctl *ctl;
2855 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2856 PCM_PLAYBACK);
2857
2858 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2859 "Compress Playback %d Volume", pcm_device_id);
2860 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2861 if (!ctl) {
2862 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2863 __func__, mixer_ctl_name);
2864 return -EINVAL;
2865 }
2866 ALOGV("%s: ctl for mixer cmd - %s, left %f, right %f",
2867 __func__, mixer_ctl_name, left, right);
2868 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2869 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2870 mixer_ctl_set_array(ctl, volume, sizeof(volume) / sizeof(volume[0]));
2871
2872 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002873}
2874
2875static int out_set_volume(struct audio_stream_out *stream, float left,
2876 float right)
2877{
Eric Laurenta9024de2013-04-04 09:19:12 -07002878 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002879 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002880
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002881 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002882 /* only take left channel into account: the API is for stereo anyway */
2883 out->muted = (left == 0.0f);
2884 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002885 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002886 pthread_mutex_lock(&out->compr_mute_lock);
2887 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
2888 if (!out->a2dp_compress_mute)
2889 ret = set_compr_volume(stream, left, right);
2890 out->volume_l = left;
2891 out->volume_r = right;
2892 pthread_mutex_unlock(&out->compr_mute_lock);
2893 return ret;
vivek mehtaa68fea62017-06-08 19:04:02 -07002894 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002895 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2896 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2897 if (!out->standby) {
2898 // if in standby, cached volume will be sent after stream is opened
2899 audio_extn_utils_send_app_type_gain(out->dev,
2900 out->app_type_cfg.app_type,
2901 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002902 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002903 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002904 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002905
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002906 return -ENOSYS;
2907}
2908
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002909// note: this call is safe only if the stream_cb is
2910// removed first in close_output_stream (as is done now).
2911static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2912{
2913 if (!stream || !parms)
2914 return;
2915
2916 struct stream_out *out = (struct stream_out *)stream;
2917 struct audio_device *adev = out->dev;
2918
2919 card_status_t status;
2920 int card;
2921 if (parse_snd_card_status(parms, &card, &status) < 0)
2922 return;
2923
2924 pthread_mutex_lock(&adev->lock);
2925 bool valid_cb = (card == adev->snd_card);
2926 pthread_mutex_unlock(&adev->lock);
2927
2928 if (!valid_cb)
2929 return;
2930
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002931 lock_output_stream(out);
2932 if (out->card_status != status)
2933 out->card_status = status;
2934 pthread_mutex_unlock(&out->lock);
2935
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002936 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2937 use_case_table[out->usecase],
2938 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2939
2940 if (status == CARD_STATUS_OFFLINE)
2941 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002942
2943 return;
2944}
2945
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002946#ifdef NO_AUDIO_OUT
2947static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002948 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002949{
2950 struct stream_out *out = (struct stream_out *)stream;
2951
2952 /* No Output device supported other than BT for playback.
2953 * Sleep for the amount of buffer duration
2954 */
Eric Laurenta1478072015-09-21 17:21:52 -07002955 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002956 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2957 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002958 out_get_sample_rate(&out->stream.common));
2959 pthread_mutex_unlock(&out->lock);
2960 return bytes;
2961}
2962#endif
2963
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002964static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2965 size_t bytes)
2966{
2967 struct stream_out *out = (struct stream_out *)stream;
2968 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002969 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002970 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002971
Eric Laurenta1478072015-09-21 17:21:52 -07002972 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002973 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07002974 const size_t frame_size = audio_stream_out_frame_size(stream);
2975 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002976
Eric Laurent0e46adf2016-12-16 12:49:24 -08002977 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2978 error_code = ERROR_CODE_WRITE;
2979 goto exit;
2980 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002981
2982 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2983 (audio_extn_a2dp_is_suspended())) {
juyuchen9baad392018-06-05 19:02:10 +08002984 if (!(out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002985 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2986 ret = -EIO;
2987 goto exit;
2988 }
2989 }
2990 }
2991
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002992 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002993 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002994 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002995 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07002996
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002997 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002998 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002999 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07003000 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003001 goto exit;
3002 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07003003
vivek mehta40125092017-08-21 18:48:51 -07003004 // after standby always force set last known cal step
3005 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
3006 ALOGD("%s: retry previous failed cal level set", __func__);
3007 send_gain_dep_calibration_l();
3008 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003009 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003010
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003011 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003012 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003013 if (out->send_new_metadata) {
3014 ALOGVV("send new gapless metadata");
3015 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3016 out->send_new_metadata = 0;
3017 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003018 unsigned int avail;
3019 struct timespec tstamp;
3020 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
3021 /* Do not limit write size if the available frames count is unknown */
3022 if (ret != 0) {
3023 avail = bytes;
3024 }
3025 if (avail == 0) {
3026 ret = 0;
3027 } else {
3028 if (avail > bytes) {
3029 avail = bytes;
3030 }
3031 ret = compress_write(out->compr, buffer, avail);
3032 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
3033 __func__, avail, ret);
3034 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003035
Eric Laurent6e895242013-09-05 16:10:57 -07003036 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003037 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
3038 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003039 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003040 compress_start(out->compr);
3041 out->playback_started = 1;
3042 out->offload_state = OFFLOAD_STATE_PLAYING;
3043 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003044 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07003045 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07003046 } else {
3047 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07003048 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003049 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07003050 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003051 return ret;
3052 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07003053 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003054 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003055 size_t bytes_to_write = bytes;
3056
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003057 if (out->muted)
3058 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07003059 // FIXME: this can be removed once audio flinger mixer supports mono output
Nadav Bar3d72cfc2018-01-07 12:19:24 +02003060 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP || out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003061 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3062 int16_t *src = (int16_t *)buffer;
3063 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003064
Eric Laurentad2dde92017-09-20 18:27:31 -07003065 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
3066 out->format != AUDIO_FORMAT_PCM_16_BIT,
3067 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003068
Eric Laurentad2dde92017-09-20 18:27:31 -07003069 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
3070 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
3071 }
3072 bytes_to_write /= 2;
3073 }
3074 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes_to_write);
3075
Glenn Kasten5a59dff2018-02-22 08:05:35 -08003076 long ns = (frames * (int64_t) NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003077 request_out_focus(out, ns);
3078
3079 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3080 if (use_mmap)
Eric Laurentad2dde92017-09-20 18:27:31 -07003081 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003082 else
Eric Laurentad2dde92017-09-20 18:27:31 -07003083 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003084
Haynes Mathew George03c40102016-01-29 17:57:48 -08003085 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07003086 } else {
3087 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003088 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003089 }
3090
3091exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07003092 // For PCM we always consume the buffer and return #bytes regardless of ret.
3093 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003094 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07003095 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003096 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07003097
Andy Hung7401c7c2016-09-21 12:41:21 -07003098 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07003099 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07003100 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3101 ALOGE_IF(out->pcm != NULL,
3102 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07003103 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003104 // usleep not guaranteed for values over 1 second but we don't limit here.
3105 }
3106 }
Andy Hungda9b56b2016-09-16 20:06:35 -07003107
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003108 pthread_mutex_unlock(&out->lock);
3109
3110 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07003111 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003112 if (sleeptime_us != 0)
3113 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003114 }
3115 return bytes;
3116}
3117
3118static int out_get_render_position(const struct audio_stream_out *stream,
3119 uint32_t *dsp_frames)
3120{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003121 struct stream_out *out = (struct stream_out *)stream;
3122 *dsp_frames = 0;
3123 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07003124 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003125 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003126 unsigned long frames = 0;
3127 // TODO: check return value
3128 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
3129 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003130 ALOGVV("%s rendered frames %d sample_rate %d",
3131 __func__, *dsp_frames, out->sample_rate);
3132 }
3133 pthread_mutex_unlock(&out->lock);
3134 return 0;
3135 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003136 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003137}
3138
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003139static int out_add_audio_effect(const struct audio_stream *stream __unused,
3140 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003141{
3142 return 0;
3143}
3144
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003145static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3146 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003147{
3148 return 0;
3149}
3150
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003151static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3152 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003153{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003154 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003155}
3156
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003157static int out_get_presentation_position(const struct audio_stream_out *stream,
3158 uint64_t *frames, struct timespec *timestamp)
3159{
3160 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003161 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07003162 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003163
Eric Laurenta1478072015-09-21 17:21:52 -07003164 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003165
Eric Laurent949a0892013-09-20 09:20:13 -07003166 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3167 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003168 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07003169 compress_get_tstamp(out->compr, &dsp_frames,
3170 &out->sample_rate);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003171 // Adjustment accounts for A2DP encoder latency with offload usecases
3172 // Note: Encoder latency is returned in ms.
3173 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3174 unsigned long offset =
3175 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3176 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
3177 }
Eric Laurent949a0892013-09-20 09:20:13 -07003178 ALOGVV("%s rendered frames %ld sample_rate %d",
3179 __func__, dsp_frames, out->sample_rate);
3180 *frames = dsp_frames;
3181 ret = 0;
3182 /* this is the best we can do */
3183 clock_gettime(CLOCK_MONOTONIC, timestamp);
3184 }
3185 } else {
3186 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07003187 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003188 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3189 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003190 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003191 // This adjustment accounts for buffering after app processor.
3192 // It is based on estimated DSP latency per use case, rather than exact.
3193 signed_frames -=
3194 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3195
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003196 // Adjustment accounts for A2DP encoder latency with non-offload usecases
3197 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3198 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3199 signed_frames -=
3200 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3201 }
3202
Eric Laurent949a0892013-09-20 09:20:13 -07003203 // It would be unusual for this value to be negative, but check just in case ...
3204 if (signed_frames >= 0) {
3205 *frames = signed_frames;
3206 ret = 0;
3207 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003208 }
3209 }
3210 }
3211
3212 pthread_mutex_unlock(&out->lock);
3213
3214 return ret;
3215}
3216
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003217static int out_set_callback(struct audio_stream_out *stream,
3218 stream_callback_t callback, void *cookie)
3219{
3220 struct stream_out *out = (struct stream_out *)stream;
3221
3222 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003223 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003224 out->offload_callback = callback;
3225 out->offload_cookie = cookie;
3226 pthread_mutex_unlock(&out->lock);
3227 return 0;
3228}
3229
3230static int out_pause(struct audio_stream_out* stream)
3231{
3232 struct stream_out *out = (struct stream_out *)stream;
3233 int status = -ENOSYS;
3234 ALOGV("%s", __func__);
3235 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003236 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003237 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
3238 status = compress_pause(out->compr);
3239 out->offload_state = OFFLOAD_STATE_PAUSED;
3240 }
3241 pthread_mutex_unlock(&out->lock);
3242 }
3243 return status;
3244}
3245
3246static int out_resume(struct audio_stream_out* stream)
3247{
3248 struct stream_out *out = (struct stream_out *)stream;
3249 int status = -ENOSYS;
3250 ALOGV("%s", __func__);
3251 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3252 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07003253 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003254 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
3255 status = compress_resume(out->compr);
3256 out->offload_state = OFFLOAD_STATE_PLAYING;
3257 }
3258 pthread_mutex_unlock(&out->lock);
3259 }
3260 return status;
3261}
3262
3263static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3264{
3265 struct stream_out *out = (struct stream_out *)stream;
3266 int status = -ENOSYS;
3267 ALOGV("%s", __func__);
3268 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003269 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003270 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3271 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3272 else
3273 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3274 pthread_mutex_unlock(&out->lock);
3275 }
3276 return status;
3277}
3278
3279static int out_flush(struct audio_stream_out* stream)
3280{
3281 struct stream_out *out = (struct stream_out *)stream;
3282 ALOGV("%s", __func__);
3283 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003284 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003285 stop_compressed_output_l(out);
3286 pthread_mutex_unlock(&out->lock);
3287 return 0;
3288 }
3289 return -ENOSYS;
3290}
3291
Eric Laurent0e46adf2016-12-16 12:49:24 -08003292static int out_stop(const struct audio_stream_out* stream)
3293{
3294 struct stream_out *out = (struct stream_out *)stream;
3295 struct audio_device *adev = out->dev;
3296 int ret = -ENOSYS;
3297
3298 ALOGV("%s", __func__);
3299 pthread_mutex_lock(&adev->lock);
3300 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3301 out->playback_started && out->pcm != NULL) {
3302 pcm_stop(out->pcm);
3303 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08003304 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003305 }
3306 pthread_mutex_unlock(&adev->lock);
3307 return ret;
3308}
3309
3310static int out_start(const struct audio_stream_out* stream)
3311{
3312 struct stream_out *out = (struct stream_out *)stream;
3313 struct audio_device *adev = out->dev;
3314 int ret = -ENOSYS;
3315
3316 ALOGV("%s", __func__);
3317 pthread_mutex_lock(&adev->lock);
3318 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3319 !out->playback_started && out->pcm != NULL) {
3320 ret = start_output_stream(out);
3321 if (ret == 0) {
3322 out->playback_started = true;
3323 }
3324 }
3325 pthread_mutex_unlock(&adev->lock);
3326 return ret;
3327}
3328
Phil Burkbc991042017-02-24 08:06:44 -08003329/*
3330 * Modify config->period_count based on min_size_frames
3331 */
3332static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
3333{
3334 int periodCountRequested = (min_size_frames + config->period_size - 1)
3335 / config->period_size;
3336 int periodCount = MMAP_PERIOD_COUNT_MIN;
3337
3338 ALOGV("%s original config.period_size = %d config.period_count = %d",
3339 __func__, config->period_size, config->period_count);
3340
3341 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
3342 periodCount *= 2;
3343 }
3344 config->period_count = periodCount;
3345
3346 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
3347}
3348
Eric Laurent0e46adf2016-12-16 12:49:24 -08003349static int out_create_mmap_buffer(const struct audio_stream_out *stream,
3350 int32_t min_size_frames,
3351 struct audio_mmap_buffer_info *info)
3352{
3353 struct stream_out *out = (struct stream_out *)stream;
3354 struct audio_device *adev = out->dev;
3355 int ret = 0;
3356 unsigned int offset1;
3357 unsigned int frames1;
3358 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003359 uint32_t mmap_size;
3360 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003361
3362 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003363 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003364 pthread_mutex_lock(&adev->lock);
3365
3366 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003367 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003368 ret = -EINVAL;
3369 goto exit;
3370 }
3371 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003372 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003373 ret = -ENOSYS;
3374 goto exit;
3375 }
3376 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3377 if (out->pcm_device_id < 0) {
3378 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3379 __func__, out->pcm_device_id, out->usecase);
3380 ret = -EINVAL;
3381 goto exit;
3382 }
Phil Burkbc991042017-02-24 08:06:44 -08003383
3384 adjust_mmap_period_count(&out->config, min_size_frames);
3385
Eric Laurent0e46adf2016-12-16 12:49:24 -08003386 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3387 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3388 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3389 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3390 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3391 step = "open";
3392 ret = -ENODEV;
3393 goto exit;
3394 }
3395 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3396 if (ret < 0) {
3397 step = "begin";
3398 goto exit;
3399 }
3400 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003401 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003402 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003403 ret = platform_get_mmap_data_fd(adev->platform,
3404 out->pcm_device_id, 0 /*playback*/,
3405 &info->shared_memory_fd,
3406 &mmap_size);
3407 if (ret < 0) {
3408 // Fall back to non exclusive mode
3409 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3410 } else {
3411 if (mmap_size < buffer_size) {
3412 step = "mmap";
3413 goto exit;
3414 }
3415 // FIXME: indicate exclusive mode support by returning a negative buffer size
3416 info->buffer_size_frames *= -1;
3417 }
3418 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003419
3420 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3421 if (ret < 0) {
3422 step = "commit";
3423 goto exit;
3424 }
Phil Burkbc991042017-02-24 08:06:44 -08003425
3426 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003427 ret = 0;
3428
3429 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3430 __func__, info->shared_memory_address, info->buffer_size_frames);
3431
3432exit:
3433 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003434 if (out->pcm == NULL) {
3435 ALOGE("%s: %s - %d", __func__, step, ret);
3436 } else {
3437 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003438 pcm_close(out->pcm);
3439 out->pcm = NULL;
3440 }
3441 }
3442 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003443 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003444 return ret;
3445}
3446
3447static int out_get_mmap_position(const struct audio_stream_out *stream,
3448 struct audio_mmap_position *position)
3449{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003450 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003451 struct stream_out *out = (struct stream_out *)stream;
3452 ALOGVV("%s", __func__);
3453 if (position == NULL) {
3454 return -EINVAL;
3455 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003456 lock_output_stream(out);
3457 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3458 out->pcm == NULL) {
3459 ret = -ENOSYS;
3460 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003461 }
3462
3463 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003464 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003465 if (ret < 0) {
3466 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003467 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003468 }
Andy Hungfc044e12017-03-20 09:24:22 -07003469 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003470exit:
3471 pthread_mutex_unlock(&out->lock);
3472 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003473}
3474
3475
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003476/** audio_stream_in implementation **/
3477static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3478{
3479 struct stream_in *in = (struct stream_in *)stream;
3480
3481 return in->config.rate;
3482}
3483
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003484static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003485{
3486 return -ENOSYS;
3487}
3488
3489static size_t in_get_buffer_size(const struct audio_stream *stream)
3490{
3491 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003492 return in->config.period_size * in->af_period_multiplier *
3493 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003494}
3495
3496static uint32_t in_get_channels(const struct audio_stream *stream)
3497{
3498 struct stream_in *in = (struct stream_in *)stream;
3499
3500 return in->channel_mask;
3501}
3502
vivek mehta4ed66e62016-04-15 23:33:34 -07003503static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003504{
vivek mehta4ed66e62016-04-15 23:33:34 -07003505 struct stream_in *in = (struct stream_in *)stream;
3506 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003507}
3508
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003509static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003510{
3511 return -ENOSYS;
3512}
3513
3514static int in_standby(struct audio_stream *stream)
3515{
3516 struct stream_in *in = (struct stream_in *)stream;
3517 struct audio_device *adev = in->dev;
3518 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003519 bool do_stop = true;
3520
Eric Laurent994a6932013-07-17 11:51:42 -07003521 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003522
3523 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003524
3525 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003526 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003527 audio_extn_sound_trigger_stop_lab(in);
3528 in->standby = true;
3529 }
3530
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003531 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003532 if (adev->adm_deregister_stream)
3533 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3534
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003535 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003536 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003537 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003538 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003539 in->capture_started = false;
3540 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003541 if (in->pcm) {
3542 pcm_close(in->pcm);
3543 in->pcm = NULL;
3544 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003545 adev->enable_voicerx = false;
3546 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003547 if (do_stop) {
3548 status = stop_input_stream(in);
3549 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003550 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003551 }
3552 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003553 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003554 return status;
3555}
3556
Andy Hungd13f0d32017-06-12 13:58:37 -07003557static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003558{
Andy Hungd13f0d32017-06-12 13:58:37 -07003559 struct stream_in *in = (struct stream_in *)stream;
3560
3561 // We try to get the lock for consistency,
3562 // but it isn't necessary for these variables.
3563 // If we're not in standby, we may be blocked on a read.
3564 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3565 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3566 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3567 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3568
3569 if (locked) {
3570 pthread_mutex_unlock(&in->lock);
3571 }
3572
3573 // dump error info
3574 (void)error_log_dump(
3575 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003576 return 0;
3577}
3578
3579static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3580{
3581 struct stream_in *in = (struct stream_in *)stream;
3582 struct audio_device *adev = in->dev;
3583 struct str_parms *parms;
3584 char *str;
3585 char value[32];
3586 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003587 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003588
Eric Laurent994a6932013-07-17 11:51:42 -07003589 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003590 parms = str_parms_create_str(kvpairs);
3591
3592 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3593
Eric Laurenta1478072015-09-21 17:21:52 -07003594 lock_input_stream(in);
3595
Eric Laurent150dbfe2013-02-27 14:31:02 -08003596 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003597 if (ret >= 0) {
3598 val = atoi(value);
3599 /* no audio source uses val == 0 */
3600 if ((in->source != val) && (val != 0)) {
3601 in->source = val;
3602 }
3603 }
3604
3605 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003606
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003607 if (ret >= 0) {
3608 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003609 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003610
3611 // Workaround: If routing to an non existing usb device, fail gracefully
3612 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003613 int card;
3614 if (audio_is_usb_in_device(val) &&
3615 (card = get_alive_usb_card(parms)) >= 0) {
3616
3617 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003618 status = -ENOSYS;
3619 } else {
3620
3621 in->device = val;
3622 /* If recording is in progress, change the tx device to new device */
3623 if (!in->standby) {
3624 ALOGV("update input routing change");
3625 // inform adm before actual routing to prevent glitches.
3626 if (adev->adm_on_routing_change) {
3627 adev->adm_on_routing_change(adev->adm_data,
3628 in->capture_handle);
3629 }
3630 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003631 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003632 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003633 }
3634 }
3635
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003636 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003637 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003638
3639 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003640 ALOGV("%s: exit: status(%d)", __func__, status);
3641 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003642}
3643
Haynes Mathew George569b7482017-05-08 14:44:27 -07003644static char* in_get_parameters(const struct audio_stream *stream,
3645 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003646{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003647 struct stream_in *in = (struct stream_in *)stream;
3648 struct str_parms *query = str_parms_create_str(keys);
3649 char *str;
3650 struct str_parms *reply = str_parms_create();
3651 bool replied = false;
3652
3653 ALOGV("%s: enter: keys - %s", __func__, keys);
3654 replied |= stream_get_parameter_channels(query, reply,
3655 &in->supported_channel_masks[0]);
3656 replied |= stream_get_parameter_formats(query, reply,
3657 &in->supported_formats[0]);
3658 replied |= stream_get_parameter_rates(query, reply,
3659 &in->supported_sample_rates[0]);
3660 if (replied) {
3661 str = str_parms_to_str(reply);
3662 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003663 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003664 }
3665 str_parms_destroy(query);
3666 str_parms_destroy(reply);
3667 ALOGV("%s: exit: returns - %s", __func__, str);
3668 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003669}
3670
Eric Laurent51f3c662018-04-10 18:21:34 -07003671static int in_set_gain(struct audio_stream_in *stream, float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003672{
Eric Laurent51f3c662018-04-10 18:21:34 -07003673 struct stream_in *in = (struct stream_in *)stream;
3674 char mixer_ctl_name[128];
3675 struct mixer_ctl *ctl;
3676 int ctl_value;
3677
3678 ALOGV("%s: gain %f", __func__, gain);
3679
3680 if (stream == NULL)
3681 return -EINVAL;
3682
3683 /* in_set_gain() only used to silence MMAP capture for now */
3684 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
3685 return -ENOSYS;
3686
3687 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
3688
3689 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
3690 if (!ctl) {
3691 ALOGW("%s: Could not get ctl for mixer cmd - %s",
3692 __func__, mixer_ctl_name);
3693 return -ENOSYS;
3694 }
3695
3696 if (gain < RECORD_GAIN_MIN)
3697 gain = RECORD_GAIN_MIN;
3698 else if (gain > RECORD_GAIN_MAX)
3699 gain = RECORD_GAIN_MAX;
3700 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
3701
3702 mixer_ctl_set_value(ctl, 0, ctl_value);
3703 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003704}
3705
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003706static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3707{
3708 if (!stream || !parms)
3709 return;
3710
3711 struct stream_in *in = (struct stream_in *)stream;
3712 struct audio_device *adev = in->dev;
3713
3714 card_status_t status;
3715 int card;
3716 if (parse_snd_card_status(parms, &card, &status) < 0)
3717 return;
3718
3719 pthread_mutex_lock(&adev->lock);
3720 bool valid_cb = (card == adev->snd_card);
3721 pthread_mutex_unlock(&adev->lock);
3722
3723 if (!valid_cb)
3724 return;
3725
3726 lock_input_stream(in);
3727 if (in->card_status != status)
3728 in->card_status = status;
3729 pthread_mutex_unlock(&in->lock);
3730
3731 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3732 use_case_table[in->usecase],
3733 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3734
3735 // a better solution would be to report error back to AF and let
3736 // it put the stream to standby
3737 if (status == CARD_STATUS_OFFLINE)
3738 in_standby(&in->stream.common);
3739
3740 return;
3741}
3742
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003743static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3744 size_t bytes)
3745{
3746 struct stream_in *in = (struct stream_in *)stream;
3747 struct audio_device *adev = in->dev;
3748 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003749 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003750 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003751
Eric Laurenta1478072015-09-21 17:21:52 -07003752 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003753 const size_t frame_size = audio_stream_in_frame_size(stream);
3754 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003755
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003756 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003757 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003758 /* Read from sound trigger HAL */
3759 audio_extn_sound_trigger_read(in, buffer, bytes);
3760 pthread_mutex_unlock(&in->lock);
3761 return bytes;
3762 }
3763
Eric Laurent0e46adf2016-12-16 12:49:24 -08003764 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3765 ret = -ENOSYS;
3766 goto exit;
3767 }
3768
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003769 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003770 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003771 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003772 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003773 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003774 goto exit;
3775 }
3776 in->standby = 0;
3777 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003778
Andy Hungd13f0d32017-06-12 13:58:37 -07003779 // errors that occur here are read errors.
3780 error_code = ERROR_CODE_READ;
3781
Haynes Mathew George03c40102016-01-29 17:57:48 -08003782 //what's the duration requested by the client?
3783 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3784 in->config.rate;
3785 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003786
Haynes Mathew George03c40102016-01-29 17:57:48 -08003787 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003788 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003789 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003790 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003791 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003792 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003793 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003794 if (ret < 0) {
3795 ALOGE("Failed to read w/err %s", strerror(errno));
3796 ret = -errno;
3797 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003798 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3799 if (bytes % 4 == 0) {
3800 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3801 int_buf_stream = buffer;
3802 for (size_t itt=0; itt < bytes/4 ; itt++) {
3803 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003804 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003805 } else {
3806 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3807 ret = -EINVAL;
3808 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003809 }
3810 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003811 }
3812
Haynes Mathew George03c40102016-01-29 17:57:48 -08003813 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003814
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003815 /*
3816 * Instead of writing zeroes here, we could trust the hardware
3817 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003818 * 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 -08003819 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08003820 if (ret == 0 && adev->mic_muted &&
3821 !voice_is_in_call_rec_stream(in) &&
3822 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003823 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07003824 in->frames_muted += frames;
3825 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003826
3827exit:
3828 pthread_mutex_unlock(&in->lock);
3829
3830 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07003831 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003832 in_standby(&in->stream.common);
3833 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003834 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003835 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07003836 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08003837 }
3838 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003839 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003840 }
3841 return bytes;
3842}
3843
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003844static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003845{
3846 return 0;
3847}
3848
Andy Hung6ebe5962016-01-15 17:46:57 -08003849static int in_get_capture_position(const struct audio_stream_in *stream,
3850 int64_t *frames, int64_t *time)
3851{
3852 if (stream == NULL || frames == NULL || time == NULL) {
3853 return -EINVAL;
3854 }
3855 struct stream_in *in = (struct stream_in *)stream;
3856 int ret = -ENOSYS;
3857
3858 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003859 // note: ST sessions do not close the alsa pcm driver synchronously
3860 // on standby. Therefore, we may return an error even though the
3861 // pcm stream is still opened.
3862 if (in->standby) {
3863 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
3864 "%s stream in standby but pcm not NULL for non ST session", __func__);
3865 goto exit;
3866 }
Andy Hung6ebe5962016-01-15 17:46:57 -08003867 if (in->pcm) {
3868 struct timespec timestamp;
3869 unsigned int avail;
3870 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3871 *frames = in->frames_read + avail;
3872 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3873 ret = 0;
3874 }
3875 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003876exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08003877 pthread_mutex_unlock(&in->lock);
3878 return ret;
3879}
3880
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003881static int add_remove_audio_effect(const struct audio_stream *stream,
3882 effect_handle_t effect,
3883 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003884{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003885 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003886 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003887 int status = 0;
3888 effect_descriptor_t desc;
3889
3890 status = (*effect)->get_descriptor(effect, &desc);
3891 if (status != 0)
3892 return status;
3893
Eric Laurenta1478072015-09-21 17:21:52 -07003894 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003895 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003896 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003897 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003898 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003899 in->enable_aec != enable &&
3900 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3901 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003902 if (!enable)
3903 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003904 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3905 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3906 adev->enable_voicerx = enable;
3907 struct audio_usecase *usecase;
3908 struct listnode *node;
3909 list_for_each(node, &adev->usecase_list) {
3910 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07003911 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07003912 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05003913 }
3914 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003915 if (!in->standby)
3916 select_devices(in->dev, in->usecase);
3917 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003918 if (in->enable_ns != enable &&
3919 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3920 in->enable_ns = enable;
3921 if (!in->standby)
3922 select_devices(in->dev, in->usecase);
3923 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003924 pthread_mutex_unlock(&in->dev->lock);
3925 pthread_mutex_unlock(&in->lock);
3926
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003927 return 0;
3928}
3929
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003930static int in_add_audio_effect(const struct audio_stream *stream,
3931 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003932{
Eric Laurent994a6932013-07-17 11:51:42 -07003933 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003934 return add_remove_audio_effect(stream, effect, true);
3935}
3936
3937static int in_remove_audio_effect(const struct audio_stream *stream,
3938 effect_handle_t effect)
3939{
Eric Laurent994a6932013-07-17 11:51:42 -07003940 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003941 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003942}
3943
Eric Laurent0e46adf2016-12-16 12:49:24 -08003944static int in_stop(const struct audio_stream_in* stream)
3945{
3946 struct stream_in *in = (struct stream_in *)stream;
3947 struct audio_device *adev = in->dev;
3948
3949 int ret = -ENOSYS;
3950 ALOGV("%s", __func__);
3951 pthread_mutex_lock(&adev->lock);
3952 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3953 in->capture_started && in->pcm != NULL) {
3954 pcm_stop(in->pcm);
3955 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003956 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003957 }
3958 pthread_mutex_unlock(&adev->lock);
3959 return ret;
3960}
3961
3962static int in_start(const struct audio_stream_in* stream)
3963{
3964 struct stream_in *in = (struct stream_in *)stream;
3965 struct audio_device *adev = in->dev;
3966 int ret = -ENOSYS;
3967
3968 ALOGV("%s in %p", __func__, in);
3969 pthread_mutex_lock(&adev->lock);
3970 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3971 !in->capture_started && in->pcm != NULL) {
3972 if (!in->capture_started) {
3973 ret = start_input_stream(in);
3974 if (ret == 0) {
3975 in->capture_started = true;
3976 }
3977 }
3978 }
3979 pthread_mutex_unlock(&adev->lock);
3980 return ret;
3981}
3982
3983static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3984 int32_t min_size_frames,
3985 struct audio_mmap_buffer_info *info)
3986{
3987 struct stream_in *in = (struct stream_in *)stream;
3988 struct audio_device *adev = in->dev;
3989 int ret = 0;
3990 unsigned int offset1;
3991 unsigned int frames1;
3992 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003993 uint32_t mmap_size;
3994 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003995
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003996 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003997 pthread_mutex_lock(&adev->lock);
3998 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003999
Eric Laurent0e46adf2016-12-16 12:49:24 -08004000 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004001 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004002 ret = -EINVAL;
4003 goto exit;
4004 }
4005 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08004006 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004007 ALOGV("%s in %p", __func__, in);
4008 ret = -ENOSYS;
4009 goto exit;
4010 }
4011 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
4012 if (in->pcm_device_id < 0) {
4013 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4014 __func__, in->pcm_device_id, in->usecase);
4015 ret = -EINVAL;
4016 goto exit;
4017 }
Phil Burkbc991042017-02-24 08:06:44 -08004018
4019 adjust_mmap_period_count(&in->config, min_size_frames);
4020
Eric Laurent0e46adf2016-12-16 12:49:24 -08004021 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4022 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
4023 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
4024 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
4025 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
4026 step = "open";
4027 ret = -ENODEV;
4028 goto exit;
4029 }
4030
4031 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
4032 if (ret < 0) {
4033 step = "begin";
4034 goto exit;
4035 }
4036 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07004037 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004038 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07004039 ret = platform_get_mmap_data_fd(adev->platform,
4040 in->pcm_device_id, 1 /*capture*/,
4041 &info->shared_memory_fd,
4042 &mmap_size);
4043 if (ret < 0) {
4044 // Fall back to non exclusive mode
4045 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
4046 } else {
4047 if (mmap_size < buffer_size) {
4048 step = "mmap";
4049 goto exit;
4050 }
4051 // FIXME: indicate exclusive mode support by returning a negative buffer size
4052 info->buffer_size_frames *= -1;
4053 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08004054
Haynes Mathew George96483a22017-03-28 14:52:47 -07004055 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004056
4057 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4058 if (ret < 0) {
4059 step = "commit";
4060 goto exit;
4061 }
4062
Phil Burkbc991042017-02-24 08:06:44 -08004063 in->standby = false;
4064 ret = 0;
4065
Eric Laurent0e46adf2016-12-16 12:49:24 -08004066 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4067 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004068
4069exit:
4070 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004071 if (in->pcm == NULL) {
4072 ALOGE("%s: %s - %d", __func__, step, ret);
4073 } else {
4074 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08004075 pcm_close(in->pcm);
4076 in->pcm = NULL;
4077 }
4078 }
4079 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004080 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004081 return ret;
4082}
4083
4084static int in_get_mmap_position(const struct audio_stream_in *stream,
4085 struct audio_mmap_position *position)
4086{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004087 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004088 struct stream_in *in = (struct stream_in *)stream;
4089 ALOGVV("%s", __func__);
4090 if (position == NULL) {
4091 return -EINVAL;
4092 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004093 lock_input_stream(in);
4094 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
4095 in->pcm == NULL) {
4096 ret = -ENOSYS;
4097 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004098 }
4099 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004100 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004101 if (ret < 0) {
4102 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004103 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004104 }
Andy Hungfc044e12017-03-20 09:24:22 -07004105 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004106exit:
4107 pthread_mutex_unlock(&in->lock);
4108 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004109}
4110
jiabin8962a4d2018-03-19 18:21:24 -07004111static int in_get_active_microphones(const struct audio_stream_in *stream,
4112 struct audio_microphone_characteristic_t *mic_array,
4113 size_t *mic_count) {
4114 struct stream_in *in = (struct stream_in *)stream;
4115 struct audio_device *adev = in->dev;
4116 ALOGVV("%s", __func__);
4117
4118 lock_input_stream(in);
4119 pthread_mutex_lock(&adev->lock);
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004120 int ret = platform_get_active_microphones(adev->platform,
jiabin8962a4d2018-03-19 18:21:24 -07004121 audio_channel_count_from_in_mask(in->channel_mask),
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004122 in->usecase, mic_array, mic_count);
jiabin8962a4d2018-03-19 18:21:24 -07004123 pthread_mutex_unlock(&adev->lock);
4124 pthread_mutex_unlock(&in->lock);
4125
4126 return ret;
4127}
4128
4129static int adev_get_microphones(const struct audio_hw_device *dev,
4130 struct audio_microphone_characteristic_t *mic_array,
4131 size_t *mic_count) {
4132 struct audio_device *adev = (struct audio_device *)dev;
4133 ALOGVV("%s", __func__);
4134
4135 pthread_mutex_lock(&adev->lock);
4136 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
4137 pthread_mutex_unlock(&adev->lock);
4138
4139 return ret;
4140}
Eric Laurent0e46adf2016-12-16 12:49:24 -08004141
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004142static int adev_open_output_stream(struct audio_hw_device *dev,
4143 audio_io_handle_t handle,
4144 audio_devices_t devices,
4145 audio_output_flags_t flags,
4146 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07004147 struct audio_stream_out **stream_out,
4148 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004149{
4150 struct audio_device *adev = (struct audio_device *)dev;
4151 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004152 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004153 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
4154 bool is_usb_dev = audio_is_usb_out_device(devices) &&
4155 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004156
Andy Hungd9653bd2017-08-01 19:31:39 -07004157 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
4158 return -ENOSYS;
4159 }
4160
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004161 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
4162 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004163 *stream_out = NULL;
4164 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4165
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004166 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
4167
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004168 if (devices == AUDIO_DEVICE_NONE)
4169 devices = AUDIO_DEVICE_OUT_SPEAKER;
4170
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004171 out->flags = flags;
4172 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004173 out->dev = adev;
Eric Laurentc4aef752013-09-12 17:45:53 -07004174 out->handle = handle;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004175 out->a2dp_compress_mute = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004176
4177 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004178 if ((is_hdmi || is_usb_dev) &&
4179 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
4180 (flags == AUDIO_OUTPUT_FLAG_NONE ||
4181 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Eric Laurentab805ee2018-03-30 12:20:38 -07004182 audio_format_t req_format = config->format;
4183 audio_channel_mask_t req_channel_mask = config->channel_mask;
4184 uint32_t req_sample_rate = config->sample_rate;
4185
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004186 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004187 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004188 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004189 if (config->sample_rate == 0)
4190 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Eric Laurentab805ee2018-03-30 12:20:38 -07004191 if (config->channel_mask == AUDIO_CHANNEL_NONE)
Haynes Mathew George569b7482017-05-08 14:44:27 -07004192 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
4193 if (config->format == AUDIO_FORMAT_DEFAULT)
4194 config->format = AUDIO_FORMAT_PCM_16_BIT;
4195 } else if (is_usb_dev) {
4196 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
4197 &config->format,
4198 &out->supported_formats[0],
4199 MAX_SUPPORTED_FORMATS,
4200 &config->channel_mask,
4201 &out->supported_channel_masks[0],
4202 MAX_SUPPORTED_CHANNEL_MASKS,
4203 &config->sample_rate,
4204 &out->supported_sample_rates[0],
4205 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004206 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004207 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004208 pthread_mutex_unlock(&adev->lock);
Eric Laurentab805ee2018-03-30 12:20:38 -07004209 if (ret != 0) {
4210 // For MMAP NO IRQ, allow conversions in ADSP
4211 if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
4212 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004213
Eric Laurentab805ee2018-03-30 12:20:38 -07004214 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
4215 config->sample_rate = req_sample_rate;
4216 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
4217 config->channel_mask = req_channel_mask;
4218 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
4219 config->format = req_format;
4220 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004221
Haynes Mathew George569b7482017-05-08 14:44:27 -07004222 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004223 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004224 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004225 if (is_hdmi) {
4226 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4227 out->config = pcm_config_hdmi_multi;
4228 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
4229 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4230 out->config = pcm_config_mmap_playback;
4231 out->stream.start = out_start;
4232 out->stream.stop = out_stop;
4233 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4234 out->stream.get_mmap_position = out_get_mmap_position;
4235 } else {
4236 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4237 out->config = pcm_config_hifi;
4238 }
4239
4240 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004241 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004242 if (is_hdmi) {
4243 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
4244 audio_bytes_per_sample(out->format));
4245 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004246 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004247 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07004248 pthread_mutex_lock(&adev->lock);
4249 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4250 pthread_mutex_unlock(&adev->lock);
4251
4252 // reject offload during card offline to allow
4253 // fallback to s/w paths
4254 if (offline) {
4255 ret = -ENODEV;
4256 goto error_open;
4257 }
4258
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004259 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4260 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4261 ALOGE("%s: Unsupported Offload information", __func__);
4262 ret = -EINVAL;
4263 goto error_open;
4264 }
4265 if (!is_supported_format(config->offload_info.format)) {
4266 ALOGE("%s: Unsupported audio format", __func__);
4267 ret = -EINVAL;
4268 goto error_open;
4269 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004270 out->sample_rate = config->offload_info.sample_rate;
4271 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
4272 out->channel_mask = config->offload_info.channel_mask;
4273 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
4274 out->channel_mask = config->channel_mask;
4275 else
4276 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4277
4278 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004279
4280 out->compr_config.codec = (struct snd_codec *)
4281 calloc(1, sizeof(struct snd_codec));
4282
4283 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004284
4285 out->stream.set_callback = out_set_callback;
4286 out->stream.pause = out_pause;
4287 out->stream.resume = out_resume;
4288 out->stream.drain = out_drain;
4289 out->stream.flush = out_flush;
4290
4291 out->compr_config.codec->id =
4292 get_snd_codec_id(config->offload_info.format);
4293 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
4294 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004295 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004296 out->compr_config.codec->bit_rate =
4297 config->offload_info.bit_rate;
4298 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004299 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004300 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
4301
4302 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4303 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004304
4305 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004306 create_offload_callback_thread(out);
4307 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4308 __func__, config->offload_info.version,
4309 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02004310 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4311 switch (config->sample_rate) {
4312 case 0:
4313 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4314 break;
4315 case 8000:
4316 case 16000:
4317 case 48000:
4318 out->sample_rate = config->sample_rate;
4319 break;
4320 default:
4321 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
4322 config->sample_rate);
4323 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4324 ret = -EINVAL;
4325 goto error_open;
4326 }
4327 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4328 switch (config->channel_mask) {
4329 case AUDIO_CHANNEL_NONE:
4330 case AUDIO_CHANNEL_OUT_STEREO:
4331 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4332 break;
4333 default:
4334 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
4335 config->channel_mask);
4336 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4337 ret = -EINVAL;
4338 goto error_open;
4339 }
4340 switch (config->format) {
4341 case AUDIO_FORMAT_DEFAULT:
4342 case AUDIO_FORMAT_PCM_16_BIT:
4343 out->format = AUDIO_FORMAT_PCM_16_BIT;
4344 break;
4345 default:
4346 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
4347 config->format);
4348 config->format = AUDIO_FORMAT_PCM_16_BIT;
4349 ret = -EINVAL;
4350 goto error_open;
4351 }
4352
4353 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004354 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004355 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004356 case 0:
4357 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
4358 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07004359 case 8000:
4360 case 16000:
4361 case 48000:
4362 out->sample_rate = config->sample_rate;
4363 break;
4364 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004365 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
4366 config->sample_rate);
4367 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4368 ret = -EINVAL;
4369 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004370 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004371 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4372 switch (config->channel_mask) {
4373 case AUDIO_CHANNEL_NONE:
4374 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4375 break;
4376 case AUDIO_CHANNEL_OUT_STEREO:
4377 out->channel_mask = config->channel_mask;
4378 break;
4379 default:
4380 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
4381 config->channel_mask);
4382 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4383 ret = -EINVAL;
4384 break;
4385 }
4386 switch (config->format) {
4387 case AUDIO_FORMAT_DEFAULT:
4388 out->format = AUDIO_FORMAT_PCM_16_BIT;
4389 break;
4390 case AUDIO_FORMAT_PCM_16_BIT:
4391 out->format = config->format;
4392 break;
4393 default:
4394 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
4395 config->format);
4396 config->format = AUDIO_FORMAT_PCM_16_BIT;
4397 ret = -EINVAL;
4398 break;
4399 }
4400 if (ret != 0)
4401 goto error_open;
4402
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004403 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4404 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004405 out->config.rate = out->sample_rate;
4406 out->config.channels =
4407 audio_channel_count_from_out_mask(out->channel_mask);
4408 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004409 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004410 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
4411 switch (config->sample_rate) {
4412 case 0:
4413 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4414 break;
4415 case 8000:
4416 case 16000:
4417 case 32000:
4418 case 48000:
4419 out->sample_rate = config->sample_rate;
4420 break;
4421 default:
4422 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
4423 config->sample_rate);
4424 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4425 ret = -EINVAL;
4426 break;
4427 }
Eric Laurentad2dde92017-09-20 18:27:31 -07004428 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004429 switch (config->channel_mask) {
4430 case AUDIO_CHANNEL_NONE:
4431 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4432 break;
4433 case AUDIO_CHANNEL_OUT_STEREO:
4434 out->channel_mask = config->channel_mask;
4435 break;
4436 default:
4437 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
4438 config->channel_mask);
4439 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4440 ret = -EINVAL;
4441 break;
4442 }
4443 switch (config->format) {
4444 case AUDIO_FORMAT_DEFAULT:
4445 out->format = AUDIO_FORMAT_PCM_16_BIT;
4446 break;
4447 case AUDIO_FORMAT_PCM_16_BIT:
4448 out->format = config->format;
4449 break;
4450 default:
4451 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
4452 config->format);
4453 config->format = AUDIO_FORMAT_PCM_16_BIT;
4454 ret = -EINVAL;
4455 break;
4456 }
4457 if (ret != 0)
4458 goto error_open;
4459
vivek mehtaa68fea62017-06-08 19:04:02 -07004460 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07004461 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4462 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004463 out->config.rate = out->sample_rate;
4464 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07004465 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004466 out->sample_rate,
4467 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07004468 out->config.channels,
4469 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004470 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07004471 out->config.period_size = buffer_size / frame_size;
4472 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
4473 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004474 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004475 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07004476 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4477 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004478 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07004479 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
4480 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004481 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07004482 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004483 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004484 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004485 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004486 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4487 out->config = pcm_config_mmap_playback;
4488 out->stream.start = out_start;
4489 out->stream.stop = out_stop;
4490 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4491 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004492 } else {
4493 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4494 out->config = pcm_config_low_latency;
4495 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004496
4497 if (config->sample_rate == 0) {
4498 out->sample_rate = out->config.rate;
4499 } else {
4500 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004501 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004502 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
4503 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
4504 } else {
4505 out->channel_mask = config->channel_mask;
4506 }
4507 if (config->format == AUDIO_FORMAT_DEFAULT)
4508 out->format = audio_format_from_pcm_format(out->config.format);
4509 else if (!audio_is_linear_pcm(config->format)) {
4510 config->format = AUDIO_FORMAT_PCM_16_BIT;
4511 ret = -EINVAL;
4512 goto error_open;
4513 } else {
4514 out->format = config->format;
4515 }
4516
4517 out->config.rate = out->sample_rate;
4518 out->config.channels =
4519 audio_channel_count_from_out_mask(out->channel_mask);
4520 if (out->format != audio_format_from_pcm_format(out->config.format)) {
4521 out->config.format = pcm_format_from_audio_format(out->format);
4522 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004523 }
Kevin Rocard50eff892017-05-02 16:52:05 -07004524
4525 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
4526 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004527 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004528 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
4529 __func__, config->sample_rate, config->format, config->channel_mask);
4530 config->sample_rate = out->sample_rate;
4531 config->format = out->format;
4532 config->channel_mask = out->channel_mask;
4533 ret = -EINVAL;
4534 goto error_open;
4535 }
4536
Andy Hung6fcba9c2014-03-18 11:53:32 -07004537 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
4538 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004539
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004540 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004541 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004542 adev->primary_output = out;
4543 else {
4544 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004545 ret = -EEXIST;
4546 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004547 }
4548 }
4549
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004550 /* Check if this usecase is already existing */
4551 pthread_mutex_lock(&adev->lock);
4552 if (get_usecase_from_list(adev, out->usecase) != NULL) {
4553 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004554 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004555 ret = -EEXIST;
4556 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004557 }
4558 pthread_mutex_unlock(&adev->lock);
4559
4560 out->stream.common.get_sample_rate = out_get_sample_rate;
4561 out->stream.common.set_sample_rate = out_set_sample_rate;
4562 out->stream.common.get_buffer_size = out_get_buffer_size;
4563 out->stream.common.get_channels = out_get_channels;
4564 out->stream.common.get_format = out_get_format;
4565 out->stream.common.set_format = out_set_format;
4566 out->stream.common.standby = out_standby;
4567 out->stream.common.dump = out_dump;
4568 out->stream.common.set_parameters = out_set_parameters;
4569 out->stream.common.get_parameters = out_get_parameters;
4570 out->stream.common.add_audio_effect = out_add_audio_effect;
4571 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4572 out->stream.get_latency = out_get_latency;
4573 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004574#ifdef NO_AUDIO_OUT
4575 out->stream.write = out_write_for_no_output;
4576#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004577 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004578#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004579 out->stream.get_render_position = out_get_render_position;
4580 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004581 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004582
Eric Laurent0e46adf2016-12-16 12:49:24 -08004583 if (out->realtime)
4584 out->af_period_multiplier = af_period_multiplier;
4585 else
4586 out->af_period_multiplier = 1;
4587
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004588 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004589 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004590 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004591
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004592 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004593 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004594 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4595
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004596 config->format = out->stream.common.get_format(&out->stream.common);
4597 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4598 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4599
Kevin Rocarda325aa22018-04-03 09:15:52 -07004600 register_format(out->format, out->supported_formats);
4601 register_channel_mask(out->channel_mask, out->supported_channel_masks);
4602 register_sample_rate(out->sample_rate, out->supported_sample_rates);
4603
Andy Hunga452b0a2017-03-15 14:51:15 -07004604 out->error_log = error_log_create(
4605 ERROR_LOG_ENTRIES,
4606 1000000000 /* aggregate consecutive identical errors within one second in ns */);
4607
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004608 /*
4609 By locking output stream before registering, we allow the callback
4610 to update stream's state only after stream's initial state is set to
4611 adev state.
4612 */
4613 lock_output_stream(out);
4614 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4615 pthread_mutex_lock(&adev->lock);
4616 out->card_status = adev->card_status;
4617 pthread_mutex_unlock(&adev->lock);
4618 pthread_mutex_unlock(&out->lock);
4619
vivek mehta4a824772017-06-08 19:05:49 -07004620 stream_app_type_cfg_init(&out->app_type_cfg);
4621
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004622 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004623
Eric Laurent994a6932013-07-17 11:51:42 -07004624 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004625 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004626
4627error_open:
4628 free(out);
4629 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07004630 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004631 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004632}
4633
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004634static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004635 struct audio_stream_out *stream)
4636{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004637 struct stream_out *out = (struct stream_out *)stream;
4638 struct audio_device *adev = out->dev;
4639
Eric Laurent994a6932013-07-17 11:51:42 -07004640 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004641
4642 // must deregister from sndmonitor first to prevent races
4643 // between the callback and close_stream
4644 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004645 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004646 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
4647 destroy_offload_callback_thread(out);
4648
4649 if (out->compr_config.codec != NULL)
4650 free(out->compr_config.codec);
4651 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004652
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004653 out->a2dp_compress_mute = false;
4654
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004655 if (adev->voice_tx_output == out)
4656 adev->voice_tx_output = NULL;
4657
Andy Hunga452b0a2017-03-15 14:51:15 -07004658 error_log_destroy(out->error_log);
4659 out->error_log = NULL;
4660
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004661 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004662 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004663 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004664 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004665 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004666}
4667
4668static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4669{
4670 struct audio_device *adev = (struct audio_device *)dev;
4671 struct str_parms *parms;
4672 char *str;
4673 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004674 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004675 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07004676 int status = 0;
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004677 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004678
Joe Onorato188b6222016-03-01 11:02:27 -08004679 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004680
4681 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004682
4683 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004684 status = voice_set_parameters(adev, parms);
4685 if (status != 0) {
4686 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004687 }
4688
4689 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4690 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07004691 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004692 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4693 adev->bluetooth_nrec = true;
4694 else
4695 adev->bluetooth_nrec = false;
4696 }
4697
4698 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4699 if (ret >= 0) {
4700 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4701 adev->screen_off = false;
4702 else
4703 adev->screen_off = true;
4704 }
4705
jasmine cha270b7762018-03-30 15:41:33 +08004706#ifndef MAXXAUDIO_QDSP_ENABLED
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004707 ret = str_parms_get_int(parms, "rotation", &val);
4708 if (ret >= 0) {
4709 bool reverse_speakers = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004710 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004711 // FIXME: note that the code below assumes that the speakers are in the correct placement
4712 // relative to the user when the device is rotated 90deg from its default rotation. This
4713 // assumption is device-specific, not platform-specific like this code.
4714 case 270:
4715 reverse_speakers = true;
4716 break;
4717 case 0:
4718 case 90:
4719 case 180:
4720 break;
4721 default:
4722 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07004723 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004724 }
Eric Laurent03f09432014-03-25 18:09:11 -07004725 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004726 // check and set swap
4727 // - check if orientation changed and speaker active
4728 // - set rotation and cache the rotation value
4729 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004730 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004731 }
jasmine cha270b7762018-03-30 15:41:33 +08004732#endif
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004733
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004734 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4735 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004736 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004737 }
4738
David Linee3fe402017-03-13 10:00:42 -07004739 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4740 if (ret >= 0) {
4741 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004742 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004743 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4744 if (ret >= 0) {
4745 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004746 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004747 }
Eric Laurent99dab492017-06-17 15:19:08 -07004748 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004749 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4750 if (ret >= 0) {
4751 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004752 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004753 }
4754 }
4755 }
4756
4757 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4758 if (ret >= 0) {
4759 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004760 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004761 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4762 if (ret >= 0) {
4763 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004764 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004765 }
Eric Laurent99dab492017-06-17 15:19:08 -07004766 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004767 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4768 if (ret >= 0) {
4769 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004770 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004771 }
4772 }
4773 }
4774
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004775 audio_extn_hfp_set_parameters(adev, parms);
jasmine cha270b7762018-03-30 15:41:33 +08004776 audio_extn_ma_set_parameters(adev, parms);
4777
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004778 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
4779 if (status >= 0 && a2dp_reconfig) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004780 struct audio_usecase *usecase;
4781 struct listnode *node;
4782 list_for_each(node, &adev->usecase_list) {
4783 usecase = node_to_item(node, struct audio_usecase, list);
4784 if ((usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004785 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004786 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
4787
4788 pthread_mutex_unlock(&adev->lock);
4789 lock_output_stream(usecase->stream.out);
4790 pthread_mutex_lock(&adev->lock);
4791 audio_extn_a2dp_set_handoff_mode(true);
4792 // force device switch to reconfigure encoder
4793 select_devices(adev, usecase->id);
4794 audio_extn_a2dp_set_handoff_mode(false);
4795 pthread_mutex_unlock(&usecase->stream.out->lock);
4796 break;
4797 }
4798 }
4799 }
4800
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004801done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004802 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004803 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004804 ALOGV("%s: exit with code(%d)", __func__, status);
4805 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004806}
4807
4808static char* adev_get_parameters(const struct audio_hw_device *dev,
4809 const char *keys)
4810{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004811 struct audio_device *adev = (struct audio_device *)dev;
4812 struct str_parms *reply = str_parms_create();
4813 struct str_parms *query = str_parms_create_str(keys);
4814 char *str;
4815
4816 pthread_mutex_lock(&adev->lock);
4817
4818 voice_get_parameters(adev, query, reply);
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004819 audio_extn_a2dp_get_parameters(query, reply);
4820
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004821 str = str_parms_to_str(reply);
4822 str_parms_destroy(query);
4823 str_parms_destroy(reply);
4824
4825 pthread_mutex_unlock(&adev->lock);
4826 ALOGV("%s: exit: returns - %s", __func__, str);
4827 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004828}
4829
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004830static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004831{
4832 return 0;
4833}
4834
Haynes Mathew George5191a852013-09-11 14:19:36 -07004835static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4836{
4837 int ret;
4838 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004839
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004840 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4841
Haynes Mathew George5191a852013-09-11 14:19:36 -07004842 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004843 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004844 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004845
Haynes Mathew George5191a852013-09-11 14:19:36 -07004846 return ret;
4847}
4848
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004849static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004850{
4851 return -ENOSYS;
4852}
4853
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004854static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4855 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004856{
4857 return -ENOSYS;
4858}
4859
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004860static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004861{
4862 return -ENOSYS;
4863}
4864
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004865static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004866{
4867 return -ENOSYS;
4868}
4869
4870static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4871{
4872 struct audio_device *adev = (struct audio_device *)dev;
4873
4874 pthread_mutex_lock(&adev->lock);
4875 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004876 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004877 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004878 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4879 voice_is_in_call(adev)) {
4880 voice_stop_call(adev);
4881 adev->current_call_output = NULL;
4882 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004883 }
4884 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004885
4886 audio_extn_extspk_set_mode(adev->extspk, mode);
4887
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004888 return 0;
4889}
4890
4891static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4892{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004893 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004894 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004895
Eric Laurent2bafff12016-03-17 12:17:23 -07004896 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004897 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004898 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4899 ret = audio_extn_hfp_set_mic_mute(adev, state);
4900 } else {
4901 ret = voice_set_mic_mute(adev, state);
4902 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004903 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004904 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004905
4906 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004907}
4908
4909static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4910{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004911 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004912 return 0;
4913}
4914
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004915static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004916 const struct audio_config *config)
4917{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004918 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004919
Eric Laurent74b55762017-07-09 17:04:53 -07004920 /* Don't know if USB HIFI in this context so use true to be conservative */
4921 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4922 true /*is_usb_hifi */) != 0)
4923 return 0;
4924
vivek mehtaa68fea62017-06-08 19:04:02 -07004925 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4926 config->sample_rate, config->format,
4927 channel_count,
4928 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004929}
4930
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004931static bool adev_input_allow_hifi_record(struct audio_device *adev,
4932 audio_devices_t devices,
4933 audio_input_flags_t flags,
4934 audio_source_t source) {
4935 const bool allowed = true;
4936
4937 if (!audio_is_usb_in_device(devices))
4938 return !allowed;
4939
4940 switch (flags) {
4941 case AUDIO_INPUT_FLAG_NONE:
4942 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4943 break;
4944 default:
4945 return !allowed;
4946 }
4947
4948 switch (source) {
4949 case AUDIO_SOURCE_DEFAULT:
4950 case AUDIO_SOURCE_MIC:
4951 case AUDIO_SOURCE_UNPROCESSED:
4952 break;
4953 default:
4954 return !allowed;
4955 }
4956
4957 switch (adev->mode) {
4958 case 0:
4959 break;
4960 default:
4961 return !allowed;
4962 }
4963
4964 return allowed;
4965}
4966
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004967static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004968 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004969 audio_devices_t devices,
4970 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004971 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004972 audio_input_flags_t flags,
4973 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004974 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004975{
4976 struct audio_device *adev = (struct audio_device *)dev;
4977 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004978 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004979 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004980 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004981 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004982 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4983 devices,
4984 flags,
4985 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004986 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004987 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004988
Andy Hungd9653bd2017-08-01 19:31:39 -07004989 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
4990 return -ENOSYS;
4991 }
4992
Eric Laurent74b55762017-07-09 17:04:53 -07004993 if (!(is_usb_dev && may_use_hifi_record)) {
4994 if (config->sample_rate == 0)
4995 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4996 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4997 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4998 if (config->format == AUDIO_FORMAT_DEFAULT)
4999 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005000
Eric Laurent74b55762017-07-09 17:04:53 -07005001 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
5002
5003 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
5004 return -EINVAL;
5005 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005006
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005007 if (audio_extn_tfa_98xx_is_supported() &&
5008 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005009 return -EINVAL;
5010
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005011 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
5012
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005013 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005014 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005015
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005016 in->stream.common.get_sample_rate = in_get_sample_rate;
5017 in->stream.common.set_sample_rate = in_set_sample_rate;
5018 in->stream.common.get_buffer_size = in_get_buffer_size;
5019 in->stream.common.get_channels = in_get_channels;
5020 in->stream.common.get_format = in_get_format;
5021 in->stream.common.set_format = in_set_format;
5022 in->stream.common.standby = in_standby;
5023 in->stream.common.dump = in_dump;
5024 in->stream.common.set_parameters = in_set_parameters;
5025 in->stream.common.get_parameters = in_get_parameters;
5026 in->stream.common.add_audio_effect = in_add_audio_effect;
5027 in->stream.common.remove_audio_effect = in_remove_audio_effect;
5028 in->stream.set_gain = in_set_gain;
5029 in->stream.read = in_read;
5030 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08005031 in->stream.get_capture_position = in_get_capture_position;
jiabin8962a4d2018-03-19 18:21:24 -07005032 in->stream.get_active_microphones = in_get_active_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005033
5034 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005035 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005036 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005037 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005038 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005039 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005040
Arun Mirpuriba2749a2018-04-17 14:32:24 -07005041 ALOGV("%s: source = %d, config->channel_mask = %d", __func__, source, config->channel_mask);
5042 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
5043 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
5044 /* Force channel config requested to mono if incall
5045 record is being requested for only uplink/downlink */
5046 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
5047 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5048 ret = -EINVAL;
5049 goto err_open;
5050 }
5051 }
5052
Haynes Mathew George569b7482017-05-08 14:44:27 -07005053 if (is_usb_dev && may_use_hifi_record) {
5054 /* HiFi record selects an appropriate format, channel, rate combo
5055 depending on sink capabilities*/
5056 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
5057 &config->format,
5058 &in->supported_formats[0],
5059 MAX_SUPPORTED_FORMATS,
5060 &config->channel_mask,
5061 &in->supported_channel_masks[0],
5062 MAX_SUPPORTED_CHANNEL_MASKS,
5063 &config->sample_rate,
5064 &in->supported_sample_rates[0],
5065 MAX_SUPPORTED_SAMPLE_RATES);
5066 if (ret != 0) {
5067 ret = -EINVAL;
5068 goto err_open;
5069 }
Eric Laurent74b55762017-07-09 17:04:53 -07005070 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005071 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07005072 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07005073 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
5074 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
5075 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5076 bool ret_error = false;
5077 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5078 from HAL is 8_24
5079 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5080 8_24 return error indicating supported format is 8_24
5081 *> In case of any other source requesting 24 bit or float return error
5082 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07005083
vivek mehta57ff9b52016-04-28 14:13:08 -07005084 on error flinger will retry with supported format passed
5085 */
5086 if (source != AUDIO_SOURCE_UNPROCESSED) {
5087 config->format = AUDIO_FORMAT_PCM_16_BIT;
5088 ret_error = true;
5089 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
5090 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
5091 ret_error = true;
5092 }
5093
5094 if (ret_error) {
5095 ret = -EINVAL;
5096 goto err_open;
5097 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005098 }
5099
vivek mehta57ff9b52016-04-28 14:13:08 -07005100 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07005101 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07005102
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005103 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005104 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
5105 if (config->sample_rate == 0)
5106 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5107 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5108 config->sample_rate != 8000) {
5109 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5110 ret = -EINVAL;
5111 goto err_open;
5112 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005113
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005114 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5115 config->format = AUDIO_FORMAT_PCM_16_BIT;
5116 ret = -EINVAL;
5117 goto err_open;
5118 }
5119
5120 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5121 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07005122 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005123 } else if (is_usb_dev && may_use_hifi_record) {
5124 in->usecase = USECASE_AUDIO_RECORD_HIFI;
5125 in->config = pcm_config_audio_capture;
5126 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005127 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5128 config->sample_rate,
5129 config->format,
5130 channel_count,
5131 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005132 in->config.period_size = buffer_size / frame_size;
5133 in->config.rate = config->sample_rate;
5134 in->af_period_multiplier = 1;
5135 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005136 } else {
5137 in->usecase = USECASE_AUDIO_RECORD;
5138 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08005139 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005140 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07005141#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005142 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07005143#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08005144 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005145 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08005146 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005147 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005148 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5149 config->sample_rate,
5150 config->format,
5151 channel_count,
5152 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005153 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005154 in->config.rate = config->sample_rate;
5155 in->af_period_multiplier = 1;
5156 } else {
5157 // period size is left untouched for rt mode playback
5158 in->config = pcm_config_audio_capture_rt;
5159 in->af_period_multiplier = af_period_multiplier;
5160 }
5161 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
5162 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005163 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08005164 in->usecase = USECASE_AUDIO_RECORD_MMAP;
5165 in->config = pcm_config_mmap_capture;
5166 in->stream.start = in_start;
5167 in->stream.stop = in_stop;
5168 in->stream.create_mmap_buffer = in_create_mmap_buffer;
5169 in->stream.get_mmap_position = in_get_mmap_position;
5170 in->af_period_multiplier = 1;
5171 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07005172 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07005173 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07005174 (config->sample_rate == 8000 ||
5175 config->sample_rate == 16000 ||
5176 config->sample_rate == 32000 ||
5177 config->sample_rate == 48000) &&
5178 channel_count == 1) {
5179 in->usecase = USECASE_AUDIO_RECORD_VOIP;
5180 in->config = pcm_config_audio_capture;
5181 frame_size = audio_stream_in_frame_size(&in->stream);
5182 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
5183 config->sample_rate,
5184 config->format,
5185 channel_count, false /*is_low_latency*/);
5186 in->config.period_size = buffer_size / frame_size;
5187 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
5188 in->config.rate = config->sample_rate;
5189 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005190 } else {
5191 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005192 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005193 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5194 config->sample_rate,
5195 config->format,
5196 channel_count,
5197 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005198 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005199 in->config.rate = config->sample_rate;
5200 in->af_period_multiplier = 1;
5201 }
5202 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
5203 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005204 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08005205
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005206 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07005207 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005208
Kevin Rocarda325aa22018-04-03 09:15:52 -07005209
5210 register_format(in->format, in->supported_formats);
5211 register_channel_mask(in->channel_mask, in->supported_channel_masks);
5212 register_sample_rate(in->sample_rate, in->supported_sample_rates);
5213
Andy Hungd13f0d32017-06-12 13:58:37 -07005214 in->error_log = error_log_create(
5215 ERROR_LOG_ENTRIES,
5216 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
5217
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005218 /* This stream could be for sound trigger lab,
5219 get sound trigger pcm if present */
5220 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005221
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005222 lock_input_stream(in);
5223 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5224 pthread_mutex_lock(&adev->lock);
5225 in->card_status = adev->card_status;
5226 pthread_mutex_unlock(&adev->lock);
5227 pthread_mutex_unlock(&in->lock);
5228
vivek mehta4a824772017-06-08 19:05:49 -07005229 stream_app_type_cfg_init(&in->app_type_cfg);
5230
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005231 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005232 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005233 return 0;
5234
5235err_open:
5236 free(in);
5237 *stream_in = NULL;
5238 return ret;
5239}
5240
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005241static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005242 struct audio_stream_in *stream)
5243{
Andy Hungd13f0d32017-06-12 13:58:37 -07005244 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005245 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005246
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005247 // must deregister from sndmonitor first to prevent races
5248 // between the callback and close_stream
5249 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005250 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07005251
5252 error_log_destroy(in->error_log);
5253 in->error_log = NULL;
5254
Andy Hung0dbb52b2017-08-09 13:51:38 -07005255 pthread_mutex_destroy(&in->pre_lock);
5256 pthread_mutex_destroy(&in->lock);
5257
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005258 free(stream);
5259
5260 return;
5261}
5262
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005263static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005264{
5265 return 0;
5266}
5267
Andy Hung31aca912014-03-20 17:14:59 -07005268/* verifies input and output devices and their capabilities.
5269 *
5270 * This verification is required when enabling extended bit-depth or
5271 * sampling rates, as not all qcom products support it.
5272 *
5273 * Suitable for calling only on initialization such as adev_open().
5274 * It fills the audio_device use_case_table[] array.
5275 *
5276 * Has a side-effect that it needs to configure audio routing / devices
5277 * in order to power up the devices and read the device parameters.
5278 * It does not acquire any hw device lock. Should restore the devices
5279 * back to "normal state" upon completion.
5280 */
5281static int adev_verify_devices(struct audio_device *adev)
5282{
5283 /* enumeration is a bit difficult because one really wants to pull
5284 * the use_case, device id, etc from the hidden pcm_device_table[].
5285 * In this case there are the following use cases and device ids.
5286 *
5287 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
5288 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005289 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07005290 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
5291 * [USECASE_AUDIO_RECORD] = {0, 0},
5292 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
5293 * [USECASE_VOICE_CALL] = {2, 2},
5294 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005295 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07005296 * USECASE_VOICE_CALL omitted, but possible for either input or output.
5297 */
5298
5299 /* should be the usecases enabled in adev_open_input_stream() */
5300 static const int test_in_usecases[] = {
5301 USECASE_AUDIO_RECORD,
5302 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
5303 };
5304 /* should be the usecases enabled in adev_open_output_stream()*/
5305 static const int test_out_usecases[] = {
5306 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
5307 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
5308 };
5309 static const usecase_type_t usecase_type_by_dir[] = {
5310 PCM_PLAYBACK,
5311 PCM_CAPTURE,
5312 };
5313 static const unsigned flags_by_dir[] = {
5314 PCM_OUT,
5315 PCM_IN,
5316 };
5317
5318 size_t i;
5319 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005320 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07005321 char info[512]; /* for possible debug info */
5322
5323 for (dir = 0; dir < 2; ++dir) {
5324 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
5325 const unsigned flags_dir = flags_by_dir[dir];
5326 const size_t testsize =
5327 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
5328 const int *testcases =
5329 dir ? test_in_usecases : test_out_usecases;
5330 const audio_devices_t audio_device =
5331 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
5332
5333 for (i = 0; i < testsize; ++i) {
5334 const audio_usecase_t audio_usecase = testcases[i];
5335 int device_id;
5336 snd_device_t snd_device;
5337 struct pcm_params **pparams;
5338 struct stream_out out;
5339 struct stream_in in;
5340 struct audio_usecase uc_info;
5341 int retval;
5342
5343 pparams = &adev->use_case_table[audio_usecase];
5344 pcm_params_free(*pparams); /* can accept null input */
5345 *pparams = NULL;
5346
5347 /* find the device ID for the use case (signed, for error) */
5348 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
5349 if (device_id < 0)
5350 continue;
5351
5352 /* prepare structures for device probing */
5353 memset(&uc_info, 0, sizeof(uc_info));
5354 uc_info.id = audio_usecase;
5355 uc_info.type = usecase_type;
5356 if (dir) {
5357 adev->active_input = &in;
5358 memset(&in, 0, sizeof(in));
5359 in.device = audio_device;
5360 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
5361 uc_info.stream.in = &in;
5362 } else {
5363 adev->active_input = NULL;
5364 }
5365 memset(&out, 0, sizeof(out));
5366 out.devices = audio_device; /* only field needed in select_devices */
5367 uc_info.stream.out = &out;
5368 uc_info.devices = audio_device;
5369 uc_info.in_snd_device = SND_DEVICE_NONE;
5370 uc_info.out_snd_device = SND_DEVICE_NONE;
5371 list_add_tail(&adev->usecase_list, &uc_info.list);
5372
5373 /* select device - similar to start_(in/out)put_stream() */
5374 retval = select_devices(adev, audio_usecase);
5375 if (retval >= 0) {
5376 *pparams = pcm_params_get(card_id, device_id, flags_dir);
5377#if LOG_NDEBUG == 0
5378 if (*pparams) {
5379 ALOGV("%s: (%s) card %d device %d", __func__,
5380 dir ? "input" : "output", card_id, device_id);
5381 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07005382 } else {
5383 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
5384 }
5385#endif
5386 }
5387
5388 /* deselect device - similar to stop_(in/out)put_stream() */
5389 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07005390 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07005391 /* 2. Disable the rx device */
5392 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07005393 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07005394 list_remove(&uc_info.list);
5395 }
5396 }
5397 adev->active_input = NULL; /* restore adev state */
5398 return 0;
5399}
5400
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005401static int adev_close(hw_device_t *device)
5402{
Andy Hung31aca912014-03-20 17:14:59 -07005403 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005404 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005405
5406 if (!adev)
5407 return 0;
5408
5409 pthread_mutex_lock(&adev_init_lock);
5410
5411 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005412 audio_extn_snd_mon_unregister_listener(adev);
5413 audio_extn_tfa_98xx_deinit();
jasmine cha270b7762018-03-30 15:41:33 +08005414 audio_extn_ma_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005415 audio_route_free(adev->audio_route);
5416 free(adev->snd_dev_ref_cnt);
5417 platform_deinit(adev->platform);
5418 audio_extn_extspk_deinit(adev->extspk);
5419 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005420 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005421 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
5422 pcm_params_free(adev->use_case_table[i]);
5423 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005424 if (adev->adm_deinit)
5425 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005426 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005427 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07005428 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07005429
5430 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005431
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005432 return 0;
5433}
5434
Glenn Kasten4f993392014-05-14 07:30:48 -07005435/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5436 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5437 * just that it _might_ work.
5438 */
5439static int period_size_is_plausible_for_low_latency(int period_size)
5440{
5441 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005442 case 48:
5443 case 96:
5444 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07005445 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005446 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07005447 case 240:
5448 case 320:
5449 case 480:
5450 return 1;
5451 default:
5452 return 0;
5453 }
5454}
5455
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005456static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
5457{
5458 int card;
5459 card_status_t status;
5460
5461 if (!parms)
5462 return;
5463
5464 if (parse_snd_card_status(parms, &card, &status) < 0)
5465 return;
5466
5467 pthread_mutex_lock(&adev->lock);
5468 bool valid_cb = (card == adev->snd_card);
5469 if (valid_cb) {
5470 if (adev->card_status != status) {
5471 adev->card_status = status;
5472 platform_snd_card_update(adev->platform, status);
5473 }
5474 }
5475 pthread_mutex_unlock(&adev->lock);
5476 return;
5477}
5478
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005479/* out and adev lock held */
5480static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
5481{
5482 struct audio_usecase *uc_info;
5483 float left_p;
5484 float right_p;
5485 audio_devices_t devices;
5486
5487 uc_info = get_usecase_from_list(adev, out->usecase);
5488 if (uc_info == NULL) {
5489 ALOGE("%s: Could not find the usecase (%d) in the list",
5490 __func__, out->usecase);
5491 return -EINVAL;
5492 }
5493
5494 ALOGD("%s: enter: usecase(%d: %s)", __func__,
5495 out->usecase, use_case_table[out->usecase]);
5496
5497 if (restore) {
5498 // restore A2DP device for active usecases and unmute if required
5499 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
5500 !is_a2dp_device(uc_info->out_snd_device)) {
5501 ALOGD("%s: restoring A2DP and unmuting stream", __func__);
5502 select_devices(adev, uc_info->id);
5503 pthread_mutex_lock(&out->compr_mute_lock);
5504 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5505 (out->a2dp_compress_mute)) {
5506 out->a2dp_compress_mute = false;
5507 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5508 }
5509 pthread_mutex_unlock(&out->compr_mute_lock);
5510 }
5511 } else {
5512 // mute compress stream if suspended
5513 pthread_mutex_lock(&out->compr_mute_lock);
5514 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5515 (!out->a2dp_compress_mute)) {
5516 if (!out->standby) {
5517 ALOGD("%s: selecting speaker and muting stream", __func__);
5518 devices = out->devices;
5519 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
5520 left_p = out->volume_l;
5521 right_p = out->volume_r;
5522 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5523 compress_pause(out->compr);
5524 set_compr_volume(&out->stream, 0.0f, 0.0f);
5525 out->a2dp_compress_mute = true;
5526 select_devices(adev, out->usecase);
5527 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5528 compress_resume(out->compr);
5529 out->devices = devices;
5530 out->volume_l = left_p;
5531 out->volume_r = right_p;
5532 }
5533 }
5534 pthread_mutex_unlock(&out->compr_mute_lock);
5535 }
5536 ALOGV("%s: exit", __func__);
5537 return 0;
5538}
5539
5540int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
5541{
5542 int ret = 0;
5543
5544 lock_output_stream(out);
5545 pthread_mutex_lock(&adev->lock);
5546
5547 ret = check_a2dp_restore_l(adev, out, restore);
5548
5549 pthread_mutex_unlock(&adev->lock);
5550 pthread_mutex_unlock(&out->lock);
5551 return ret;
5552}
5553
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005554static int adev_open(const hw_module_t *module, const char *name,
5555 hw_device_t **device)
5556{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005557 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005558
Eric Laurent2bafff12016-03-17 12:17:23 -07005559 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005560 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005561 pthread_mutex_lock(&adev_init_lock);
5562 if (audio_device_ref_count != 0) {
5563 *device = &adev->device.common;
5564 audio_device_ref_count++;
5565 ALOGV("%s: returning existing instance of adev", __func__);
5566 ALOGV("%s: exit", __func__);
5567 pthread_mutex_unlock(&adev_init_lock);
5568 return 0;
5569 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005570 adev = calloc(1, sizeof(struct audio_device));
5571
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005572 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5573
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005574 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5575 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5576 adev->device.common.module = (struct hw_module_t *)module;
5577 adev->device.common.close = adev_close;
5578
5579 adev->device.init_check = adev_init_check;
5580 adev->device.set_voice_volume = adev_set_voice_volume;
5581 adev->device.set_master_volume = adev_set_master_volume;
5582 adev->device.get_master_volume = adev_get_master_volume;
5583 adev->device.set_master_mute = adev_set_master_mute;
5584 adev->device.get_master_mute = adev_get_master_mute;
5585 adev->device.set_mode = adev_set_mode;
5586 adev->device.set_mic_mute = adev_set_mic_mute;
5587 adev->device.get_mic_mute = adev_get_mic_mute;
5588 adev->device.set_parameters = adev_set_parameters;
5589 adev->device.get_parameters = adev_get_parameters;
5590 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5591 adev->device.open_output_stream = adev_open_output_stream;
5592 adev->device.close_output_stream = adev_close_output_stream;
5593 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005594
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005595 adev->device.close_input_stream = adev_close_input_stream;
5596 adev->device.dump = adev_dump;
jiabin8962a4d2018-03-19 18:21:24 -07005597 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005598
5599 /* Set the default route before the PCM stream is opened */
5600 pthread_mutex_lock(&adev->lock);
5601 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005602 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005603 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005604 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005605 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005606 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005607 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005608 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005609 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005610 pthread_mutex_unlock(&adev->lock);
5611
5612 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005613 adev->platform = platform_init(adev);
5614 if (!adev->platform) {
5615 free(adev->snd_dev_ref_cnt);
5616 free(adev);
5617 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5618 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005619 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005620 return -EINVAL;
5621 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05005622 adev->extspk = audio_extn_extspk_init(adev);
5623
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005624 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5625 if (adev->visualizer_lib == NULL) {
5626 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5627 } else {
5628 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5629 adev->visualizer_start_output =
Aniket Kumar Lata72a3cea2018-04-06 13:56:37 -07005630 (int (*)(audio_io_handle_t, int, int, int))dlsym(adev->visualizer_lib,
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005631 "visualizer_hal_start_output");
5632 adev->visualizer_stop_output =
5633 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5634 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07005635 }
5636
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005637 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5638 if (adev->offload_effects_lib == NULL) {
5639 ALOGW("%s: DLOPEN failed for %s", __func__,
5640 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5641 } else {
5642 ALOGV("%s: DLOPEN successful for %s", __func__,
5643 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5644 adev->offload_effects_start_output =
5645 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5646 "offload_effects_bundle_hal_start_output");
5647 adev->offload_effects_stop_output =
5648 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5649 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07005650 }
5651
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005652 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5653 if (adev->adm_lib == NULL) {
5654 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5655 } else {
5656 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5657 adev->adm_init = (adm_init_t)
5658 dlsym(adev->adm_lib, "adm_init");
5659 adev->adm_deinit = (adm_deinit_t)
5660 dlsym(adev->adm_lib, "adm_deinit");
5661 adev->adm_register_input_stream = (adm_register_input_stream_t)
5662 dlsym(adev->adm_lib, "adm_register_input_stream");
5663 adev->adm_register_output_stream = (adm_register_output_stream_t)
5664 dlsym(adev->adm_lib, "adm_register_output_stream");
5665 adev->adm_deregister_stream = (adm_deregister_stream_t)
5666 dlsym(adev->adm_lib, "adm_deregister_stream");
5667 adev->adm_request_focus = (adm_request_focus_t)
5668 dlsym(adev->adm_lib, "adm_request_focus");
5669 adev->adm_abandon_focus = (adm_abandon_focus_t)
5670 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08005671 adev->adm_set_config = (adm_set_config_t)
5672 dlsym(adev->adm_lib, "adm_set_config");
5673 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5674 dlsym(adev->adm_lib, "adm_request_focus_v2");
5675 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5676 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5677 adev->adm_on_routing_change = (adm_on_routing_change_t)
5678 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005679 }
5680
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005681 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005682 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005683
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005684 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005685
Andy Hung31aca912014-03-20 17:14:59 -07005686 if (k_enable_extended_precision)
5687 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005688
Glenn Kasten4f993392014-05-14 07:30:48 -07005689 char value[PROPERTY_VALUE_MAX];
5690 int trial;
5691 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5692 trial = atoi(value);
5693 if (period_size_is_plausible_for_low_latency(trial)) {
5694 pcm_config_low_latency.period_size = trial;
5695 pcm_config_low_latency.start_threshold = trial / 4;
5696 pcm_config_low_latency.avail_min = trial / 4;
5697 configured_low_latency_capture_period_size = trial;
5698 }
5699 }
5700 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5701 trial = atoi(value);
5702 if (period_size_is_plausible_for_low_latency(trial)) {
5703 configured_low_latency_capture_period_size = trial;
5704 }
5705 }
5706
Vignesh Kulothunganb6f0a9c2018-03-22 13:50:22 -07005707 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
5708
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005709 // commented as full set of app type cfg is sent from platform
5710 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005711 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005712
5713 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5714 af_period_multiplier = atoi(value);
5715 if (af_period_multiplier < 0) {
5716 af_period_multiplier = 2;
5717 } else if (af_period_multiplier > 4) {
5718 af_period_multiplier = 4;
5719 }
5720 ALOGV("new period_multiplier = %d", af_period_multiplier);
5721 }
5722
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005723 audio_extn_tfa_98xx_init(adev);
jasmine cha270b7762018-03-30 15:41:33 +08005724 audio_extn_ma_init(adev->platform);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005725
vivek mehta1a9b7c02015-06-25 11:49:38 -07005726 pthread_mutex_unlock(&adev_init_lock);
5727
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005728 if (adev->adm_init)
5729 adev->adm_data = adev->adm_init();
5730
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005731 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005732 audio_extn_snd_mon_init();
5733 pthread_mutex_lock(&adev->lock);
5734 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
5735 adev->card_status = CARD_STATUS_ONLINE;
5736 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005737 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005738
Eric Laurent2bafff12016-03-17 12:17:23 -07005739 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005740 return 0;
5741}
5742
5743static struct hw_module_methods_t hal_module_methods = {
5744 .open = adev_open,
5745};
5746
5747struct audio_module HAL_MODULE_INFO_SYM = {
5748 .common = {
5749 .tag = HARDWARE_MODULE_TAG,
5750 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5751 .hal_api_version = HARDWARE_HAL_API_VERSION,
5752 .id = AUDIO_HARDWARE_MODULE_ID,
5753 .name = "QCOM Audio HAL",
5754 .author = "Code Aurora Forum",
5755 .methods = &hal_module_methods,
5756 },
5757};