blob: 7f8c75a47990f4255649efe1c96a031cd3ab8e95 [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,
252 .stop_threshold = INT_MAX,
253 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
254};
255
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700256const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700257 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
258 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800259 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700260 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700261 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700262 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800263 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700264
Eric Laurentb23d5282013-05-14 15:27:20 -0700265 [USECASE_AUDIO_RECORD] = "audio-record",
266 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800267 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George569b7482017-05-08 14:44:27 -0700268 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700269
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800270 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
271 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700272
Eric Laurentb23d5282013-05-14 15:27:20 -0700273 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700274 [USECASE_VOICE2_CALL] = "voice2-call",
275 [USECASE_VOLTE_CALL] = "volte-call",
276 [USECASE_QCHAT_CALL] = "qchat-call",
277 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800278 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
279 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700280
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700281 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
282 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
283
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700284 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
285 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
vivek mehta781065c2017-04-04 12:55:01 -0700286
287 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
288 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
289 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
290
vivek mehtaa68fea62017-06-08 19:04:02 -0700291 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
292 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Nadav Bar3d72cfc2018-01-07 12:19:24 +0200293
294 [USECASE_INCALL_MUSIC_UPLINK] = "incall-music-uplink",
Aniket Kumar Lata99546312018-03-19 21:38:38 -0700295
296 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700297};
298
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800299
300#define STRING_TO_ENUM(string) { #string, string }
301
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800302struct string_to_enum {
303 const char *name;
304 uint32_t value;
305};
306
Haynes Mathew George569b7482017-05-08 14:44:27 -0700307static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800308 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
309 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
310 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Eric Laurent74b55762017-07-09 17:04:53 -0700311 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
Haynes Mathew George569b7482017-05-08 14:44:27 -0700312 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
Eric Laurent74b55762017-07-09 17:04:53 -0700313 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
314 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
315 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
316 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
317 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
318 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
319 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
320 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
321 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800322};
323
Haynes Mathew George5191a852013-09-11 14:19:36 -0700324static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700325static struct audio_device *adev = NULL;
Andy Hung9e737de2017-05-22 10:51:22 -0700326static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700327static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700328//cache last MBDRC cal step level
329static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700330
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800331static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
332static int set_compr_volume(struct audio_stream_out *stream, float left, float right);
333
Haynes Mathew George03c40102016-01-29 17:57:48 -0800334static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
335 int flags __unused)
336{
337 int dir = 0;
338 switch (uc_id) {
339 case USECASE_AUDIO_RECORD_LOW_LATENCY:
340 dir = 1;
341 case USECASE_AUDIO_PLAYBACK_ULL:
342 break;
343 default:
344 return false;
345 }
346
347 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
348 PCM_PLAYBACK : PCM_CAPTURE);
349 if (adev->adm_is_noirq_avail)
350 return adev->adm_is_noirq_avail(adev->adm_data,
351 adev->snd_card, dev_id, dir);
352 return false;
353}
354
355static void register_out_stream(struct stream_out *out)
356{
357 struct audio_device *adev = out->dev;
358 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
359 return;
360
361 if (!adev->adm_register_output_stream)
362 return;
363
364 adev->adm_register_output_stream(adev->adm_data,
365 out->handle,
366 out->flags);
367
368 if (!adev->adm_set_config)
369 return;
370
371 if (out->realtime) {
372 adev->adm_set_config(adev->adm_data,
373 out->handle,
374 out->pcm, &out->config);
375 }
376}
377
378static void register_in_stream(struct stream_in *in)
379{
380 struct audio_device *adev = in->dev;
381 if (!adev->adm_register_input_stream)
382 return;
383
384 adev->adm_register_input_stream(adev->adm_data,
385 in->capture_handle,
386 in->flags);
387
388 if (!adev->adm_set_config)
389 return;
390
391 if (in->realtime) {
392 adev->adm_set_config(adev->adm_data,
393 in->capture_handle,
394 in->pcm,
395 &in->config);
396 }
397}
398
399static void request_out_focus(struct stream_out *out, long ns)
400{
401 struct audio_device *adev = out->dev;
402
Haynes Mathew George03c40102016-01-29 17:57:48 -0800403 if (adev->adm_request_focus_v2) {
404 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
405 } else if (adev->adm_request_focus) {
406 adev->adm_request_focus(adev->adm_data, out->handle);
407 }
408}
409
410static void request_in_focus(struct stream_in *in, long ns)
411{
412 struct audio_device *adev = in->dev;
413
Haynes Mathew George03c40102016-01-29 17:57:48 -0800414 if (adev->adm_request_focus_v2) {
415 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
416 } else if (adev->adm_request_focus) {
417 adev->adm_request_focus(adev->adm_data, in->capture_handle);
418 }
419}
420
421static void release_out_focus(struct stream_out *out, long ns __unused)
422{
423 struct audio_device *adev = out->dev;
424
425 if (adev->adm_abandon_focus)
426 adev->adm_abandon_focus(adev->adm_data, out->handle);
427}
428
429static void release_in_focus(struct stream_in *in, long ns __unused)
430{
431 struct audio_device *adev = in->dev;
432 if (adev->adm_abandon_focus)
433 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
434}
435
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700436static int parse_snd_card_status(struct str_parms * parms, int * card,
437 card_status_t * status)
438{
439 char value[32]={0};
440 char state[32]={0};
441
442 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
443
444 if (ret < 0)
445 return -1;
446
447 // sscanf should be okay as value is of max length 32.
448 // same as sizeof state.
449 if (sscanf(value, "%d,%s", card, state) < 2)
450 return -1;
451
452 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
453 CARD_STATUS_OFFLINE;
454 return 0;
455}
456
vivek mehta40125092017-08-21 18:48:51 -0700457// always call with adev lock held
458void send_gain_dep_calibration_l() {
459 if (last_known_cal_step >= 0)
460 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
461}
462
vivek mehta1a9b7c02015-06-25 11:49:38 -0700463__attribute__ ((visibility ("default")))
464bool audio_hw_send_gain_dep_calibration(int level) {
465 bool ret_val = false;
466 ALOGV("%s: enter ... ", __func__);
467
468 pthread_mutex_lock(&adev_init_lock);
469
470 if (adev != NULL && adev->platform != NULL) {
471 pthread_mutex_lock(&adev->lock);
vivek mehta40125092017-08-21 18:48:51 -0700472 last_known_cal_step = level;
473 send_gain_dep_calibration_l();
vivek mehta1a9b7c02015-06-25 11:49:38 -0700474 pthread_mutex_unlock(&adev->lock);
475 } else {
476 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
477 }
478
479 pthread_mutex_unlock(&adev_init_lock);
480
481 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
482 return ret_val;
483}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700484
jasmine cha270b7762018-03-30 15:41:33 +0800485#ifdef MAXXAUDIO_QDSP_ENABLED
486bool audio_hw_send_ma_parameter(int stream_type, float vol, bool active)
487{
488 bool ret = false;
489 ALOGV("%s: enter ...", __func__);
490
491 pthread_mutex_lock(&adev_init_lock);
492
493 if (adev != NULL && adev->platform != NULL) {
494 pthread_mutex_lock(&adev->lock);
495 ret = audio_extn_ma_set_state(adev, stream_type, vol, active);
496 pthread_mutex_unlock(&adev->lock);
497 }
498
499 pthread_mutex_unlock(&adev_init_lock);
500
501 ALOGV("%s: exit with ret %d", __func__, ret);
502 return ret;
503}
504#else
505#define audio_hw_send_ma_parameter(stream_type, vol, active) (0)
506#endif
507
vivek mehtaa8d7c922016-05-25 14:40:44 -0700508__attribute__ ((visibility ("default")))
509int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
510 int table_size) {
511 int ret_val = 0;
512 ALOGV("%s: enter ... ", __func__);
513
514 pthread_mutex_lock(&adev_init_lock);
515 if (adev == NULL) {
516 ALOGW("%s: adev is NULL .... ", __func__);
517 goto done;
518 }
519
520 pthread_mutex_lock(&adev->lock);
521 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
522 pthread_mutex_unlock(&adev->lock);
523done:
524 pthread_mutex_unlock(&adev_init_lock);
525 ALOGV("%s: exit ... ", __func__);
526 return ret_val;
527}
528
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700529static bool is_supported_format(audio_format_t format)
530{
Eric Laurent8251ac82014-07-23 11:00:25 -0700531 switch (format) {
532 case AUDIO_FORMAT_MP3:
533 case AUDIO_FORMAT_AAC_LC:
534 case AUDIO_FORMAT_AAC_HE_V1:
535 case AUDIO_FORMAT_AAC_HE_V2:
536 return true;
537 default:
538 break;
539 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700540 return false;
541}
542
Haynes Mathew George03c40102016-01-29 17:57:48 -0800543static inline bool is_mmap_usecase(audio_usecase_t uc_id)
544{
545 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
546 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
547}
548
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700549static int get_snd_codec_id(audio_format_t format)
550{
551 int id = 0;
552
Eric Laurent8251ac82014-07-23 11:00:25 -0700553 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700554 case AUDIO_FORMAT_MP3:
555 id = SND_AUDIOCODEC_MP3;
556 break;
557 case AUDIO_FORMAT_AAC:
558 id = SND_AUDIOCODEC_AAC;
559 break;
560 default:
561 ALOGE("%s: Unsupported audio format", __func__);
562 }
563
564 return id;
565}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800566
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800567static int audio_ssr_status(struct audio_device *adev)
568{
569 int ret = 0;
570 struct mixer_ctl *ctl;
571 const char *mixer_ctl_name = "Audio SSR Status";
572
573 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
574 ret = mixer_ctl_get_value(ctl, 0);
575 ALOGD("%s: value: %d", __func__, ret);
576 return ret;
577}
578
vivek mehta4a824772017-06-08 19:05:49 -0700579static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
580{
581 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
582}
583
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800584static bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
585{
586 return out_snd_device == SND_DEVICE_OUT_BT_SCO ||
587 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
588 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
589 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
590 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
591 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC;
592
593}
594
595static bool is_a2dp_device(snd_device_t out_snd_device)
596{
597 return out_snd_device == SND_DEVICE_OUT_BT_A2DP;
598}
599
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800600int enable_audio_route(struct audio_device *adev,
601 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800602{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700603 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800604 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800605
606 if (usecase == NULL)
607 return -EINVAL;
608
609 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
610
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800611 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700612 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800613 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700614 snd_device = usecase->out_snd_device;
Yamit Mehtae3b99562016-09-16 22:44:00 +0530615 audio_extn_utils_send_app_type_cfg(adev, usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800616 audio_extn_utils_send_audio_calibration(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800617 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500618 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000619 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700620 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700621 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800622
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800623 ALOGV("%s: exit", __func__);
624 return 0;
625}
626
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800627int disable_audio_route(struct audio_device *adev,
628 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800629{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700630 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800631 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800632
633 if (usecase == NULL)
634 return -EINVAL;
635
636 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700637 if (usecase->type == PCM_CAPTURE)
638 snd_device = usecase->in_snd_device;
639 else
640 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800641 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500642 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700643 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700644 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000645 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800646
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800647 ALOGV("%s: exit", __func__);
648 return 0;
649}
650
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800651int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700652 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800653{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700654 int i, num_devices = 0;
655 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800656 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800657 if (snd_device < SND_DEVICE_MIN ||
658 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800659 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800660 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800661 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700662
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700663 platform_send_audio_calibration(adev->platform, snd_device);
664
vivek mehtade4849c2016-03-03 17:23:38 -0800665 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700666 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700667 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800668 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700669 }
670
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700671 /* due to the possibility of calibration overwrite between listen
672 and audio, notify sound trigger hal before audio calibration is sent */
673 audio_extn_sound_trigger_update_device_status(snd_device,
674 ST_EVENT_SND_DEVICE_BUSY);
675
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700676 if (audio_extn_spkr_prot_is_enabled())
677 audio_extn_spkr_prot_calib_cancel(adev);
678
zhaoyang yin4211fad2015-06-04 21:13:25 +0800679 audio_extn_dsm_feedback_enable(adev, snd_device, true);
680
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700681 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800682 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
juyuchen1d05ba32018-03-31 16:03:51 +0800683 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700684 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
685 audio_extn_spkr_prot_is_enabled()) {
Aniket Kumar Lata9d6679a2018-04-11 18:13:23 -0700686 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800687 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700688 }
689 if (audio_extn_spkr_prot_start_processing(snd_device)) {
690 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800691 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700692 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700693 } else if (platform_can_split_snd_device(snd_device,
694 &num_devices,
695 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700696 for (i = 0; i < num_devices; i++) {
697 enable_snd_device(adev, new_snd_devices[i]);
698 }
vivek mehtab6506412015-08-07 16:55:17 -0700699 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700700 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800701 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
702 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
703 ALOGE(" %s: Invalid sound device returned", __func__);
704 goto on_error;
705 }
Ed Tam70b5c142016-03-21 19:14:29 -0700706
Eric Laurent2e140aa2016-06-30 17:14:46 -0700707 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Aniket Kumar Lataa158e862018-05-11 17:28:40 -0700708
709 if (is_a2dp_device(snd_device) &&
710 (audio_extn_a2dp_start_playback() < 0)) {
711 ALOGE("%s: failed to configure A2DP control path", __func__);
712 goto on_error;
713 }
714
vivek mehtade4849c2016-03-03 17:23:38 -0800715 audio_route_apply_and_update_path(adev->audio_route, device_name);
716 }
717on_success:
718 adev->snd_dev_ref_cnt[snd_device]++;
719 ret_val = 0;
720on_error:
721 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800722}
723
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800724int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700725 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800726{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700727 int i, num_devices = 0;
728 snd_device_t new_snd_devices[2];
729
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800730 if (snd_device < SND_DEVICE_MIN ||
731 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800732 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800733 return -EINVAL;
734 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700735 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
736 ALOGE("%s: device ref cnt is already 0", __func__);
737 return -EINVAL;
738 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800739 audio_extn_tfa_98xx_disable_speaker(snd_device);
740
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700741 adev->snd_dev_ref_cnt[snd_device]--;
742 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800743 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800744
745 if (is_a2dp_device(snd_device))
746 audio_extn_a2dp_stop_playback();
747
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700748 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800749 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700750 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700751 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
752 audio_extn_spkr_prot_is_enabled()) {
753 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700754
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700755 // FIXME b/65363602: bullhead is the only Nexus with audio_extn_spkr_prot_is_enabled()
756 // and does not use speaker swap. As this code causes a problem with device enable ref
757 // counting we remove it for now.
vivek mehtae59cfb22017-06-16 15:57:11 -0700758 // when speaker device is disabled, reset swap.
759 // will be renabled on usecase start
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700760 // platform_set_swap_channels(adev, false);
vivek mehtae59cfb22017-06-16 15:57:11 -0700761
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700762 } else if (platform_can_split_snd_device(snd_device,
763 &num_devices,
764 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700765 for (i = 0; i < num_devices; i++) {
766 disable_snd_device(adev, new_snd_devices[i]);
767 }
vivek mehtab6506412015-08-07 16:55:17 -0700768 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700769 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800770 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
771 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
772 ALOGE(" %s: Invalid sound device returned", __func__);
773 return -EINVAL;
774 }
775
Eric Laurent2e140aa2016-06-30 17:14:46 -0700776 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800777 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700778 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700779 audio_extn_sound_trigger_update_device_status(snd_device,
780 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700781 }
vivek mehtab6506412015-08-07 16:55:17 -0700782
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800783 return 0;
784}
785
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700786/*
787 legend:
788 uc - existing usecase
789 new_uc - new usecase
790 d1, d11, d2 - SND_DEVICE enums
791 a1, a2 - corresponding ANDROID device enums
792 B, B1, B2 - backend strings
793
794case 1
795 uc->dev d1 (a1) B1
796 new_uc->dev d1 (a1), d2 (a2) B1, B2
797
798 resolution: disable and enable uc->dev on d1
799
800case 2
801 uc->dev d1 (a1) B1
802 new_uc->dev d11 (a1) B1
803
804 resolution: need to switch uc since d1 and d11 are related
805 (e.g. speaker and voice-speaker)
806 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
807
808case 3
809 uc->dev d1 (a1) B1
810 new_uc->dev d2 (a2) B2
811
812 resolution: no need to switch uc
813
814case 4
815 uc->dev d1 (a1) B
816 new_uc->dev d2 (a2) B
817
818 resolution: disable enable uc-dev on d2 since backends match
819 we cannot enable two streams on two different devices if they
820 share the same backend. e.g. if offload is on speaker device using
821 QUAD_MI2S backend and a low-latency stream is started on voice-handset
822 using the same backend, offload must also be switched to voice-handset.
823
824case 5
825 uc->dev d1 (a1) B
826 new_uc->dev d1 (a1), d2 (a2) B
827
828 resolution: disable enable uc-dev on d2 since backends match
829 we cannot enable two streams on two different devices if they
830 share the same backend.
831
832case 6
833 uc->dev d1 a1 B1
834 new_uc->dev d2 a1 B2
835
836 resolution: no need to switch
837
838case 7
839
840 uc->dev d1 (a1), d2 (a2) B1, B2
841 new_uc->dev d1 B1
842
843 resolution: no need to switch
844
845*/
846static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
847 struct audio_usecase *new_uc,
848 snd_device_t new_snd_device)
849{
850 audio_devices_t a1 = uc->stream.out->devices;
851 audio_devices_t a2 = new_uc->stream.out->devices;
852
853 snd_device_t d1 = uc->out_snd_device;
854 snd_device_t d2 = new_snd_device;
855
856 // Treat as a special case when a1 and a2 are not disjoint
857 if ((a1 != a2) && (a1 & a2)) {
858 snd_device_t d3[2];
859 int num_devices = 0;
860 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
861 &num_devices,
862 d3);
863 if (ret < 0) {
864 if (ret != -ENOSYS) {
865 ALOGW("%s failed to split snd_device %d",
866 __func__,
867 popcount(a1) > 1 ? d1 : d2);
868 }
869 goto end;
870 }
871
872 // NB: case 7 is hypothetical and isn't a practical usecase yet.
873 // But if it does happen, we need to give priority to d2 if
874 // the combo devices active on the existing usecase share a backend.
875 // This is because we cannot have a usecase active on a combo device
876 // and a new usecase requests one device in this combo pair.
877 if (platform_check_backends_match(d3[0], d3[1])) {
878 return d2; // case 5
879 } else {
880 return d1; // case 1
881 }
882 } else {
883 if (platform_check_backends_match(d1, d2)) {
884 return d2; // case 2, 4
885 } else {
886 return d1; // case 6, 3
887 }
888 }
889
890end:
891 return d2; // return whatever was calculated before.
892}
893
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700894static void check_and_route_playback_usecases(struct audio_device *adev,
895 struct audio_usecase *uc_info,
896 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700897{
898 struct listnode *node;
899 struct audio_usecase *usecase;
900 bool switch_device[AUDIO_USECASE_MAX];
901 int i, num_uc_to_switch = 0;
902
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700903 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
904 uc_info,
905 snd_device);
David Linee3fe402017-03-13 10:00:42 -0700906
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800907 /* For a2dp device reconfigure all active sessions
908 * with new AFE encoder format based on a2dp state
909 */
910 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
911 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
912 audio_extn_a2dp_is_force_device_switch()) {
913 force_routing = true;
914 }
915
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700916 /*
917 * This function is to make sure that all the usecases that are active on
918 * the hardware codec backend are always routed to any one device that is
919 * handled by the hardware codec.
920 * For example, if low-latency and deep-buffer usecases are currently active
921 * on speaker and out_set_parameters(headset) is received on low-latency
922 * output, then we have to make sure deep-buffer is also switched to headset,
923 * because of the limitation that both the devices cannot be enabled
924 * at the same time as they share the same backend.
925 */
926 /* Disable all the usecases on the shared backend other than the
927 specified usecase */
928 for (i = 0; i < AUDIO_USECASE_MAX; i++)
929 switch_device[i] = false;
930
931 list_for_each(node, &adev->usecase_list) {
932 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700933 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
934 continue;
935
936 if (force_routing ||
937 (usecase->out_snd_device != snd_device &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -0700938 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
939 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700940 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700941 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
942 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700943 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700944 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700945 switch_device[usecase->id] = true;
946 num_uc_to_switch++;
947 }
948 }
949
950 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700951 list_for_each(node, &adev->usecase_list) {
952 usecase = node_to_item(node, struct audio_usecase, list);
953 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700954 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900955 }
956 }
957
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700958 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900959 list_for_each(node, &adev->usecase_list) {
960 usecase = node_to_item(node, struct audio_usecase, list);
961 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700962 d_device = derive_playback_snd_device(usecase, uc_info,
963 snd_device);
964 enable_snd_device(adev, d_device);
965 /* Update the out_snd_device before enabling the audio route */
966 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700967 }
968 }
969
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700970 /* Re-route all the usecases on the shared backend other than the
971 specified usecase to new snd devices */
972 list_for_each(node, &adev->usecase_list) {
973 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700974 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700975 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700976 }
977 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700978 }
979}
980
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700981static void check_and_route_capture_usecases(struct audio_device *adev,
982 struct audio_usecase *uc_info,
983 snd_device_t snd_device)
984{
985 struct listnode *node;
986 struct audio_usecase *usecase;
987 bool switch_device[AUDIO_USECASE_MAX];
988 int i, num_uc_to_switch = 0;
989
vivek mehta4ed66e62016-04-15 23:33:34 -0700990 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
991
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700992 /*
993 * This function is to make sure that all the active capture usecases
994 * are always routed to the same input sound device.
995 * For example, if audio-record and voice-call usecases are currently
996 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
997 * is received for voice call then we have to make sure that audio-record
998 * usecase is also switched to earpiece i.e. voice-dmic-ef,
999 * because of the limitation that two devices cannot be enabled
1000 * at the same time if they share the same backend.
1001 */
1002 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1003 switch_device[i] = false;
1004
1005 list_for_each(node, &adev->usecase_list) {
1006 usecase = node_to_item(node, struct audio_usecase, list);
1007 if (usecase->type != PCM_PLAYBACK &&
1008 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -07001009 usecase->in_snd_device != snd_device &&
1010 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001011 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1012 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001013 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001014 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001015 switch_device[usecase->id] = true;
1016 num_uc_to_switch++;
1017 }
1018 }
1019
1020 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001021 list_for_each(node, &adev->usecase_list) {
1022 usecase = node_to_item(node, struct audio_usecase, list);
1023 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001024 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001025 }
1026 }
1027
1028 list_for_each(node, &adev->usecase_list) {
1029 usecase = node_to_item(node, struct audio_usecase, list);
1030 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001031 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001032 }
1033 }
1034
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001035 /* Re-route all the usecases on the shared backend other than the
1036 specified usecase to new snd devices */
1037 list_for_each(node, &adev->usecase_list) {
1038 usecase = node_to_item(node, struct audio_usecase, list);
1039 /* Update the in_snd_device only before enabling the audio route */
1040 if (switch_device[usecase->id] ) {
1041 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001042 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001043 }
1044 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001045 }
1046}
1047
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001048/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001049static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001050{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001051 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001052 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001053
1054 switch (channels) {
1055 /*
1056 * Do not handle stereo output in Multi-channel cases
1057 * Stereo case is handled in normal playback path
1058 */
1059 case 6:
1060 ALOGV("%s: HDMI supports 5.1", __func__);
1061 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1062 break;
1063 case 8:
1064 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
1065 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1066 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
1067 break;
1068 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001069 ALOGE("HDMI does not support multi channel playback");
1070 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001071 break;
1072 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001073 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001074}
1075
Andy Hung18859412017-08-09 11:47:21 -07001076static ssize_t read_usb_sup_sample_rates(bool is_playback,
1077 uint32_t *supported_sample_rates,
1078 uint32_t max_rates)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001079{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001080 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1081 supported_sample_rates,
1082 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001083#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001084 for (ssize_t i=0; i<count; i++) {
1085 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1086 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001087 }
1088#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001089 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001090}
1091
Haynes Mathew George569b7482017-05-08 14:44:27 -07001092static int read_usb_sup_channel_masks(bool is_playback,
1093 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001094 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001095{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001096 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001097 int channel_count;
1098 uint32_t num_masks = 0;
1099 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1100 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001101 }
Eric Laurent74b55762017-07-09 17:04:53 -07001102 if (is_playback) {
Andy Hung6c1afb12017-12-22 11:34:41 -08001103 // start from 2 channels as framework currently doesn't support mono.
1104 // TODO: consider only supporting channel index masks beyond stereo here.
1105 for (channel_count = FCC_2;
1106 channel_count <= channels && num_masks < max_masks;
1107 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001108 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1109 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001110 for (channel_count = FCC_2;
1111 channel_count <= channels && num_masks < max_masks;
1112 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001113 supported_channel_masks[num_masks++] =
1114 audio_channel_mask_for_index_assignment_from_count(channel_count);
1115 }
1116 } else {
1117 // For capture we report all supported channel masks from 1 channel up.
1118 channel_count = MIN_CHANNEL_COUNT;
1119 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1120 // indexed mask
1121 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1122 supported_channel_masks[num_masks++] =
1123 audio_channel_in_mask_from_count(channel_count);
1124 }
1125 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001126#ifdef NDEBUG
1127 for (size_t i = 0; i < num_masks; ++i) {
1128 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1129 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
1130 }
1131#endif
Eric Laurent74b55762017-07-09 17:04:53 -07001132 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001133}
1134
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001135static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001136 audio_format_t *supported_formats,
1137 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001138{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001139 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001140 switch (bitwidth) {
1141 case 24:
1142 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001143 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001144 break;
1145 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001146 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001147 break;
1148 case 16:
1149 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001150 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001151 break;
1152 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001153 ALOGV("%s: %s supported format %d", __func__,
1154 is_playback ? "P" : "C", bitwidth);
1155 return 1;
1156}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001157
Haynes Mathew George569b7482017-05-08 14:44:27 -07001158static int read_usb_sup_params_and_compare(bool is_playback,
1159 audio_format_t *format,
1160 audio_format_t *supported_formats,
1161 uint32_t max_formats,
1162 audio_channel_mask_t *mask,
1163 audio_channel_mask_t *supported_channel_masks,
1164 uint32_t max_masks,
1165 uint32_t *rate,
1166 uint32_t *supported_sample_rates,
1167 uint32_t max_rates) {
1168 int ret = 0;
1169 int num_formats;
1170 int num_masks;
1171 int num_rates;
1172 int i;
1173
1174 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1175 max_formats);
1176 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1177 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001178
Haynes Mathew George569b7482017-05-08 14:44:27 -07001179 num_rates = read_usb_sup_sample_rates(is_playback,
1180 supported_sample_rates, max_rates);
1181
1182#define LUT(table, len, what, dflt) \
1183 for (i=0; i<len && (table[i] != what); i++); \
1184 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1185
1186 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1187 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1188 LUT(supported_sample_rates, num_rates, *rate, 0);
1189
1190#undef LUT
1191 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001192}
1193
Andy Hungd9653bd2017-08-01 19:31:39 -07001194static bool is_usb_ready(struct audio_device *adev, bool is_playback)
1195{
1196 // Check if usb is ready.
1197 // The usb device may have been removed quickly after insertion and hence
1198 // no longer available. This will show up as empty channel masks, or rates.
1199
1200 pthread_mutex_lock(&adev->lock);
1201 uint32_t supported_sample_rate;
1202
1203 // we consider usb ready if we can fetch at least one sample rate.
1204 const bool ready = read_usb_sup_sample_rates(
1205 is_playback, &supported_sample_rate, 1 /* max_rates */) > 0;
1206 pthread_mutex_unlock(&adev->lock);
1207 return ready;
1208}
1209
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001210static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1211{
1212 struct audio_usecase *usecase;
1213 struct listnode *node;
1214
1215 list_for_each(node, &adev->usecase_list) {
1216 usecase = node_to_item(node, struct audio_usecase, list);
1217 if (usecase->type == VOICE_CALL) {
1218 ALOGV("%s: usecase id %d", __func__, usecase->id);
1219 return usecase->id;
1220 }
1221 }
1222 return USECASE_INVALID;
1223}
1224
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001225struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1226 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001227{
1228 struct audio_usecase *usecase;
1229 struct listnode *node;
1230
1231 list_for_each(node, &adev->usecase_list) {
1232 usecase = node_to_item(node, struct audio_usecase, list);
1233 if (usecase->id == uc_id)
1234 return usecase;
1235 }
1236 return NULL;
1237}
1238
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001239static bool force_device_switch(struct audio_usecase *usecase)
1240{
1241 if (usecase->stream.out == NULL) {
1242 ALOGE("%s: stream.out is NULL", __func__);
1243 return false;
1244 }
1245
1246 // Force all A2DP output devices to reconfigure for proper AFE encode format
1247 // Also handle a case where in earlier A2DP start failed as A2DP stream was
1248 // in suspended state, hence try to trigger a retry when we again get a routing request.
1249 if ((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
1250 audio_extn_a2dp_is_force_device_switch()) {
1251 ALOGD("%s: Force A2DP device switch to update new encoder config", __func__);
1252 return true;
1253 }
1254
1255 return false;
1256}
1257
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001258int select_devices(struct audio_device *adev,
1259 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001260{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001261 snd_device_t out_snd_device = SND_DEVICE_NONE;
1262 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001263 struct audio_usecase *usecase = NULL;
1264 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001265 struct audio_usecase *hfp_usecase = NULL;
1266 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001267 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001268 int status = 0;
Eric Laurentf4520b02017-09-20 18:31:58 -07001269 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1270 USECASE_AUDIO_PLAYBACK_VOIP);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001271
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001272 usecase = get_usecase_from_list(adev, uc_id);
1273 if (usecase == NULL) {
1274 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1275 return -EINVAL;
1276 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001277
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001278 if ((usecase->type == VOICE_CALL) ||
1279 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001280 out_snd_device = platform_get_output_snd_device(adev->platform,
1281 usecase->stream.out->devices);
1282 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001283 usecase->devices = usecase->stream.out->devices;
1284 } else {
1285 /*
1286 * If the voice call is active, use the sound devices of voice call usecase
1287 * so that it would not result any device switch. All the usecases will
1288 * be switched to new device when select_devices() is called for voice call
1289 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001290 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001291 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001292 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001293 vc_usecase = get_usecase_from_list(adev,
1294 get_voice_usecase_id_from_list(adev));
1295 if ((vc_usecase != NULL) &&
1296 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1297 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001298 in_snd_device = vc_usecase->in_snd_device;
1299 out_snd_device = vc_usecase->out_snd_device;
1300 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001301 } else if (audio_extn_hfp_is_active(adev)) {
1302 hfp_ucid = audio_extn_hfp_get_usecase();
1303 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1304 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1305 in_snd_device = hfp_usecase->in_snd_device;
1306 out_snd_device = hfp_usecase->out_snd_device;
1307 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001308 }
1309 if (usecase->type == PCM_PLAYBACK) {
1310 usecase->devices = usecase->stream.out->devices;
1311 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001312 if (out_snd_device == SND_DEVICE_NONE) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001313 struct stream_out *voip_out = adev->primary_output;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001314
Eric Laurentb23d5282013-05-14 15:27:20 -07001315 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001316 usecase->stream.out->devices);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001317
1318 if (voip_usecase)
1319 voip_out = voip_usecase->stream.out;
1320
1321 if (usecase->stream.out == voip_out &&
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001322 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001323 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001324 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001325 select_devices(adev, adev->active_input->usecase);
1326 }
1327 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001328 } else if (usecase->type == PCM_CAPTURE) {
1329 usecase->devices = usecase->stream.in->device;
1330 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001331 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001332 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001333 if (adev->active_input &&
1334 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1335 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001336
1337 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1338 USECASE_AUDIO_PLAYBACK_VOIP);
1339
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001340 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001341 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1342 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001343 } else if (voip_usecase) {
1344 out_device = voip_usecase->stream.out->devices;
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001345 } else if (adev->primary_output) {
1346 out_device = adev->primary_output->devices;
1347 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001348 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001349 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001350 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001351 }
1352 }
1353
1354 if (out_snd_device == usecase->out_snd_device &&
1355 in_snd_device == usecase->in_snd_device) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001356 if (!force_device_switch(usecase))
1357 return 0;
1358 }
1359
1360 if (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready()) {
1361 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1362 return 0;
1363 }
1364
1365 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP) &&
1366 (!audio_extn_a2dp_is_ready())) {
1367 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
1368 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001369 }
1370
Eric Laurent2bafff12016-03-17 12:17:23 -07001371 if (out_snd_device != SND_DEVICE_NONE &&
1372 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1373 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1374 __func__,
1375 use_case_table[uc_id],
1376 adev->last_logged_snd_device[uc_id][0],
1377 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1378 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1379 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1380 -1,
1381 out_snd_device,
1382 platform_get_snd_device_name(out_snd_device),
1383 platform_get_snd_device_acdb_id(out_snd_device));
1384 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1385 }
1386 if (in_snd_device != SND_DEVICE_NONE &&
1387 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1388 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1389 __func__,
1390 use_case_table[uc_id],
1391 adev->last_logged_snd_device[uc_id][1],
1392 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1393 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1394 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1395 -1,
1396 in_snd_device,
1397 platform_get_snd_device_name(in_snd_device),
1398 platform_get_snd_device_acdb_id(in_snd_device));
1399 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1400 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001401
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001402 /*
1403 * Limitation: While in call, to do a device switch we need to disable
1404 * and enable both RX and TX devices though one of them is same as current
1405 * device.
1406 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001407 if ((usecase->type == VOICE_CALL) &&
1408 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1409 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001410 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001411 /* Disable sidetone only if voice call already exists */
1412 if (voice_is_call_state_active(adev))
1413 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001414 }
1415
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001416 /* Disable current sound devices */
1417 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001418 disable_audio_route(adev, usecase);
1419 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001420 }
1421
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001422 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001423 disable_audio_route(adev, usecase);
1424 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001425 }
1426
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001427 /* Applicable only on the targets that has external modem.
1428 * New device information should be sent to modem before enabling
1429 * the devices to reduce in-call device switch time.
1430 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001431 if ((usecase->type == VOICE_CALL) &&
1432 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1433 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001434 status = platform_switch_voice_call_enable_device_config(adev->platform,
1435 out_snd_device,
1436 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001437 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001438
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001439 /* Enable new sound devices */
1440 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001441 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001442 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) ||
1443 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001444 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001445 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001446 }
1447
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001448 if (in_snd_device != SND_DEVICE_NONE) {
1449 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001450 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001451 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001452
Eric Laurentb23d5282013-05-14 15:27:20 -07001453 if (usecase->type == VOICE_CALL)
1454 status = platform_switch_voice_call_device_post(adev->platform,
1455 out_snd_device,
1456 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001457
sangwoo170731f2013-06-08 15:36:36 +09001458 usecase->in_snd_device = in_snd_device;
1459 usecase->out_snd_device = out_snd_device;
1460
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001461 audio_extn_tfa_98xx_set_mode();
1462
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001463 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001464
jasmine cha270b7762018-03-30 15:41:33 +08001465 audio_extn_ma_set_device(adev, usecase);
1466
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001467 /* Applicable only on the targets that has external modem.
1468 * Enable device command should be sent to modem only after
1469 * enabling voice call mixer controls
1470 */
vivek mehta765eb642015-08-07 19:46:06 -07001471 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001472 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1473 out_snd_device,
1474 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001475 /* Enable sidetone only if voice call already exists */
1476 if (voice_is_call_state_active(adev))
1477 voice_set_sidetone(adev, out_snd_device, true);
1478 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001479
Eric Laurentf4520b02017-09-20 18:31:58 -07001480 if (usecase == voip_usecase) {
1481 struct stream_out *voip_out = voip_usecase->stream.out;
1482 audio_extn_utils_send_app_type_gain(adev,
1483 voip_out->app_type_cfg.app_type,
1484 &voip_out->app_type_cfg.gain[0]);
1485 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001486 return status;
1487}
1488
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001489static int stop_input_stream(struct stream_in *in)
1490{
1491 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001492 struct audio_usecase *uc_info;
1493 struct audio_device *adev = in->dev;
1494
Eric Laurent994a6932013-07-17 11:51:42 -07001495 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001496 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001497
1498 if (adev->active_input) {
1499 if (adev->active_input->usecase == in->usecase) {
1500 adev->active_input = NULL;
1501 } else {
1502 ALOGW("%s adev->active_input->usecase %s, v/s in->usecase %s",
1503 __func__,
1504 use_case_table[adev->active_input->usecase],
1505 use_case_table[in->usecase]);
1506 }
1507 }
1508
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001509 uc_info = get_usecase_from_list(adev, in->usecase);
1510 if (uc_info == NULL) {
1511 ALOGE("%s: Could not find the usecase (%d) in the list",
1512 __func__, in->usecase);
1513 return -EINVAL;
1514 }
1515
vivek mehta781065c2017-04-04 12:55:01 -07001516 /* Close in-call recording streams */
1517 voice_check_and_stop_incall_rec_usecase(adev, in);
1518
Eric Laurent150dbfe2013-02-27 14:31:02 -08001519 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001520 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001521
1522 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001523 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001524
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001525 list_remove(&uc_info->list);
1526 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001527
Eric Laurent994a6932013-07-17 11:51:42 -07001528 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001529 return ret;
1530}
1531
1532int start_input_stream(struct stream_in *in)
1533{
1534 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001535 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001536 struct audio_usecase *uc_info;
1537 struct audio_device *adev = in->dev;
1538
Eric Laurent994a6932013-07-17 11:51:42 -07001539 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001540
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001541 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1542 return -EIO;
1543
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001544 if (in->card_status == CARD_STATUS_OFFLINE ||
1545 adev->card_status == CARD_STATUS_OFFLINE) {
1546 ALOGW("in->card_status or adev->card_status offline, try again");
1547 ret = -EAGAIN;
1548 goto error_config;
1549 }
1550
vivek mehta781065c2017-04-04 12:55:01 -07001551 /* Check if source matches incall recording usecase criteria */
1552 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1553 if (ret)
1554 goto error_config;
1555 else
1556 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1557
Eric Laurentb23d5282013-05-14 15:27:20 -07001558 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001559 if (in->pcm_device_id < 0) {
1560 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1561 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001562 ret = -EINVAL;
1563 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001564 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001565
1566 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001567 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1568 uc_info->id = in->usecase;
1569 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001570 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001571 uc_info->devices = in->device;
1572 uc_info->in_snd_device = SND_DEVICE_NONE;
1573 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001574
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001575 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001576
Wei Wangf4837d52017-11-21 14:51:20 -08001577 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001578 audio_extn_perf_lock_acquire();
1579
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001580 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001581
Eric Laurent0e46adf2016-12-16 12:49:24 -08001582 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001583 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001584 ALOGE("%s: pcm stream not ready", __func__);
1585 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001586 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001587 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001588 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001589 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1590 goto error_open;
1591 }
1592 } else {
1593 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1594 unsigned int pcm_open_retry_count = 0;
1595
1596 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1597 flags |= PCM_MMAP | PCM_NOIRQ;
1598 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1599 } else if (in->realtime) {
1600 flags |= PCM_MMAP | PCM_NOIRQ;
1601 }
1602
1603 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1604 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1605
1606 while (1) {
1607 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1608 flags, &in->config);
1609 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1610 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1611 if (in->pcm != NULL) {
1612 pcm_close(in->pcm);
1613 in->pcm = NULL;
1614 }
1615 if (pcm_open_retry_count-- == 0) {
1616 ret = -EIO;
1617 goto error_open;
1618 }
1619 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1620 continue;
1621 }
1622 break;
1623 }
1624
1625 ALOGV("%s: pcm_prepare", __func__);
1626 ret = pcm_prepare(in->pcm);
1627 if (ret < 0) {
1628 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001629 pcm_close(in->pcm);
1630 in->pcm = NULL;
1631 goto error_open;
1632 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001633 if (in->realtime) {
1634 ret = pcm_start(in->pcm);
1635 if (ret < 0) {
1636 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1637 pcm_close(in->pcm);
1638 in->pcm = NULL;
1639 goto error_open;
1640 }
1641 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001642 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001643 register_in_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001644 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001645 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001646 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001647
Eric Laurent0e46adf2016-12-16 12:49:24 -08001648 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001649
1650error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001651 stop_input_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001652 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001653 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001654
1655error_config:
1656 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001657 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001658 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001659}
1660
Eric Laurenta1478072015-09-21 17:21:52 -07001661void lock_input_stream(struct stream_in *in)
1662{
1663 pthread_mutex_lock(&in->pre_lock);
1664 pthread_mutex_lock(&in->lock);
1665 pthread_mutex_unlock(&in->pre_lock);
1666}
1667
1668void lock_output_stream(struct stream_out *out)
1669{
1670 pthread_mutex_lock(&out->pre_lock);
1671 pthread_mutex_lock(&out->lock);
1672 pthread_mutex_unlock(&out->pre_lock);
1673}
1674
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001675/* must be called with out->lock locked */
1676static int send_offload_cmd_l(struct stream_out* out, int command)
1677{
1678 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1679
1680 ALOGVV("%s %d", __func__, command);
1681
1682 cmd->cmd = command;
1683 list_add_tail(&out->offload_cmd_list, &cmd->node);
1684 pthread_cond_signal(&out->offload_cond);
1685 return 0;
1686}
1687
1688/* must be called iwth out->lock locked */
1689static void stop_compressed_output_l(struct stream_out *out)
1690{
1691 out->offload_state = OFFLOAD_STATE_IDLE;
1692 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001693 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001694 if (out->compr != NULL) {
1695 compress_stop(out->compr);
1696 while (out->offload_thread_blocked) {
1697 pthread_cond_wait(&out->cond, &out->lock);
1698 }
1699 }
1700}
1701
1702static void *offload_thread_loop(void *context)
1703{
1704 struct stream_out *out = (struct stream_out *) context;
1705 struct listnode *item;
1706
1707 out->offload_state = OFFLOAD_STATE_IDLE;
1708 out->playback_started = 0;
1709
1710 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1711 set_sched_policy(0, SP_FOREGROUND);
1712 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1713
1714 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001715 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001716 for (;;) {
1717 struct offload_cmd *cmd = NULL;
1718 stream_callback_event_t event;
1719 bool send_callback = false;
1720
1721 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1722 __func__, list_empty(&out->offload_cmd_list),
1723 out->offload_state);
1724 if (list_empty(&out->offload_cmd_list)) {
1725 ALOGV("%s SLEEPING", __func__);
1726 pthread_cond_wait(&out->offload_cond, &out->lock);
1727 ALOGV("%s RUNNING", __func__);
1728 continue;
1729 }
1730
1731 item = list_head(&out->offload_cmd_list);
1732 cmd = node_to_item(item, struct offload_cmd, node);
1733 list_remove(item);
1734
1735 ALOGVV("%s STATE %d CMD %d out->compr %p",
1736 __func__, out->offload_state, cmd->cmd, out->compr);
1737
1738 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1739 free(cmd);
1740 break;
1741 }
1742
1743 if (out->compr == NULL) {
1744 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001745 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001746 pthread_cond_signal(&out->cond);
1747 continue;
1748 }
1749 out->offload_thread_blocked = true;
1750 pthread_mutex_unlock(&out->lock);
1751 send_callback = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001752 switch (cmd->cmd) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001753 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1754 compress_wait(out->compr, -1);
1755 send_callback = true;
1756 event = STREAM_CBK_EVENT_WRITE_READY;
1757 break;
1758 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001759 compress_next_track(out->compr);
1760 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001761 send_callback = true;
1762 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001763 /* Resend the metadata for next iteration */
1764 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001765 break;
1766 case OFFLOAD_CMD_DRAIN:
1767 compress_drain(out->compr);
1768 send_callback = true;
1769 event = STREAM_CBK_EVENT_DRAIN_READY;
1770 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001771 case OFFLOAD_CMD_ERROR:
1772 send_callback = true;
1773 event = STREAM_CBK_EVENT_ERROR;
1774 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001775 default:
1776 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1777 break;
1778 }
Eric Laurenta1478072015-09-21 17:21:52 -07001779 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001780 out->offload_thread_blocked = false;
1781 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001782 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001783 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001784 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001785 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001786 free(cmd);
1787 }
1788
1789 pthread_cond_signal(&out->cond);
1790 while (!list_empty(&out->offload_cmd_list)) {
1791 item = list_head(&out->offload_cmd_list);
1792 list_remove(item);
1793 free(node_to_item(item, struct offload_cmd, node));
1794 }
1795 pthread_mutex_unlock(&out->lock);
1796
1797 return NULL;
1798}
1799
1800static int create_offload_callback_thread(struct stream_out *out)
1801{
1802 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1803 list_init(&out->offload_cmd_list);
1804 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1805 offload_thread_loop, out);
1806 return 0;
1807}
1808
1809static int destroy_offload_callback_thread(struct stream_out *out)
1810{
Eric Laurenta1478072015-09-21 17:21:52 -07001811 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001812 stop_compressed_output_l(out);
1813 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1814
1815 pthread_mutex_unlock(&out->lock);
1816 pthread_join(out->offload_thread, (void **) NULL);
1817 pthread_cond_destroy(&out->offload_cond);
1818
1819 return 0;
1820}
1821
Eric Laurent07eeafd2013-10-06 12:52:49 -07001822static bool allow_hdmi_channel_config(struct audio_device *adev)
1823{
1824 struct listnode *node;
1825 struct audio_usecase *usecase;
1826 bool ret = true;
1827
1828 list_for_each(node, &adev->usecase_list) {
1829 usecase = node_to_item(node, struct audio_usecase, list);
1830 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1831 /*
1832 * If voice call is already existing, do not proceed further to avoid
1833 * disabling/enabling both RX and TX devices, CSD calls, etc.
1834 * Once the voice call done, the HDMI channels can be configured to
1835 * max channels of remaining use cases.
1836 */
1837 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001838 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001839 __func__);
1840 ret = false;
1841 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001842 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1843 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001844 "no change in HDMI channels", __func__);
1845 ret = false;
1846 break;
1847 }
1848 }
1849 }
1850 return ret;
1851}
1852
1853static int check_and_set_hdmi_channels(struct audio_device *adev,
1854 unsigned int channels)
1855{
1856 struct listnode *node;
1857 struct audio_usecase *usecase;
1858
1859 /* Check if change in HDMI channel config is allowed */
1860 if (!allow_hdmi_channel_config(adev))
1861 return 0;
1862
1863 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001864 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001865 return 0;
1866 }
1867
1868 platform_set_hdmi_channels(adev->platform, channels);
1869 adev->cur_hdmi_channels = channels;
1870
1871 /*
1872 * Deroute all the playback streams routed to HDMI so that
1873 * the back end is deactivated. Note that backend will not
1874 * be deactivated if any one stream is connected to it.
1875 */
1876 list_for_each(node, &adev->usecase_list) {
1877 usecase = node_to_item(node, struct audio_usecase, list);
1878 if (usecase->type == PCM_PLAYBACK &&
1879 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001880 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001881 }
1882 }
1883
1884 /*
1885 * Enable all the streams disabled above. Now the HDMI backend
1886 * will be activated with new channel configuration
1887 */
1888 list_for_each(node, &adev->usecase_list) {
1889 usecase = node_to_item(node, struct audio_usecase, list);
1890 if (usecase->type == PCM_PLAYBACK &&
1891 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001892 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001893 }
1894 }
1895
1896 return 0;
1897}
1898
Haynes Mathew George65f6b432018-02-27 17:44:55 -08001899static int check_and_set_usb_service_interval(struct audio_device *adev,
1900 struct audio_usecase *uc_info,
1901 bool min)
1902{
1903 struct listnode *node;
1904 struct audio_usecase *usecase;
1905 bool switch_usecases = false;
1906 bool reconfig = false;
1907
1908 if ((uc_info->id != USECASE_AUDIO_PLAYBACK_MMAP) &&
1909 (uc_info->id != USECASE_AUDIO_PLAYBACK_ULL))
1910 return -1;
1911
1912 /* set if the valid usecase do not already exist */
1913 list_for_each(node, &adev->usecase_list) {
1914 usecase = node_to_item(node, struct audio_usecase, list);
1915 if (usecase->type == PCM_PLAYBACK &&
1916 (audio_is_usb_out_device(usecase->devices & AUDIO_DEVICE_OUT_ALL_USB))) {
1917 switch (usecase->id) {
1918 case USECASE_AUDIO_PLAYBACK_MMAP:
1919 case USECASE_AUDIO_PLAYBACK_ULL:
1920 // cannot reconfig while mmap/ull is present.
1921 return -1;
1922 default:
1923 switch_usecases = true;
1924 break;
1925 }
1926 }
1927 if (switch_usecases)
1928 break;
1929 }
1930 /*
1931 * client can try to set service interval in start_output_stream
1932 * to min or to 0 (i.e reset) in stop_output_stream .
1933 */
1934 unsigned long service_interval =
1935 audio_extn_usb_find_service_interval(min, true /*playback*/);
1936 int ret = platform_set_usb_service_interval(adev->platform,
1937 true /*playback*/,
1938 service_interval,
1939 &reconfig);
1940 /* no change or not supported or no active usecases */
1941 if (ret || !reconfig || !switch_usecases)
1942 return -1;
1943 return 0;
1944#undef VALID_USECASE
1945}
1946
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001947static int stop_output_stream(struct stream_out *out)
1948{
1949 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001950 struct audio_usecase *uc_info;
1951 struct audio_device *adev = out->dev;
1952
Eric Laurent994a6932013-07-17 11:51:42 -07001953 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001954 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001955 uc_info = get_usecase_from_list(adev, out->usecase);
1956 if (uc_info == NULL) {
1957 ALOGE("%s: Could not find the usecase (%d) in the list",
1958 __func__, out->usecase);
1959 return -EINVAL;
1960 }
1961
Haynes Mathew George41f86652014-06-17 14:22:15 -07001962 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1963 if (adev->visualizer_stop_output != NULL)
1964 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1965 if (adev->offload_effects_stop_output != NULL)
1966 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08001967 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
1968 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
1969 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07001970 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001971
Eric Laurent150dbfe2013-02-27 14:31:02 -08001972 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001973 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001974
1975 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001976 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001977
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001978 list_remove(&uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001979
Eric Laurent0499d4f2014-08-25 22:39:29 -05001980 audio_extn_extspk_update(adev->extspk);
1981
Eric Laurent07eeafd2013-10-06 12:52:49 -07001982 /* Must be called after removing the usecase from list */
1983 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1984 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07001985 else if (out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
1986 struct listnode *node;
1987 struct audio_usecase *usecase;
1988 list_for_each(node, &adev->usecase_list) {
1989 usecase = node_to_item(node, struct audio_usecase, list);
1990 if (usecase->devices & AUDIO_DEVICE_OUT_SPEAKER)
1991 select_devices(adev, usecase->id);
1992 }
Haynes Mathew George65f6b432018-02-27 17:44:55 -08001993 } else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
1994 ret = check_and_set_usb_service_interval(adev, uc_info, false /*min*/);
1995 if (ret == 0) {
1996 /* default service interval was successfully updated,
1997 reopen USB backend with new service interval */
1998 check_and_route_playback_usecases(adev, uc_info, uc_info->out_snd_device);
1999 }
2000 ret = 0;
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07002001 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002002
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002003 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07002004 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002005 return ret;
2006}
2007
2008int start_output_stream(struct stream_out *out)
2009{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002010 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002011 struct audio_usecase *uc_info;
2012 struct audio_device *adev = out->dev;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002013 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002014
Eric Laurent994a6932013-07-17 11:51:42 -07002015 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002016 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002017
2018 if (out->card_status == CARD_STATUS_OFFLINE ||
2019 adev->card_status == CARD_STATUS_OFFLINE) {
2020 ALOGW("out->card_status or adev->card_status offline, try again");
2021 ret = -EAGAIN;
2022 goto error_config;
2023 }
2024
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002025 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2026 if (!audio_extn_a2dp_is_ready()) {
2027 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2028 a2dp_combo = true;
2029 } else {
2030 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2031 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2032 ret = -EAGAIN;
2033 goto error_config;
2034 }
2035 }
2036 }
2037 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002038 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002039 if (out->pcm_device_id < 0) {
2040 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2041 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002042 ret = -EINVAL;
2043 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002044 }
2045
2046 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
2047 uc_info->id = out->usecase;
2048 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002049 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002050 uc_info->devices = out->devices;
2051 uc_info->in_snd_device = SND_DEVICE_NONE;
2052 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002053
Eric Laurent07eeafd2013-10-06 12:52:49 -07002054 /* This must be called before adding this usecase to the list */
2055 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2056 check_and_set_hdmi_channels(adev, out->config.channels);
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002057 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
2058 check_and_set_usb_service_interval(adev, uc_info, true /*min*/);
2059 /* USB backend is not reopened immediately.
2060 This is eventually done as part of select_devices */
2061 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002062
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002063 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002064
Wei Wangf4837d52017-11-21 14:51:20 -08002065 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002066 audio_extn_perf_lock_acquire();
2067
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002068 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2069 (!audio_extn_a2dp_is_ready())) {
2070 if (!a2dp_combo) {
2071 check_a2dp_restore_l(adev, out, false);
2072 } else {
2073 audio_devices_t dev = out->devices;
2074 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2075 select_devices(adev, out->usecase);
2076 out->devices = dev;
2077 }
2078 } else {
2079 select_devices(adev, out->usecase);
2080 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002081
Eric Laurent0499d4f2014-08-25 22:39:29 -05002082 audio_extn_extspk_update(adev->extspk);
2083
Andy Hung31aca912014-03-20 17:14:59 -07002084 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002085 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002086 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2087 out->pcm = NULL;
2088 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
2089 COMPRESS_IN, &out->compr_config);
2090 if (out->compr && !is_compress_ready(out->compr)) {
2091 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2092 compress_close(out->compr);
2093 out->compr = NULL;
2094 ret = -EIO;
2095 goto error_open;
2096 }
2097 if (out->offload_callback)
2098 compress_nonblock(out->compr, out->non_blocking);
2099
2100 if (adev->visualizer_start_output != NULL)
2101 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2102 if (adev->offload_effects_start_output != NULL)
2103 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
2104 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002105 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002106 ALOGE("%s: pcm stream not ready", __func__);
2107 goto error_open;
2108 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002109 ret = pcm_start(out->pcm);
2110 if (ret < 0) {
2111 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2112 goto error_open;
2113 }
2114 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07002115 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002116 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002117
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002118 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2119 flags |= PCM_MMAP | PCM_NOIRQ;
2120 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002121 } else if (out->realtime) {
2122 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07002123 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002124
2125 while (1) {
2126 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2127 flags, &out->config);
2128 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2129 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2130 if (out->pcm != NULL) {
2131 pcm_close(out->pcm);
2132 out->pcm = NULL;
2133 }
2134 if (pcm_open_retry_count-- == 0) {
2135 ret = -EIO;
2136 goto error_open;
2137 }
2138 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2139 continue;
2140 }
2141 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002142 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002143 ALOGV("%s: pcm_prepare", __func__);
2144 if (pcm_is_ready(out->pcm)) {
2145 ret = pcm_prepare(out->pcm);
2146 if (ret < 0) {
2147 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2148 pcm_close(out->pcm);
2149 out->pcm = NULL;
2150 goto error_open;
2151 }
2152 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002153 if (out->realtime) {
2154 ret = pcm_start(out->pcm);
2155 if (ret < 0) {
2156 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
2157 pcm_close(out->pcm);
2158 out->pcm = NULL;
2159 goto error_open;
2160 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002161 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002162 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002163 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08002164 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002165 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002166 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07002167
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002168 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2169 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2170 audio_low_latency_hint_start();
2171 }
2172
vivek mehtae59cfb22017-06-16 15:57:11 -07002173 // consider a scenario where on pause lower layers are tear down.
2174 // so on resume, swap mixer control need to be sent only when
2175 // backend is active, hence rather than sending from enable device
2176 // sending it from start of streamtream
2177
2178 platform_set_swap_channels(adev, true);
2179
Eric Laurent994a6932013-07-17 11:51:42 -07002180 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002181 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002182error_open:
Wei Wangf4837d52017-11-21 14:51:20 -08002183 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002184 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002185 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002186error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002187 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002188}
2189
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002190static int check_input_parameters(uint32_t sample_rate,
2191 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07002192 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002193{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002194 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2195 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002196 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2197 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002198 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2199 return -EINVAL;
2200 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002201
Eric Laurent74b55762017-07-09 17:04:53 -07002202 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2203 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002204 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002205 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002206 return -EINVAL;
2207 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002208
2209 switch (sample_rate) {
2210 case 8000:
2211 case 11025:
2212 case 12000:
2213 case 16000:
2214 case 22050:
2215 case 24000:
2216 case 32000:
2217 case 44100:
2218 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002219 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002220 break;
2221 default:
vivek mehtadae44712015-07-27 14:13:18 -07002222 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002223 return -EINVAL;
2224 }
2225
2226 return 0;
2227}
2228
Kevin Rocarda325aa22018-04-03 09:15:52 -07002229/** Add a value in a list if not already present.
2230 * @return true if value was successfully inserted or already present,
2231 * false if the list is full and does not contain the value.
2232 */
2233static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
2234 for (size_t i = 0; i < list_length; i++) {
2235 if (list[i] == value) return true; // value is already present
2236 if (list[i] == 0) { // no values in this slot
2237 list[i] = value;
2238 return true; // value inserted
2239 }
2240 }
2241 return false; // could not insert value
2242}
2243
2244/** Add channel_mask in supported_channel_masks if not already present.
2245 * @return true if channel_mask was successfully inserted or already present,
2246 * false if supported_channel_masks is full and does not contain channel_mask.
2247 */
2248static void register_channel_mask(audio_channel_mask_t channel_mask,
2249 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
2250 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
2251 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
2252}
2253
2254/** Add format in supported_formats if not already present.
2255 * @return true if format was successfully inserted or already present,
2256 * false if supported_formats is full and does not contain format.
2257 */
2258static void register_format(audio_format_t format,
2259 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
2260 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
2261 "%s: stream can not declare supporting its format %x", __func__, format);
2262}
2263/** Add sample_rate in supported_sample_rates if not already present.
2264 * @return true if sample_rate was successfully inserted or already present,
2265 * false if supported_sample_rates is full and does not contain sample_rate.
2266 */
2267static void register_sample_rate(uint32_t sample_rate,
2268 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
2269 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
2270 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
2271}
2272
vivek mehtaa68fea62017-06-08 19:04:02 -07002273static size_t get_stream_buffer_size(size_t duration_ms,
2274 uint32_t sample_rate,
2275 audio_format_t format,
2276 int channel_count,
2277 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002278{
2279 size_t size = 0;
2280
vivek mehtaa68fea62017-06-08 19:04:02 -07002281 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002282 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002283 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002284
2285 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002286
Glenn Kasten4f993392014-05-14 07:30:48 -07002287 /* make sure the size is multiple of 32 bytes
2288 * At 48 kHz mono 16-bit PCM:
2289 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2290 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2291 */
2292 size += 0x1f;
2293 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002294
2295 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002296}
2297
2298static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2299{
2300 struct stream_out *out = (struct stream_out *)stream;
2301
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002302 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002303}
2304
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002305static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002306{
2307 return -ENOSYS;
2308}
2309
2310static size_t out_get_buffer_size(const struct audio_stream *stream)
2311{
2312 struct stream_out *out = (struct stream_out *)stream;
2313
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002314 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2315 return out->compr_config.fragment_size;
2316 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002317 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002318 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002319}
2320
2321static uint32_t out_get_channels(const struct audio_stream *stream)
2322{
2323 struct stream_out *out = (struct stream_out *)stream;
2324
2325 return out->channel_mask;
2326}
2327
2328static audio_format_t out_get_format(const struct audio_stream *stream)
2329{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002330 struct stream_out *out = (struct stream_out *)stream;
2331
2332 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002333}
2334
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002335static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002336{
2337 return -ENOSYS;
2338}
2339
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002340/* must be called with out->lock locked */
2341static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002342{
2343 struct stream_out *out = (struct stream_out *)stream;
2344 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002345 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002346
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002347 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002348 if (adev->adm_deregister_stream)
2349 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002350 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002351 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002352 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2353 if (out->pcm) {
2354 pcm_close(out->pcm);
2355 out->pcm = NULL;
2356 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002357 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002358 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002359 out->playback_started = false;
2360 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002361 } else {
2362 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002363 out->gapless_mdata.encoder_delay = 0;
2364 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002365 if (out->compr != NULL) {
2366 compress_close(out->compr);
2367 out->compr = NULL;
2368 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002369 }
Phil Burkbc991042017-02-24 08:06:44 -08002370 if (do_stop) {
2371 stop_output_stream(out);
2372 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002373 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002374 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002375 return 0;
2376}
2377
2378static int out_standby(struct audio_stream *stream)
2379{
2380 struct stream_out *out = (struct stream_out *)stream;
2381
2382 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2383 out->usecase, use_case_table[out->usecase]);
2384
2385 lock_output_stream(out);
2386 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002387 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002388 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002389 return 0;
2390}
2391
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002392static int out_on_error(struct audio_stream *stream)
2393{
2394 struct stream_out *out = (struct stream_out *)stream;
2395 struct audio_device *adev = out->dev;
2396 bool do_standby = false;
2397
2398 lock_output_stream(out);
2399 if (!out->standby) {
2400 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2401 stop_compressed_output_l(out);
2402 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2403 } else
2404 do_standby = true;
2405 }
2406 pthread_mutex_unlock(&out->lock);
2407
2408 if (do_standby)
2409 return out_standby(&out->stream.common);
2410
2411 return 0;
2412}
2413
Andy Hung7401c7c2016-09-21 12:41:21 -07002414static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002415{
Andy Hung7401c7c2016-09-21 12:41:21 -07002416 struct stream_out *out = (struct stream_out *)stream;
2417
2418 // We try to get the lock for consistency,
2419 // but it isn't necessary for these variables.
2420 // If we're not in standby, we may be blocked on a write.
2421 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2422 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2423 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2424
2425 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002426 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002427 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002428
2429 // dump error info
2430 (void)error_log_dump(
2431 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002432
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002433 return 0;
2434}
2435
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002436static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2437{
2438 int ret = 0;
2439 char value[32];
2440 struct compr_gapless_mdata tmp_mdata;
2441
2442 if (!out || !parms) {
2443 return -EINVAL;
2444 }
2445
2446 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2447 if (ret >= 0) {
2448 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2449 } else {
2450 return -EINVAL;
2451 }
2452
2453 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2454 if (ret >= 0) {
2455 tmp_mdata.encoder_padding = atoi(value);
2456 } else {
2457 return -EINVAL;
2458 }
2459
2460 out->gapless_mdata = tmp_mdata;
2461 out->send_new_metadata = 1;
2462 ALOGV("%s new encoder delay %u and padding %u", __func__,
2463 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2464
2465 return 0;
2466}
2467
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002468static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2469{
2470 return out == adev->primary_output || out == adev->voice_tx_output;
2471}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002472
Kevin Rocard1e02c882017-08-09 15:26:07 -07002473static int get_alive_usb_card(struct str_parms* parms) {
2474 int card;
2475 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2476 !audio_extn_usb_alive(card)) {
2477 return card;
2478 }
2479 return -ENODEV;
2480}
2481
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002482static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2483{
2484 struct stream_out *out = (struct stream_out *)stream;
2485 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002486 struct audio_usecase *usecase;
2487 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002488 struct str_parms *parms;
2489 char value[32];
2490 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002491 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002492 int status = 0;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002493 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002494
Eric Laurent2e140aa2016-06-30 17:14:46 -07002495 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002496 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002497 parms = str_parms_create_str(kvpairs);
2498 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2499 if (ret >= 0) {
2500 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002501
Eric Laurenta1478072015-09-21 17:21:52 -07002502 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002503
2504 // The usb driver needs to be closed after usb device disconnection
2505 // otherwise audio is no longer played on the new usb devices.
2506 // By forcing the stream in standby, the usb stack refcount drops to 0
2507 // and the driver is closed.
2508 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD && val == AUDIO_DEVICE_NONE &&
2509 audio_is_usb_out_device(out->devices)) {
2510 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2511 out_standby_l(&out->stream.common);
2512 }
2513
Eric Laurent150dbfe2013-02-27 14:31:02 -08002514 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002515
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002516 /*
2517 * When HDMI cable is unplugged the music playback is paused and
2518 * the policy manager sends routing=0. But the audioflinger
2519 * continues to write data until standby time (3sec).
2520 * As the HDMI core is turned off, the write gets blocked.
2521 * Avoid this by routing audio to speaker until standby.
2522 */
2523 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2524 val == AUDIO_DEVICE_NONE) {
2525 val = AUDIO_DEVICE_OUT_SPEAKER;
2526 }
2527
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002528 /*
2529 * When A2DP is disconnected the
2530 * music playback is paused and the policy manager sends routing=0
2531 * But the audioflingercontinues to write data until standby time
2532 * (3sec). As BT is turned off, the write gets blocked.
2533 * Avoid this by routing audio to speaker until standby.
2534 */
2535 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2536 (val == AUDIO_DEVICE_NONE) &&
2537 !audio_extn_a2dp_is_ready()) {
2538 val = AUDIO_DEVICE_OUT_SPEAKER;
2539 }
2540
2541 /* To avoid a2dp to sco overlapping / BT device improper state
2542 * check with BT lib about a2dp streaming support before routing
2543 */
2544 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2545 if (!audio_extn_a2dp_is_ready()) {
2546 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
2547 //combo usecase just by pass a2dp
2548 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2549 bypass_a2dp = true;
2550 } else {
2551 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2552 /* update device to a2dp and don't route as BT returned error
2553 * However it is still possible a2dp routing called because
2554 * of current active device disconnection (like wired headset)
2555 */
2556 out->devices = val;
2557 pthread_mutex_unlock(&out->lock);
2558 pthread_mutex_unlock(&adev->lock);
2559 status = -ENOSYS;
2560 goto routing_fail;
2561 }
2562 }
2563 }
2564
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002565 audio_devices_t new_dev = val;
2566
2567 // Workaround: If routing to an non existing usb device, fail gracefully
2568 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002569 int card;
2570 if (audio_is_usb_out_device(new_dev) &&
2571 (card = get_alive_usb_card(parms)) >= 0) {
2572
2573 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002574 pthread_mutex_unlock(&adev->lock);
2575 pthread_mutex_unlock(&out->lock);
2576 status = -ENOSYS;
2577 goto routing_fail;
2578 }
2579
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002580 /*
2581 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002582 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002583 * the select_devices(). But how do we undo this?
2584 *
2585 * For example, music playback is active on headset (deep-buffer usecase)
2586 * and if we go to ringtones and select a ringtone, low-latency usecase
2587 * will be started on headset+speaker. As we can't enable headset+speaker
2588 * and headset devices at the same time, select_devices() switches the music
2589 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2590 * So when the ringtone playback is completed, how do we undo the same?
2591 *
2592 * We are relying on the out_set_parameters() call on deep-buffer output,
2593 * once the ringtone playback is ended.
2594 * NOTE: We should not check if the current devices are same as new devices.
2595 * Because select_devices() must be called to switch back the music
2596 * playback to headset.
2597 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002598 if (new_dev != AUDIO_DEVICE_NONE) {
2599 bool same_dev = out->devices == new_dev;
2600 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002601
Eric Laurenta7657192014-10-09 21:09:33 -07002602 if (output_drives_call(adev, out)) {
2603 if (!voice_is_in_call(adev)) {
2604 if (adev->mode == AUDIO_MODE_IN_CALL) {
2605 adev->current_call_output = out;
2606 ret = voice_start_call(adev);
2607 }
2608 } else {
2609 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002610 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002611 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002612 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002613
2614 if (!out->standby) {
2615 if (!same_dev) {
2616 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002617 // inform adm before actual routing to prevent glitches.
2618 if (adev->adm_on_routing_change) {
2619 adev->adm_on_routing_change(adev->adm_data,
2620 out->handle);
2621 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002622 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002623 if (!bypass_a2dp) {
2624 select_devices(adev, out->usecase);
2625 } else {
2626 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2627 select_devices(adev, out->usecase);
2628 out->devices = new_dev;
2629 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002630 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002631
2632 // on device switch force swap, lower functions will make sure
2633 // to check if swap is allowed or not.
2634
2635 if (!same_dev)
2636 platform_set_swap_channels(adev, true);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002637
2638 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2639 out->a2dp_compress_mute &&
2640 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
2641 pthread_mutex_lock(&out->compr_mute_lock);
2642 out->a2dp_compress_mute = false;
2643 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
2644 pthread_mutex_unlock(&out->compr_mute_lock);
2645 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002646 }
2647
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002648 }
2649
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002650 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002651 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002652
2653 /*handles device and call state changes*/
2654 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002655 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002656 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002657
2658 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2659 parse_compress_metadata(out, parms);
2660 }
2661
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002662 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002663 ALOGV("%s: exit: code(%d)", __func__, status);
2664 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002665}
2666
Haynes Mathew George569b7482017-05-08 14:44:27 -07002667static bool stream_get_parameter_channels(struct str_parms *query,
2668 struct str_parms *reply,
2669 audio_channel_mask_t *supported_channel_masks) {
2670 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002671 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002672 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002673 size_t i, j;
2674
2675 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2676 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002677 value[0] = '\0';
2678 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002679 while (supported_channel_masks[i] != 0) {
2680 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2681 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002682 if (!first) {
2683 strcat(value, "|");
2684 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002685 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002686 first = false;
2687 break;
2688 }
2689 }
2690 i++;
2691 }
2692 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002693 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002694 return ret >= 0;
2695}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002696
Haynes Mathew George569b7482017-05-08 14:44:27 -07002697static bool stream_get_parameter_formats(struct str_parms *query,
2698 struct str_parms *reply,
2699 audio_format_t *supported_formats) {
2700 int ret = -1;
2701 char value[256];
2702 int i;
2703
2704 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2705 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002706 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002707 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002708 case AUDIO_FORMAT_PCM_16_BIT:
2709 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2710 break;
2711 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2712 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2713 break;
2714 case AUDIO_FORMAT_PCM_32_BIT:
2715 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2716 break;
2717 default:
2718 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002719 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002720 break;
2721 }
2722 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, 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_rates(struct str_parms *query,
2728 struct str_parms *reply,
2729 uint32_t *supported_sample_rates) {
2730
2731 int i;
2732 char value[256];
2733 int ret = -1;
2734 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2735 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002736 value[0] = '\0';
2737 i=0;
2738 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002739 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002740 int avail = sizeof(value) - cursor;
2741 ret = snprintf(value + cursor, avail, "%s%d",
2742 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002743 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002744 if (ret < 0 || ret >= avail) {
2745 // if cursor is at the last element of the array
2746 // overwrite with \0 is duplicate work as
2747 // snprintf already put a \0 in place.
2748 // else
2749 // we had space to write the '|' at value[cursor]
2750 // (which will be overwritten) or no space to fill
2751 // the first element (=> cursor == 0)
2752 value[cursor] = '\0';
2753 break;
2754 }
2755 cursor += ret;
2756 ++i;
2757 }
2758 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2759 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002760 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002761 return ret >= 0;
2762}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002763
Haynes Mathew George569b7482017-05-08 14:44:27 -07002764static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2765{
2766 struct stream_out *out = (struct stream_out *)stream;
2767 struct str_parms *query = str_parms_create_str(keys);
2768 char *str;
2769 struct str_parms *reply = str_parms_create();
2770 bool replied = false;
2771 ALOGV("%s: enter: keys - %s", __func__, keys);
2772
2773 replied |= stream_get_parameter_channels(query, reply,
2774 &out->supported_channel_masks[0]);
2775 replied |= stream_get_parameter_formats(query, reply,
2776 &out->supported_formats[0]);
2777 replied |= stream_get_parameter_rates(query, reply,
2778 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002779 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002780 str = str_parms_to_str(reply);
2781 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002782 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002783 }
2784 str_parms_destroy(query);
2785 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002786 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002787 return str;
2788}
2789
2790static uint32_t out_get_latency(const struct audio_stream_out *stream)
2791{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002792 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002793 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002794 uint32_t latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002795
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002796 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2797 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002798 else if ((out->realtime) ||
2799 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002800 // since the buffer won't be filled up faster than realtime,
2801 // return a smaller number
2802 period_ms = (out->af_period_multiplier * out->config.period_size *
2803 1000) / (out->config.rate);
2804 hw_delay = platform_render_latency(out->usecase)/1000;
2805 return period_ms + hw_delay;
2806 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002807
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002808 latency = (out->config.period_count * out->config.period_size * 1000) /
2809 (out->config.rate);
2810
2811 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
2812 latency += audio_extn_a2dp_get_encoder_latency();
2813
2814 return latency;
2815}
2816
2817static int set_compr_volume(struct audio_stream_out *stream, float left,
2818 float right)
2819{
2820 struct stream_out *out = (struct stream_out *)stream;
2821 int volume[2];
2822 char mixer_ctl_name[128];
2823 struct audio_device *adev = out->dev;
2824 struct mixer_ctl *ctl;
2825 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2826 PCM_PLAYBACK);
2827
2828 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2829 "Compress Playback %d Volume", pcm_device_id);
2830 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2831 if (!ctl) {
2832 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2833 __func__, mixer_ctl_name);
2834 return -EINVAL;
2835 }
2836 ALOGV("%s: ctl for mixer cmd - %s, left %f, right %f",
2837 __func__, mixer_ctl_name, left, right);
2838 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2839 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2840 mixer_ctl_set_array(ctl, volume, sizeof(volume) / sizeof(volume[0]));
2841
2842 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002843}
2844
2845static int out_set_volume(struct audio_stream_out *stream, float left,
2846 float right)
2847{
Eric Laurenta9024de2013-04-04 09:19:12 -07002848 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002849 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002850
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002851 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002852 /* only take left channel into account: the API is for stereo anyway */
2853 out->muted = (left == 0.0f);
2854 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002855 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002856 pthread_mutex_lock(&out->compr_mute_lock);
2857 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
2858 if (!out->a2dp_compress_mute)
2859 ret = set_compr_volume(stream, left, right);
2860 out->volume_l = left;
2861 out->volume_r = right;
2862 pthread_mutex_unlock(&out->compr_mute_lock);
2863 return ret;
vivek mehtaa68fea62017-06-08 19:04:02 -07002864 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002865 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2866 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2867 if (!out->standby) {
2868 // if in standby, cached volume will be sent after stream is opened
2869 audio_extn_utils_send_app_type_gain(out->dev,
2870 out->app_type_cfg.app_type,
2871 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002872 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002873 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002874 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002875
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002876 return -ENOSYS;
2877}
2878
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002879// note: this call is safe only if the stream_cb is
2880// removed first in close_output_stream (as is done now).
2881static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2882{
2883 if (!stream || !parms)
2884 return;
2885
2886 struct stream_out *out = (struct stream_out *)stream;
2887 struct audio_device *adev = out->dev;
2888
2889 card_status_t status;
2890 int card;
2891 if (parse_snd_card_status(parms, &card, &status) < 0)
2892 return;
2893
2894 pthread_mutex_lock(&adev->lock);
2895 bool valid_cb = (card == adev->snd_card);
2896 pthread_mutex_unlock(&adev->lock);
2897
2898 if (!valid_cb)
2899 return;
2900
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002901 lock_output_stream(out);
2902 if (out->card_status != status)
2903 out->card_status = status;
2904 pthread_mutex_unlock(&out->lock);
2905
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002906 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2907 use_case_table[out->usecase],
2908 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2909
2910 if (status == CARD_STATUS_OFFLINE)
2911 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002912
2913 return;
2914}
2915
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002916#ifdef NO_AUDIO_OUT
2917static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002918 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002919{
2920 struct stream_out *out = (struct stream_out *)stream;
2921
2922 /* No Output device supported other than BT for playback.
2923 * Sleep for the amount of buffer duration
2924 */
Eric Laurenta1478072015-09-21 17:21:52 -07002925 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002926 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2927 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002928 out_get_sample_rate(&out->stream.common));
2929 pthread_mutex_unlock(&out->lock);
2930 return bytes;
2931}
2932#endif
2933
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002934static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2935 size_t bytes)
2936{
2937 struct stream_out *out = (struct stream_out *)stream;
2938 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002939 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002940 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002941
Eric Laurenta1478072015-09-21 17:21:52 -07002942 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002943 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07002944 const size_t frame_size = audio_stream_out_frame_size(stream);
2945 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002946
Eric Laurent0e46adf2016-12-16 12:49:24 -08002947 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2948 error_code = ERROR_CODE_WRITE;
2949 goto exit;
2950 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002951
2952 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2953 (audio_extn_a2dp_is_suspended())) {
2954 if (!(out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2955 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2956 ret = -EIO;
2957 goto exit;
2958 }
2959 }
2960 }
2961
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002962 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002963 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002964 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002965 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07002966
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002967 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002968 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002969 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07002970 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002971 goto exit;
2972 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002973
vivek mehta40125092017-08-21 18:48:51 -07002974 // after standby always force set last known cal step
2975 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
2976 ALOGD("%s: retry previous failed cal level set", __func__);
2977 send_gain_dep_calibration_l();
2978 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002979 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002980
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002981 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002982 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002983 if (out->send_new_metadata) {
2984 ALOGVV("send new gapless metadata");
2985 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2986 out->send_new_metadata = 0;
2987 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002988 unsigned int avail;
2989 struct timespec tstamp;
2990 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2991 /* Do not limit write size if the available frames count is unknown */
2992 if (ret != 0) {
2993 avail = bytes;
2994 }
2995 if (avail == 0) {
2996 ret = 0;
2997 } else {
2998 if (avail > bytes) {
2999 avail = bytes;
3000 }
3001 ret = compress_write(out->compr, buffer, avail);
3002 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
3003 __func__, avail, ret);
3004 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003005
Eric Laurent6e895242013-09-05 16:10:57 -07003006 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003007 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
3008 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003009 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003010 compress_start(out->compr);
3011 out->playback_started = 1;
3012 out->offload_state = OFFLOAD_STATE_PLAYING;
3013 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003014 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07003015 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07003016 } else {
3017 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07003018 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003019 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07003020 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003021 return ret;
3022 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07003023 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003024 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003025 size_t bytes_to_write = bytes;
3026
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003027 if (out->muted)
3028 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07003029 // FIXME: this can be removed once audio flinger mixer supports mono output
Nadav Bar3d72cfc2018-01-07 12:19:24 +02003030 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP || out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003031 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3032 int16_t *src = (int16_t *)buffer;
3033 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003034
Eric Laurentad2dde92017-09-20 18:27:31 -07003035 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
3036 out->format != AUDIO_FORMAT_PCM_16_BIT,
3037 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003038
Eric Laurentad2dde92017-09-20 18:27:31 -07003039 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
3040 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
3041 }
3042 bytes_to_write /= 2;
3043 }
3044 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes_to_write);
3045
Glenn Kasten5a59dff2018-02-22 08:05:35 -08003046 long ns = (frames * (int64_t) NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003047 request_out_focus(out, ns);
3048
3049 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3050 if (use_mmap)
Eric Laurentad2dde92017-09-20 18:27:31 -07003051 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003052 else
Eric Laurentad2dde92017-09-20 18:27:31 -07003053 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003054
Haynes Mathew George03c40102016-01-29 17:57:48 -08003055 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07003056 } else {
3057 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003058 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003059 }
3060
3061exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07003062 // For PCM we always consume the buffer and return #bytes regardless of ret.
3063 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003064 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07003065 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003066 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07003067
Andy Hung7401c7c2016-09-21 12:41:21 -07003068 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07003069 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07003070 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3071 ALOGE_IF(out->pcm != NULL,
3072 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07003073 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003074 // usleep not guaranteed for values over 1 second but we don't limit here.
3075 }
3076 }
Andy Hungda9b56b2016-09-16 20:06:35 -07003077
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003078 pthread_mutex_unlock(&out->lock);
3079
3080 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07003081 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003082 if (sleeptime_us != 0)
3083 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003084 }
3085 return bytes;
3086}
3087
3088static int out_get_render_position(const struct audio_stream_out *stream,
3089 uint32_t *dsp_frames)
3090{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003091 struct stream_out *out = (struct stream_out *)stream;
3092 *dsp_frames = 0;
3093 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07003094 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003095 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003096 unsigned long frames = 0;
3097 // TODO: check return value
3098 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
3099 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003100 ALOGVV("%s rendered frames %d sample_rate %d",
3101 __func__, *dsp_frames, out->sample_rate);
3102 }
3103 pthread_mutex_unlock(&out->lock);
3104 return 0;
3105 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003106 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003107}
3108
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003109static int out_add_audio_effect(const struct audio_stream *stream __unused,
3110 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003111{
3112 return 0;
3113}
3114
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003115static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3116 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003117{
3118 return 0;
3119}
3120
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003121static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3122 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003123{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003124 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003125}
3126
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003127static int out_get_presentation_position(const struct audio_stream_out *stream,
3128 uint64_t *frames, struct timespec *timestamp)
3129{
3130 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003131 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07003132 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003133
Eric Laurenta1478072015-09-21 17:21:52 -07003134 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003135
Eric Laurent949a0892013-09-20 09:20:13 -07003136 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3137 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003138 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07003139 compress_get_tstamp(out->compr, &dsp_frames,
3140 &out->sample_rate);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003141 // Adjustment accounts for A2DP encoder latency with offload usecases
3142 // Note: Encoder latency is returned in ms.
3143 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3144 unsigned long offset =
3145 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3146 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
3147 }
Eric Laurent949a0892013-09-20 09:20:13 -07003148 ALOGVV("%s rendered frames %ld sample_rate %d",
3149 __func__, dsp_frames, out->sample_rate);
3150 *frames = dsp_frames;
3151 ret = 0;
3152 /* this is the best we can do */
3153 clock_gettime(CLOCK_MONOTONIC, timestamp);
3154 }
3155 } else {
3156 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07003157 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003158 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3159 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003160 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003161 // This adjustment accounts for buffering after app processor.
3162 // It is based on estimated DSP latency per use case, rather than exact.
3163 signed_frames -=
3164 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3165
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003166 // Adjustment accounts for A2DP encoder latency with non-offload usecases
3167 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3168 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3169 signed_frames -=
3170 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3171 }
3172
Eric Laurent949a0892013-09-20 09:20:13 -07003173 // It would be unusual for this value to be negative, but check just in case ...
3174 if (signed_frames >= 0) {
3175 *frames = signed_frames;
3176 ret = 0;
3177 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003178 }
3179 }
3180 }
3181
3182 pthread_mutex_unlock(&out->lock);
3183
3184 return ret;
3185}
3186
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003187static int out_set_callback(struct audio_stream_out *stream,
3188 stream_callback_t callback, void *cookie)
3189{
3190 struct stream_out *out = (struct stream_out *)stream;
3191
3192 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003193 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003194 out->offload_callback = callback;
3195 out->offload_cookie = cookie;
3196 pthread_mutex_unlock(&out->lock);
3197 return 0;
3198}
3199
3200static int out_pause(struct audio_stream_out* stream)
3201{
3202 struct stream_out *out = (struct stream_out *)stream;
3203 int status = -ENOSYS;
3204 ALOGV("%s", __func__);
3205 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003206 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003207 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
3208 status = compress_pause(out->compr);
3209 out->offload_state = OFFLOAD_STATE_PAUSED;
3210 }
3211 pthread_mutex_unlock(&out->lock);
3212 }
3213 return status;
3214}
3215
3216static int out_resume(struct audio_stream_out* stream)
3217{
3218 struct stream_out *out = (struct stream_out *)stream;
3219 int status = -ENOSYS;
3220 ALOGV("%s", __func__);
3221 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3222 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07003223 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003224 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
3225 status = compress_resume(out->compr);
3226 out->offload_state = OFFLOAD_STATE_PLAYING;
3227 }
3228 pthread_mutex_unlock(&out->lock);
3229 }
3230 return status;
3231}
3232
3233static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3234{
3235 struct stream_out *out = (struct stream_out *)stream;
3236 int status = -ENOSYS;
3237 ALOGV("%s", __func__);
3238 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003239 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003240 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3241 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3242 else
3243 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3244 pthread_mutex_unlock(&out->lock);
3245 }
3246 return status;
3247}
3248
3249static int out_flush(struct audio_stream_out* stream)
3250{
3251 struct stream_out *out = (struct stream_out *)stream;
3252 ALOGV("%s", __func__);
3253 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003254 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003255 stop_compressed_output_l(out);
3256 pthread_mutex_unlock(&out->lock);
3257 return 0;
3258 }
3259 return -ENOSYS;
3260}
3261
Eric Laurent0e46adf2016-12-16 12:49:24 -08003262static int out_stop(const struct audio_stream_out* stream)
3263{
3264 struct stream_out *out = (struct stream_out *)stream;
3265 struct audio_device *adev = out->dev;
3266 int ret = -ENOSYS;
3267
3268 ALOGV("%s", __func__);
3269 pthread_mutex_lock(&adev->lock);
3270 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3271 out->playback_started && out->pcm != NULL) {
3272 pcm_stop(out->pcm);
3273 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08003274 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003275 }
3276 pthread_mutex_unlock(&adev->lock);
3277 return ret;
3278}
3279
3280static int out_start(const struct audio_stream_out* stream)
3281{
3282 struct stream_out *out = (struct stream_out *)stream;
3283 struct audio_device *adev = out->dev;
3284 int ret = -ENOSYS;
3285
3286 ALOGV("%s", __func__);
3287 pthread_mutex_lock(&adev->lock);
3288 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3289 !out->playback_started && out->pcm != NULL) {
3290 ret = start_output_stream(out);
3291 if (ret == 0) {
3292 out->playback_started = true;
3293 }
3294 }
3295 pthread_mutex_unlock(&adev->lock);
3296 return ret;
3297}
3298
Phil Burkbc991042017-02-24 08:06:44 -08003299/*
3300 * Modify config->period_count based on min_size_frames
3301 */
3302static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
3303{
3304 int periodCountRequested = (min_size_frames + config->period_size - 1)
3305 / config->period_size;
3306 int periodCount = MMAP_PERIOD_COUNT_MIN;
3307
3308 ALOGV("%s original config.period_size = %d config.period_count = %d",
3309 __func__, config->period_size, config->period_count);
3310
3311 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
3312 periodCount *= 2;
3313 }
3314 config->period_count = periodCount;
3315
3316 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
3317}
3318
Eric Laurent0e46adf2016-12-16 12:49:24 -08003319static int out_create_mmap_buffer(const struct audio_stream_out *stream,
3320 int32_t min_size_frames,
3321 struct audio_mmap_buffer_info *info)
3322{
3323 struct stream_out *out = (struct stream_out *)stream;
3324 struct audio_device *adev = out->dev;
3325 int ret = 0;
3326 unsigned int offset1;
3327 unsigned int frames1;
3328 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003329 uint32_t mmap_size;
3330 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003331
3332 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003333 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003334 pthread_mutex_lock(&adev->lock);
3335
3336 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003337 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003338 ret = -EINVAL;
3339 goto exit;
3340 }
3341 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003342 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003343 ret = -ENOSYS;
3344 goto exit;
3345 }
3346 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3347 if (out->pcm_device_id < 0) {
3348 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3349 __func__, out->pcm_device_id, out->usecase);
3350 ret = -EINVAL;
3351 goto exit;
3352 }
Phil Burkbc991042017-02-24 08:06:44 -08003353
3354 adjust_mmap_period_count(&out->config, min_size_frames);
3355
Eric Laurent0e46adf2016-12-16 12:49:24 -08003356 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3357 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3358 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3359 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3360 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3361 step = "open";
3362 ret = -ENODEV;
3363 goto exit;
3364 }
3365 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3366 if (ret < 0) {
3367 step = "begin";
3368 goto exit;
3369 }
3370 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003371 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003372 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003373 ret = platform_get_mmap_data_fd(adev->platform,
3374 out->pcm_device_id, 0 /*playback*/,
3375 &info->shared_memory_fd,
3376 &mmap_size);
3377 if (ret < 0) {
3378 // Fall back to non exclusive mode
3379 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3380 } else {
3381 if (mmap_size < buffer_size) {
3382 step = "mmap";
3383 goto exit;
3384 }
3385 // FIXME: indicate exclusive mode support by returning a negative buffer size
3386 info->buffer_size_frames *= -1;
3387 }
3388 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003389
3390 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3391 if (ret < 0) {
3392 step = "commit";
3393 goto exit;
3394 }
Phil Burkbc991042017-02-24 08:06:44 -08003395
3396 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003397 ret = 0;
3398
3399 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3400 __func__, info->shared_memory_address, info->buffer_size_frames);
3401
3402exit:
3403 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003404 if (out->pcm == NULL) {
3405 ALOGE("%s: %s - %d", __func__, step, ret);
3406 } else {
3407 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003408 pcm_close(out->pcm);
3409 out->pcm = NULL;
3410 }
3411 }
3412 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003413 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003414 return ret;
3415}
3416
3417static int out_get_mmap_position(const struct audio_stream_out *stream,
3418 struct audio_mmap_position *position)
3419{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003420 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003421 struct stream_out *out = (struct stream_out *)stream;
3422 ALOGVV("%s", __func__);
3423 if (position == NULL) {
3424 return -EINVAL;
3425 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003426 lock_output_stream(out);
3427 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3428 out->pcm == NULL) {
3429 ret = -ENOSYS;
3430 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003431 }
3432
3433 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003434 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003435 if (ret < 0) {
3436 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003437 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003438 }
Andy Hungfc044e12017-03-20 09:24:22 -07003439 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003440exit:
3441 pthread_mutex_unlock(&out->lock);
3442 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003443}
3444
3445
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003446/** audio_stream_in implementation **/
3447static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3448{
3449 struct stream_in *in = (struct stream_in *)stream;
3450
3451 return in->config.rate;
3452}
3453
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003454static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003455{
3456 return -ENOSYS;
3457}
3458
3459static size_t in_get_buffer_size(const struct audio_stream *stream)
3460{
3461 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003462 return in->config.period_size * in->af_period_multiplier *
3463 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003464}
3465
3466static uint32_t in_get_channels(const struct audio_stream *stream)
3467{
3468 struct stream_in *in = (struct stream_in *)stream;
3469
3470 return in->channel_mask;
3471}
3472
vivek mehta4ed66e62016-04-15 23:33:34 -07003473static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003474{
vivek mehta4ed66e62016-04-15 23:33:34 -07003475 struct stream_in *in = (struct stream_in *)stream;
3476 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003477}
3478
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003479static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003480{
3481 return -ENOSYS;
3482}
3483
3484static int in_standby(struct audio_stream *stream)
3485{
3486 struct stream_in *in = (struct stream_in *)stream;
3487 struct audio_device *adev = in->dev;
3488 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003489 bool do_stop = true;
3490
Eric Laurent994a6932013-07-17 11:51:42 -07003491 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003492
3493 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003494
3495 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003496 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003497 audio_extn_sound_trigger_stop_lab(in);
3498 in->standby = true;
3499 }
3500
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003501 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003502 if (adev->adm_deregister_stream)
3503 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3504
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003505 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003506 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003507 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003508 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003509 in->capture_started = false;
3510 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003511 if (in->pcm) {
3512 pcm_close(in->pcm);
3513 in->pcm = NULL;
3514 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003515 adev->enable_voicerx = false;
3516 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003517 if (do_stop) {
3518 status = stop_input_stream(in);
3519 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003520 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003521 }
3522 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003523 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003524 return status;
3525}
3526
Andy Hungd13f0d32017-06-12 13:58:37 -07003527static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003528{
Andy Hungd13f0d32017-06-12 13:58:37 -07003529 struct stream_in *in = (struct stream_in *)stream;
3530
3531 // We try to get the lock for consistency,
3532 // but it isn't necessary for these variables.
3533 // If we're not in standby, we may be blocked on a read.
3534 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3535 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3536 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3537 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3538
3539 if (locked) {
3540 pthread_mutex_unlock(&in->lock);
3541 }
3542
3543 // dump error info
3544 (void)error_log_dump(
3545 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003546 return 0;
3547}
3548
3549static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3550{
3551 struct stream_in *in = (struct stream_in *)stream;
3552 struct audio_device *adev = in->dev;
3553 struct str_parms *parms;
3554 char *str;
3555 char value[32];
3556 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003557 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003558
Eric Laurent994a6932013-07-17 11:51:42 -07003559 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003560 parms = str_parms_create_str(kvpairs);
3561
3562 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3563
Eric Laurenta1478072015-09-21 17:21:52 -07003564 lock_input_stream(in);
3565
Eric Laurent150dbfe2013-02-27 14:31:02 -08003566 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003567 if (ret >= 0) {
3568 val = atoi(value);
3569 /* no audio source uses val == 0 */
3570 if ((in->source != val) && (val != 0)) {
3571 in->source = val;
3572 }
3573 }
3574
3575 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003576
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003577 if (ret >= 0) {
3578 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003579 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003580
3581 // Workaround: If routing to an non existing usb device, fail gracefully
3582 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003583 int card;
3584 if (audio_is_usb_in_device(val) &&
3585 (card = get_alive_usb_card(parms)) >= 0) {
3586
3587 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003588 status = -ENOSYS;
3589 } else {
3590
3591 in->device = val;
3592 /* If recording is in progress, change the tx device to new device */
3593 if (!in->standby) {
3594 ALOGV("update input routing change");
3595 // inform adm before actual routing to prevent glitches.
3596 if (adev->adm_on_routing_change) {
3597 adev->adm_on_routing_change(adev->adm_data,
3598 in->capture_handle);
3599 }
3600 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003601 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003602 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003603 }
3604 }
3605
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003606 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003607 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003608
3609 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003610 ALOGV("%s: exit: status(%d)", __func__, status);
3611 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003612}
3613
Haynes Mathew George569b7482017-05-08 14:44:27 -07003614static char* in_get_parameters(const struct audio_stream *stream,
3615 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003616{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003617 struct stream_in *in = (struct stream_in *)stream;
3618 struct str_parms *query = str_parms_create_str(keys);
3619 char *str;
3620 struct str_parms *reply = str_parms_create();
3621 bool replied = false;
3622
3623 ALOGV("%s: enter: keys - %s", __func__, keys);
3624 replied |= stream_get_parameter_channels(query, reply,
3625 &in->supported_channel_masks[0]);
3626 replied |= stream_get_parameter_formats(query, reply,
3627 &in->supported_formats[0]);
3628 replied |= stream_get_parameter_rates(query, reply,
3629 &in->supported_sample_rates[0]);
3630 if (replied) {
3631 str = str_parms_to_str(reply);
3632 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003633 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003634 }
3635 str_parms_destroy(query);
3636 str_parms_destroy(reply);
3637 ALOGV("%s: exit: returns - %s", __func__, str);
3638 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003639}
3640
Eric Laurent51f3c662018-04-10 18:21:34 -07003641static int in_set_gain(struct audio_stream_in *stream, float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003642{
Eric Laurent51f3c662018-04-10 18:21:34 -07003643 struct stream_in *in = (struct stream_in *)stream;
3644 char mixer_ctl_name[128];
3645 struct mixer_ctl *ctl;
3646 int ctl_value;
3647
3648 ALOGV("%s: gain %f", __func__, gain);
3649
3650 if (stream == NULL)
3651 return -EINVAL;
3652
3653 /* in_set_gain() only used to silence MMAP capture for now */
3654 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
3655 return -ENOSYS;
3656
3657 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
3658
3659 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
3660 if (!ctl) {
3661 ALOGW("%s: Could not get ctl for mixer cmd - %s",
3662 __func__, mixer_ctl_name);
3663 return -ENOSYS;
3664 }
3665
3666 if (gain < RECORD_GAIN_MIN)
3667 gain = RECORD_GAIN_MIN;
3668 else if (gain > RECORD_GAIN_MAX)
3669 gain = RECORD_GAIN_MAX;
3670 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
3671
3672 mixer_ctl_set_value(ctl, 0, ctl_value);
3673 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003674}
3675
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003676static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3677{
3678 if (!stream || !parms)
3679 return;
3680
3681 struct stream_in *in = (struct stream_in *)stream;
3682 struct audio_device *adev = in->dev;
3683
3684 card_status_t status;
3685 int card;
3686 if (parse_snd_card_status(parms, &card, &status) < 0)
3687 return;
3688
3689 pthread_mutex_lock(&adev->lock);
3690 bool valid_cb = (card == adev->snd_card);
3691 pthread_mutex_unlock(&adev->lock);
3692
3693 if (!valid_cb)
3694 return;
3695
3696 lock_input_stream(in);
3697 if (in->card_status != status)
3698 in->card_status = status;
3699 pthread_mutex_unlock(&in->lock);
3700
3701 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3702 use_case_table[in->usecase],
3703 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3704
3705 // a better solution would be to report error back to AF and let
3706 // it put the stream to standby
3707 if (status == CARD_STATUS_OFFLINE)
3708 in_standby(&in->stream.common);
3709
3710 return;
3711}
3712
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003713static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3714 size_t bytes)
3715{
3716 struct stream_in *in = (struct stream_in *)stream;
3717 struct audio_device *adev = in->dev;
3718 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003719 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003720 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003721
Eric Laurenta1478072015-09-21 17:21:52 -07003722 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003723 const size_t frame_size = audio_stream_in_frame_size(stream);
3724 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003725
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003726 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003727 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003728 /* Read from sound trigger HAL */
3729 audio_extn_sound_trigger_read(in, buffer, bytes);
3730 pthread_mutex_unlock(&in->lock);
3731 return bytes;
3732 }
3733
Eric Laurent0e46adf2016-12-16 12:49:24 -08003734 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3735 ret = -ENOSYS;
3736 goto exit;
3737 }
3738
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003739 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003740 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003741 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003742 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003743 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003744 goto exit;
3745 }
3746 in->standby = 0;
3747 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003748
Andy Hungd13f0d32017-06-12 13:58:37 -07003749 // errors that occur here are read errors.
3750 error_code = ERROR_CODE_READ;
3751
Haynes Mathew George03c40102016-01-29 17:57:48 -08003752 //what's the duration requested by the client?
3753 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3754 in->config.rate;
3755 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003756
Haynes Mathew George03c40102016-01-29 17:57:48 -08003757 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003758 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003759 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003760 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003761 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003762 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003763 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003764 if (ret < 0) {
3765 ALOGE("Failed to read w/err %s", strerror(errno));
3766 ret = -errno;
3767 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003768 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3769 if (bytes % 4 == 0) {
3770 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3771 int_buf_stream = buffer;
3772 for (size_t itt=0; itt < bytes/4 ; itt++) {
3773 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003774 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003775 } else {
3776 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3777 ret = -EINVAL;
3778 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003779 }
3780 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003781 }
3782
Haynes Mathew George03c40102016-01-29 17:57:48 -08003783 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003784
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003785 /*
3786 * Instead of writing zeroes here, we could trust the hardware
3787 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003788 * 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 -08003789 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08003790 if (ret == 0 && adev->mic_muted &&
3791 !voice_is_in_call_rec_stream(in) &&
3792 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003793 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07003794 in->frames_muted += frames;
3795 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003796
3797exit:
3798 pthread_mutex_unlock(&in->lock);
3799
3800 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07003801 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003802 in_standby(&in->stream.common);
3803 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003804 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003805 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07003806 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08003807 }
3808 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003809 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003810 }
3811 return bytes;
3812}
3813
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003814static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003815{
3816 return 0;
3817}
3818
Andy Hung6ebe5962016-01-15 17:46:57 -08003819static int in_get_capture_position(const struct audio_stream_in *stream,
3820 int64_t *frames, int64_t *time)
3821{
3822 if (stream == NULL || frames == NULL || time == NULL) {
3823 return -EINVAL;
3824 }
3825 struct stream_in *in = (struct stream_in *)stream;
3826 int ret = -ENOSYS;
3827
3828 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003829 // note: ST sessions do not close the alsa pcm driver synchronously
3830 // on standby. Therefore, we may return an error even though the
3831 // pcm stream is still opened.
3832 if (in->standby) {
3833 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
3834 "%s stream in standby but pcm not NULL for non ST session", __func__);
3835 goto exit;
3836 }
Andy Hung6ebe5962016-01-15 17:46:57 -08003837 if (in->pcm) {
3838 struct timespec timestamp;
3839 unsigned int avail;
3840 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3841 *frames = in->frames_read + avail;
3842 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3843 ret = 0;
3844 }
3845 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003846exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08003847 pthread_mutex_unlock(&in->lock);
3848 return ret;
3849}
3850
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003851static int add_remove_audio_effect(const struct audio_stream *stream,
3852 effect_handle_t effect,
3853 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003854{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003855 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003856 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003857 int status = 0;
3858 effect_descriptor_t desc;
3859
3860 status = (*effect)->get_descriptor(effect, &desc);
3861 if (status != 0)
3862 return status;
3863
Eric Laurenta1478072015-09-21 17:21:52 -07003864 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003865 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003866 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003867 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003868 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003869 in->enable_aec != enable &&
3870 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3871 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003872 if (!enable)
3873 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003874 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3875 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3876 adev->enable_voicerx = enable;
3877 struct audio_usecase *usecase;
3878 struct listnode *node;
3879 list_for_each(node, &adev->usecase_list) {
3880 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07003881 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07003882 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05003883 }
3884 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003885 if (!in->standby)
3886 select_devices(in->dev, in->usecase);
3887 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003888 if (in->enable_ns != enable &&
3889 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3890 in->enable_ns = enable;
3891 if (!in->standby)
3892 select_devices(in->dev, in->usecase);
3893 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003894 pthread_mutex_unlock(&in->dev->lock);
3895 pthread_mutex_unlock(&in->lock);
3896
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003897 return 0;
3898}
3899
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003900static int in_add_audio_effect(const struct audio_stream *stream,
3901 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003902{
Eric Laurent994a6932013-07-17 11:51:42 -07003903 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003904 return add_remove_audio_effect(stream, effect, true);
3905}
3906
3907static int in_remove_audio_effect(const struct audio_stream *stream,
3908 effect_handle_t effect)
3909{
Eric Laurent994a6932013-07-17 11:51:42 -07003910 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003911 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003912}
3913
Eric Laurent0e46adf2016-12-16 12:49:24 -08003914static int in_stop(const struct audio_stream_in* stream)
3915{
3916 struct stream_in *in = (struct stream_in *)stream;
3917 struct audio_device *adev = in->dev;
3918
3919 int ret = -ENOSYS;
3920 ALOGV("%s", __func__);
3921 pthread_mutex_lock(&adev->lock);
3922 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3923 in->capture_started && in->pcm != NULL) {
3924 pcm_stop(in->pcm);
3925 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003926 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003927 }
3928 pthread_mutex_unlock(&adev->lock);
3929 return ret;
3930}
3931
3932static int in_start(const struct audio_stream_in* stream)
3933{
3934 struct stream_in *in = (struct stream_in *)stream;
3935 struct audio_device *adev = in->dev;
3936 int ret = -ENOSYS;
3937
3938 ALOGV("%s in %p", __func__, in);
3939 pthread_mutex_lock(&adev->lock);
3940 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3941 !in->capture_started && in->pcm != NULL) {
3942 if (!in->capture_started) {
3943 ret = start_input_stream(in);
3944 if (ret == 0) {
3945 in->capture_started = true;
3946 }
3947 }
3948 }
3949 pthread_mutex_unlock(&adev->lock);
3950 return ret;
3951}
3952
3953static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3954 int32_t min_size_frames,
3955 struct audio_mmap_buffer_info *info)
3956{
3957 struct stream_in *in = (struct stream_in *)stream;
3958 struct audio_device *adev = in->dev;
3959 int ret = 0;
3960 unsigned int offset1;
3961 unsigned int frames1;
3962 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003963 uint32_t mmap_size;
3964 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003965
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003966 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003967 pthread_mutex_lock(&adev->lock);
3968 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003969
Eric Laurent0e46adf2016-12-16 12:49:24 -08003970 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003971 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003972 ret = -EINVAL;
3973 goto exit;
3974 }
3975 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003976 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003977 ALOGV("%s in %p", __func__, in);
3978 ret = -ENOSYS;
3979 goto exit;
3980 }
3981 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3982 if (in->pcm_device_id < 0) {
3983 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3984 __func__, in->pcm_device_id, in->usecase);
3985 ret = -EINVAL;
3986 goto exit;
3987 }
Phil Burkbc991042017-02-24 08:06:44 -08003988
3989 adjust_mmap_period_count(&in->config, min_size_frames);
3990
Eric Laurent0e46adf2016-12-16 12:49:24 -08003991 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3992 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3993 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3994 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3995 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3996 step = "open";
3997 ret = -ENODEV;
3998 goto exit;
3999 }
4000
4001 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
4002 if (ret < 0) {
4003 step = "begin";
4004 goto exit;
4005 }
4006 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07004007 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004008 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07004009 ret = platform_get_mmap_data_fd(adev->platform,
4010 in->pcm_device_id, 1 /*capture*/,
4011 &info->shared_memory_fd,
4012 &mmap_size);
4013 if (ret < 0) {
4014 // Fall back to non exclusive mode
4015 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
4016 } else {
4017 if (mmap_size < buffer_size) {
4018 step = "mmap";
4019 goto exit;
4020 }
4021 // FIXME: indicate exclusive mode support by returning a negative buffer size
4022 info->buffer_size_frames *= -1;
4023 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08004024
Haynes Mathew George96483a22017-03-28 14:52:47 -07004025 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004026
4027 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4028 if (ret < 0) {
4029 step = "commit";
4030 goto exit;
4031 }
4032
Phil Burkbc991042017-02-24 08:06:44 -08004033 in->standby = false;
4034 ret = 0;
4035
Eric Laurent0e46adf2016-12-16 12:49:24 -08004036 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4037 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004038
4039exit:
4040 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004041 if (in->pcm == NULL) {
4042 ALOGE("%s: %s - %d", __func__, step, ret);
4043 } else {
4044 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08004045 pcm_close(in->pcm);
4046 in->pcm = NULL;
4047 }
4048 }
4049 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004050 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004051 return ret;
4052}
4053
4054static int in_get_mmap_position(const struct audio_stream_in *stream,
4055 struct audio_mmap_position *position)
4056{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004057 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004058 struct stream_in *in = (struct stream_in *)stream;
4059 ALOGVV("%s", __func__);
4060 if (position == NULL) {
4061 return -EINVAL;
4062 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004063 lock_input_stream(in);
4064 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
4065 in->pcm == NULL) {
4066 ret = -ENOSYS;
4067 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004068 }
4069 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004070 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004071 if (ret < 0) {
4072 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004073 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004074 }
Andy Hungfc044e12017-03-20 09:24:22 -07004075 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004076exit:
4077 pthread_mutex_unlock(&in->lock);
4078 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004079}
4080
jiabin8962a4d2018-03-19 18:21:24 -07004081static int in_get_active_microphones(const struct audio_stream_in *stream,
4082 struct audio_microphone_characteristic_t *mic_array,
4083 size_t *mic_count) {
4084 struct stream_in *in = (struct stream_in *)stream;
4085 struct audio_device *adev = in->dev;
4086 ALOGVV("%s", __func__);
4087
4088 lock_input_stream(in);
4089 pthread_mutex_lock(&adev->lock);
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004090 int ret = platform_get_active_microphones(adev->platform,
jiabin8962a4d2018-03-19 18:21:24 -07004091 audio_channel_count_from_in_mask(in->channel_mask),
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004092 in->usecase, mic_array, mic_count);
jiabin8962a4d2018-03-19 18:21:24 -07004093 pthread_mutex_unlock(&adev->lock);
4094 pthread_mutex_unlock(&in->lock);
4095
4096 return ret;
4097}
4098
4099static int adev_get_microphones(const struct audio_hw_device *dev,
4100 struct audio_microphone_characteristic_t *mic_array,
4101 size_t *mic_count) {
4102 struct audio_device *adev = (struct audio_device *)dev;
4103 ALOGVV("%s", __func__);
4104
4105 pthread_mutex_lock(&adev->lock);
4106 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
4107 pthread_mutex_unlock(&adev->lock);
4108
4109 return ret;
4110}
Eric Laurent0e46adf2016-12-16 12:49:24 -08004111
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004112static int adev_open_output_stream(struct audio_hw_device *dev,
4113 audio_io_handle_t handle,
4114 audio_devices_t devices,
4115 audio_output_flags_t flags,
4116 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07004117 struct audio_stream_out **stream_out,
4118 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004119{
4120 struct audio_device *adev = (struct audio_device *)dev;
4121 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004122 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004123 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
4124 bool is_usb_dev = audio_is_usb_out_device(devices) &&
4125 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004126
Andy Hungd9653bd2017-08-01 19:31:39 -07004127 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
4128 return -ENOSYS;
4129 }
4130
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004131 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
4132 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004133 *stream_out = NULL;
4134 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4135
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004136 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
4137
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004138 if (devices == AUDIO_DEVICE_NONE)
4139 devices = AUDIO_DEVICE_OUT_SPEAKER;
4140
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004141 out->flags = flags;
4142 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004143 out->dev = adev;
Eric Laurentc4aef752013-09-12 17:45:53 -07004144 out->handle = handle;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004145 out->a2dp_compress_mute = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004146
4147 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004148 if ((is_hdmi || is_usb_dev) &&
4149 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
4150 (flags == AUDIO_OUTPUT_FLAG_NONE ||
4151 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Eric Laurentab805ee2018-03-30 12:20:38 -07004152 audio_format_t req_format = config->format;
4153 audio_channel_mask_t req_channel_mask = config->channel_mask;
4154 uint32_t req_sample_rate = config->sample_rate;
4155
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004156 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004157 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004158 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004159 if (config->sample_rate == 0)
4160 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Eric Laurentab805ee2018-03-30 12:20:38 -07004161 if (config->channel_mask == AUDIO_CHANNEL_NONE)
Haynes Mathew George569b7482017-05-08 14:44:27 -07004162 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
4163 if (config->format == AUDIO_FORMAT_DEFAULT)
4164 config->format = AUDIO_FORMAT_PCM_16_BIT;
4165 } else if (is_usb_dev) {
4166 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
4167 &config->format,
4168 &out->supported_formats[0],
4169 MAX_SUPPORTED_FORMATS,
4170 &config->channel_mask,
4171 &out->supported_channel_masks[0],
4172 MAX_SUPPORTED_CHANNEL_MASKS,
4173 &config->sample_rate,
4174 &out->supported_sample_rates[0],
4175 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004176 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004177 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004178 pthread_mutex_unlock(&adev->lock);
Eric Laurentab805ee2018-03-30 12:20:38 -07004179 if (ret != 0) {
4180 // For MMAP NO IRQ, allow conversions in ADSP
4181 if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
4182 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004183
Eric Laurentab805ee2018-03-30 12:20:38 -07004184 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
4185 config->sample_rate = req_sample_rate;
4186 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
4187 config->channel_mask = req_channel_mask;
4188 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
4189 config->format = req_format;
4190 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004191
Haynes Mathew George569b7482017-05-08 14:44:27 -07004192 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004193 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004194 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004195 if (is_hdmi) {
4196 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4197 out->config = pcm_config_hdmi_multi;
4198 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
4199 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4200 out->config = pcm_config_mmap_playback;
4201 out->stream.start = out_start;
4202 out->stream.stop = out_stop;
4203 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4204 out->stream.get_mmap_position = out_get_mmap_position;
4205 } else {
4206 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4207 out->config = pcm_config_hifi;
4208 }
4209
4210 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004211 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004212 if (is_hdmi) {
4213 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
4214 audio_bytes_per_sample(out->format));
4215 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004216 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004217 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07004218 pthread_mutex_lock(&adev->lock);
4219 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4220 pthread_mutex_unlock(&adev->lock);
4221
4222 // reject offload during card offline to allow
4223 // fallback to s/w paths
4224 if (offline) {
4225 ret = -ENODEV;
4226 goto error_open;
4227 }
4228
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004229 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4230 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4231 ALOGE("%s: Unsupported Offload information", __func__);
4232 ret = -EINVAL;
4233 goto error_open;
4234 }
4235 if (!is_supported_format(config->offload_info.format)) {
4236 ALOGE("%s: Unsupported audio format", __func__);
4237 ret = -EINVAL;
4238 goto error_open;
4239 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004240 out->sample_rate = config->offload_info.sample_rate;
4241 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
4242 out->channel_mask = config->offload_info.channel_mask;
4243 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
4244 out->channel_mask = config->channel_mask;
4245 else
4246 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4247
4248 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004249
4250 out->compr_config.codec = (struct snd_codec *)
4251 calloc(1, sizeof(struct snd_codec));
4252
4253 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004254
4255 out->stream.set_callback = out_set_callback;
4256 out->stream.pause = out_pause;
4257 out->stream.resume = out_resume;
4258 out->stream.drain = out_drain;
4259 out->stream.flush = out_flush;
4260
4261 out->compr_config.codec->id =
4262 get_snd_codec_id(config->offload_info.format);
4263 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
4264 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004265 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004266 out->compr_config.codec->bit_rate =
4267 config->offload_info.bit_rate;
4268 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004269 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004270 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
4271
4272 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4273 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004274
4275 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004276 create_offload_callback_thread(out);
4277 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4278 __func__, config->offload_info.version,
4279 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02004280 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4281 switch (config->sample_rate) {
4282 case 0:
4283 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4284 break;
4285 case 8000:
4286 case 16000:
4287 case 48000:
4288 out->sample_rate = config->sample_rate;
4289 break;
4290 default:
4291 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
4292 config->sample_rate);
4293 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4294 ret = -EINVAL;
4295 goto error_open;
4296 }
4297 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4298 switch (config->channel_mask) {
4299 case AUDIO_CHANNEL_NONE:
4300 case AUDIO_CHANNEL_OUT_STEREO:
4301 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4302 break;
4303 default:
4304 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
4305 config->channel_mask);
4306 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4307 ret = -EINVAL;
4308 goto error_open;
4309 }
4310 switch (config->format) {
4311 case AUDIO_FORMAT_DEFAULT:
4312 case AUDIO_FORMAT_PCM_16_BIT:
4313 out->format = AUDIO_FORMAT_PCM_16_BIT;
4314 break;
4315 default:
4316 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
4317 config->format);
4318 config->format = AUDIO_FORMAT_PCM_16_BIT;
4319 ret = -EINVAL;
4320 goto error_open;
4321 }
4322
4323 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004324 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004325 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004326 case 0:
4327 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
4328 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07004329 case 8000:
4330 case 16000:
4331 case 48000:
4332 out->sample_rate = config->sample_rate;
4333 break;
4334 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004335 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
4336 config->sample_rate);
4337 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4338 ret = -EINVAL;
4339 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004340 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004341 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4342 switch (config->channel_mask) {
4343 case AUDIO_CHANNEL_NONE:
4344 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4345 break;
4346 case AUDIO_CHANNEL_OUT_STEREO:
4347 out->channel_mask = config->channel_mask;
4348 break;
4349 default:
4350 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
4351 config->channel_mask);
4352 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4353 ret = -EINVAL;
4354 break;
4355 }
4356 switch (config->format) {
4357 case AUDIO_FORMAT_DEFAULT:
4358 out->format = AUDIO_FORMAT_PCM_16_BIT;
4359 break;
4360 case AUDIO_FORMAT_PCM_16_BIT:
4361 out->format = config->format;
4362 break;
4363 default:
4364 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
4365 config->format);
4366 config->format = AUDIO_FORMAT_PCM_16_BIT;
4367 ret = -EINVAL;
4368 break;
4369 }
4370 if (ret != 0)
4371 goto error_open;
4372
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004373 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4374 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004375 out->config.rate = out->sample_rate;
4376 out->config.channels =
4377 audio_channel_count_from_out_mask(out->channel_mask);
4378 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004379 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004380 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
4381 switch (config->sample_rate) {
4382 case 0:
4383 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4384 break;
4385 case 8000:
4386 case 16000:
4387 case 32000:
4388 case 48000:
4389 out->sample_rate = config->sample_rate;
4390 break;
4391 default:
4392 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
4393 config->sample_rate);
4394 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4395 ret = -EINVAL;
4396 break;
4397 }
Eric Laurentad2dde92017-09-20 18:27:31 -07004398 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004399 switch (config->channel_mask) {
4400 case AUDIO_CHANNEL_NONE:
4401 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4402 break;
4403 case AUDIO_CHANNEL_OUT_STEREO:
4404 out->channel_mask = config->channel_mask;
4405 break;
4406 default:
4407 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
4408 config->channel_mask);
4409 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4410 ret = -EINVAL;
4411 break;
4412 }
4413 switch (config->format) {
4414 case AUDIO_FORMAT_DEFAULT:
4415 out->format = AUDIO_FORMAT_PCM_16_BIT;
4416 break;
4417 case AUDIO_FORMAT_PCM_16_BIT:
4418 out->format = config->format;
4419 break;
4420 default:
4421 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
4422 config->format);
4423 config->format = AUDIO_FORMAT_PCM_16_BIT;
4424 ret = -EINVAL;
4425 break;
4426 }
4427 if (ret != 0)
4428 goto error_open;
4429
vivek mehtaa68fea62017-06-08 19:04:02 -07004430 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07004431 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4432 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004433 out->config.rate = out->sample_rate;
4434 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07004435 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004436 out->sample_rate,
4437 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07004438 out->config.channels,
4439 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004440 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07004441 out->config.period_size = buffer_size / frame_size;
4442 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
4443 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004444 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004445 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07004446 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4447 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004448 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07004449 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
4450 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004451 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07004452 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004453 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004454 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004455 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004456 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4457 out->config = pcm_config_mmap_playback;
4458 out->stream.start = out_start;
4459 out->stream.stop = out_stop;
4460 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4461 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004462 } else {
4463 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4464 out->config = pcm_config_low_latency;
4465 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004466
4467 if (config->sample_rate == 0) {
4468 out->sample_rate = out->config.rate;
4469 } else {
4470 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004471 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004472 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
4473 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
4474 } else {
4475 out->channel_mask = config->channel_mask;
4476 }
4477 if (config->format == AUDIO_FORMAT_DEFAULT)
4478 out->format = audio_format_from_pcm_format(out->config.format);
4479 else if (!audio_is_linear_pcm(config->format)) {
4480 config->format = AUDIO_FORMAT_PCM_16_BIT;
4481 ret = -EINVAL;
4482 goto error_open;
4483 } else {
4484 out->format = config->format;
4485 }
4486
4487 out->config.rate = out->sample_rate;
4488 out->config.channels =
4489 audio_channel_count_from_out_mask(out->channel_mask);
4490 if (out->format != audio_format_from_pcm_format(out->config.format)) {
4491 out->config.format = pcm_format_from_audio_format(out->format);
4492 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004493 }
Kevin Rocard50eff892017-05-02 16:52:05 -07004494
4495 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
4496 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004497 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004498 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
4499 __func__, config->sample_rate, config->format, config->channel_mask);
4500 config->sample_rate = out->sample_rate;
4501 config->format = out->format;
4502 config->channel_mask = out->channel_mask;
4503 ret = -EINVAL;
4504 goto error_open;
4505 }
4506
Andy Hung6fcba9c2014-03-18 11:53:32 -07004507 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
4508 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004509
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004510 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004511 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004512 adev->primary_output = out;
4513 else {
4514 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004515 ret = -EEXIST;
4516 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004517 }
4518 }
4519
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004520 /* Check if this usecase is already existing */
4521 pthread_mutex_lock(&adev->lock);
4522 if (get_usecase_from_list(adev, out->usecase) != NULL) {
4523 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004524 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004525 ret = -EEXIST;
4526 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004527 }
4528 pthread_mutex_unlock(&adev->lock);
4529
4530 out->stream.common.get_sample_rate = out_get_sample_rate;
4531 out->stream.common.set_sample_rate = out_set_sample_rate;
4532 out->stream.common.get_buffer_size = out_get_buffer_size;
4533 out->stream.common.get_channels = out_get_channels;
4534 out->stream.common.get_format = out_get_format;
4535 out->stream.common.set_format = out_set_format;
4536 out->stream.common.standby = out_standby;
4537 out->stream.common.dump = out_dump;
4538 out->stream.common.set_parameters = out_set_parameters;
4539 out->stream.common.get_parameters = out_get_parameters;
4540 out->stream.common.add_audio_effect = out_add_audio_effect;
4541 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4542 out->stream.get_latency = out_get_latency;
4543 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004544#ifdef NO_AUDIO_OUT
4545 out->stream.write = out_write_for_no_output;
4546#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004547 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004548#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004549 out->stream.get_render_position = out_get_render_position;
4550 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004551 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004552
Eric Laurent0e46adf2016-12-16 12:49:24 -08004553 if (out->realtime)
4554 out->af_period_multiplier = af_period_multiplier;
4555 else
4556 out->af_period_multiplier = 1;
4557
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004558 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004559 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004560 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004561
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004562 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004563 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004564 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4565
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004566 config->format = out->stream.common.get_format(&out->stream.common);
4567 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4568 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4569
Kevin Rocarda325aa22018-04-03 09:15:52 -07004570 register_format(out->format, out->supported_formats);
4571 register_channel_mask(out->channel_mask, out->supported_channel_masks);
4572 register_sample_rate(out->sample_rate, out->supported_sample_rates);
4573
Andy Hunga452b0a2017-03-15 14:51:15 -07004574 out->error_log = error_log_create(
4575 ERROR_LOG_ENTRIES,
4576 1000000000 /* aggregate consecutive identical errors within one second in ns */);
4577
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004578 /*
4579 By locking output stream before registering, we allow the callback
4580 to update stream's state only after stream's initial state is set to
4581 adev state.
4582 */
4583 lock_output_stream(out);
4584 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4585 pthread_mutex_lock(&adev->lock);
4586 out->card_status = adev->card_status;
4587 pthread_mutex_unlock(&adev->lock);
4588 pthread_mutex_unlock(&out->lock);
4589
vivek mehta4a824772017-06-08 19:05:49 -07004590 stream_app_type_cfg_init(&out->app_type_cfg);
4591
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004592 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004593
Eric Laurent994a6932013-07-17 11:51:42 -07004594 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004595 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004596
4597error_open:
4598 free(out);
4599 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07004600 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004601 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004602}
4603
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004604static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004605 struct audio_stream_out *stream)
4606{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004607 struct stream_out *out = (struct stream_out *)stream;
4608 struct audio_device *adev = out->dev;
4609
Eric Laurent994a6932013-07-17 11:51:42 -07004610 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004611
4612 // must deregister from sndmonitor first to prevent races
4613 // between the callback and close_stream
4614 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004615 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004616 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
4617 destroy_offload_callback_thread(out);
4618
4619 if (out->compr_config.codec != NULL)
4620 free(out->compr_config.codec);
4621 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004622
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004623 out->a2dp_compress_mute = false;
4624
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004625 if (adev->voice_tx_output == out)
4626 adev->voice_tx_output = NULL;
4627
Andy Hunga452b0a2017-03-15 14:51:15 -07004628 error_log_destroy(out->error_log);
4629 out->error_log = NULL;
4630
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004631 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004632 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004633 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004634 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004635 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004636}
4637
4638static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4639{
4640 struct audio_device *adev = (struct audio_device *)dev;
4641 struct str_parms *parms;
4642 char *str;
4643 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004644 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004645 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07004646 int status = 0;
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004647 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004648
Joe Onorato188b6222016-03-01 11:02:27 -08004649 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004650
4651 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004652
4653 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004654 status = voice_set_parameters(adev, parms);
4655 if (status != 0) {
4656 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004657 }
4658
4659 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4660 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07004661 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004662 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4663 adev->bluetooth_nrec = true;
4664 else
4665 adev->bluetooth_nrec = false;
4666 }
4667
4668 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4669 if (ret >= 0) {
4670 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4671 adev->screen_off = false;
4672 else
4673 adev->screen_off = true;
4674 }
4675
jasmine cha270b7762018-03-30 15:41:33 +08004676#ifndef MAXXAUDIO_QDSP_ENABLED
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004677 ret = str_parms_get_int(parms, "rotation", &val);
4678 if (ret >= 0) {
4679 bool reverse_speakers = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004680 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004681 // FIXME: note that the code below assumes that the speakers are in the correct placement
4682 // relative to the user when the device is rotated 90deg from its default rotation. This
4683 // assumption is device-specific, not platform-specific like this code.
4684 case 270:
4685 reverse_speakers = true;
4686 break;
4687 case 0:
4688 case 90:
4689 case 180:
4690 break;
4691 default:
4692 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07004693 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004694 }
Eric Laurent03f09432014-03-25 18:09:11 -07004695 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004696 // check and set swap
4697 // - check if orientation changed and speaker active
4698 // - set rotation and cache the rotation value
4699 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004700 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004701 }
jasmine cha270b7762018-03-30 15:41:33 +08004702#endif
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004703
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004704 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4705 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004706 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004707 }
4708
David Linee3fe402017-03-13 10:00:42 -07004709 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4710 if (ret >= 0) {
4711 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004712 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004713 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4714 if (ret >= 0) {
4715 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004716 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004717 }
Eric Laurent99dab492017-06-17 15:19:08 -07004718 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004719 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4720 if (ret >= 0) {
4721 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004722 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004723 }
4724 }
4725 }
4726
4727 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4728 if (ret >= 0) {
4729 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004730 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004731 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4732 if (ret >= 0) {
4733 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004734 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004735 }
Eric Laurent99dab492017-06-17 15:19:08 -07004736 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004737 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4738 if (ret >= 0) {
4739 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004740 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004741 }
4742 }
4743 }
4744
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004745 audio_extn_hfp_set_parameters(adev, parms);
jasmine cha270b7762018-03-30 15:41:33 +08004746 audio_extn_ma_set_parameters(adev, parms);
4747
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004748 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
4749 if (status >= 0 && a2dp_reconfig) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004750 struct audio_usecase *usecase;
4751 struct listnode *node;
4752 list_for_each(node, &adev->usecase_list) {
4753 usecase = node_to_item(node, struct audio_usecase, list);
4754 if ((usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004755 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004756 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
4757
4758 pthread_mutex_unlock(&adev->lock);
4759 lock_output_stream(usecase->stream.out);
4760 pthread_mutex_lock(&adev->lock);
4761 audio_extn_a2dp_set_handoff_mode(true);
4762 // force device switch to reconfigure encoder
4763 select_devices(adev, usecase->id);
4764 audio_extn_a2dp_set_handoff_mode(false);
4765 pthread_mutex_unlock(&usecase->stream.out->lock);
4766 break;
4767 }
4768 }
4769 }
4770
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004771done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004772 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004773 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004774 ALOGV("%s: exit with code(%d)", __func__, status);
4775 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004776}
4777
4778static char* adev_get_parameters(const struct audio_hw_device *dev,
4779 const char *keys)
4780{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004781 struct audio_device *adev = (struct audio_device *)dev;
4782 struct str_parms *reply = str_parms_create();
4783 struct str_parms *query = str_parms_create_str(keys);
4784 char *str;
4785
4786 pthread_mutex_lock(&adev->lock);
4787
4788 voice_get_parameters(adev, query, reply);
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004789 audio_extn_a2dp_get_parameters(query, reply);
4790
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004791 str = str_parms_to_str(reply);
4792 str_parms_destroy(query);
4793 str_parms_destroy(reply);
4794
4795 pthread_mutex_unlock(&adev->lock);
4796 ALOGV("%s: exit: returns - %s", __func__, str);
4797 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004798}
4799
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004800static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004801{
4802 return 0;
4803}
4804
Haynes Mathew George5191a852013-09-11 14:19:36 -07004805static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4806{
4807 int ret;
4808 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004809
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004810 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4811
Haynes Mathew George5191a852013-09-11 14:19:36 -07004812 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004813 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004814 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004815
Haynes Mathew George5191a852013-09-11 14:19:36 -07004816 return ret;
4817}
4818
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004819static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004820{
4821 return -ENOSYS;
4822}
4823
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004824static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4825 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004826{
4827 return -ENOSYS;
4828}
4829
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004830static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004831{
4832 return -ENOSYS;
4833}
4834
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004835static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004836{
4837 return -ENOSYS;
4838}
4839
4840static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4841{
4842 struct audio_device *adev = (struct audio_device *)dev;
4843
4844 pthread_mutex_lock(&adev->lock);
4845 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004846 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004847 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004848 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4849 voice_is_in_call(adev)) {
4850 voice_stop_call(adev);
4851 adev->current_call_output = NULL;
4852 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004853 }
4854 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004855
4856 audio_extn_extspk_set_mode(adev->extspk, mode);
4857
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004858 return 0;
4859}
4860
4861static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4862{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004863 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004864 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004865
Eric Laurent2bafff12016-03-17 12:17:23 -07004866 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004867 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004868 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4869 ret = audio_extn_hfp_set_mic_mute(adev, state);
4870 } else {
4871 ret = voice_set_mic_mute(adev, state);
4872 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004873 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004874 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004875
4876 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004877}
4878
4879static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4880{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004881 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004882 return 0;
4883}
4884
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004885static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004886 const struct audio_config *config)
4887{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004888 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004889
Eric Laurent74b55762017-07-09 17:04:53 -07004890 /* Don't know if USB HIFI in this context so use true to be conservative */
4891 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4892 true /*is_usb_hifi */) != 0)
4893 return 0;
4894
vivek mehtaa68fea62017-06-08 19:04:02 -07004895 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4896 config->sample_rate, config->format,
4897 channel_count,
4898 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004899}
4900
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004901static bool adev_input_allow_hifi_record(struct audio_device *adev,
4902 audio_devices_t devices,
4903 audio_input_flags_t flags,
4904 audio_source_t source) {
4905 const bool allowed = true;
4906
4907 if (!audio_is_usb_in_device(devices))
4908 return !allowed;
4909
4910 switch (flags) {
4911 case AUDIO_INPUT_FLAG_NONE:
4912 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4913 break;
4914 default:
4915 return !allowed;
4916 }
4917
4918 switch (source) {
4919 case AUDIO_SOURCE_DEFAULT:
4920 case AUDIO_SOURCE_MIC:
4921 case AUDIO_SOURCE_UNPROCESSED:
4922 break;
4923 default:
4924 return !allowed;
4925 }
4926
4927 switch (adev->mode) {
4928 case 0:
4929 break;
4930 default:
4931 return !allowed;
4932 }
4933
4934 return allowed;
4935}
4936
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004937static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004938 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004939 audio_devices_t devices,
4940 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004941 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004942 audio_input_flags_t flags,
4943 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004944 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004945{
4946 struct audio_device *adev = (struct audio_device *)dev;
4947 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004948 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004949 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004950 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004951 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004952 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4953 devices,
4954 flags,
4955 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004956 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004957 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004958
Andy Hungd9653bd2017-08-01 19:31:39 -07004959 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
4960 return -ENOSYS;
4961 }
4962
Eric Laurent74b55762017-07-09 17:04:53 -07004963 if (!(is_usb_dev && may_use_hifi_record)) {
4964 if (config->sample_rate == 0)
4965 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4966 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4967 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4968 if (config->format == AUDIO_FORMAT_DEFAULT)
4969 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004970
Eric Laurent74b55762017-07-09 17:04:53 -07004971 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
4972
4973 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
4974 return -EINVAL;
4975 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004976
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004977 if (audio_extn_tfa_98xx_is_supported() &&
4978 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004979 return -EINVAL;
4980
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004981 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4982
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004983 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004984 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004985
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004986 in->stream.common.get_sample_rate = in_get_sample_rate;
4987 in->stream.common.set_sample_rate = in_set_sample_rate;
4988 in->stream.common.get_buffer_size = in_get_buffer_size;
4989 in->stream.common.get_channels = in_get_channels;
4990 in->stream.common.get_format = in_get_format;
4991 in->stream.common.set_format = in_set_format;
4992 in->stream.common.standby = in_standby;
4993 in->stream.common.dump = in_dump;
4994 in->stream.common.set_parameters = in_set_parameters;
4995 in->stream.common.get_parameters = in_get_parameters;
4996 in->stream.common.add_audio_effect = in_add_audio_effect;
4997 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4998 in->stream.set_gain = in_set_gain;
4999 in->stream.read = in_read;
5000 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08005001 in->stream.get_capture_position = in_get_capture_position;
jiabin8962a4d2018-03-19 18:21:24 -07005002 in->stream.get_active_microphones = in_get_active_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005003
5004 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005005 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005006 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005007 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005008 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005009 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005010
Arun Mirpuriba2749a2018-04-17 14:32:24 -07005011 ALOGV("%s: source = %d, config->channel_mask = %d", __func__, source, config->channel_mask);
5012 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
5013 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
5014 /* Force channel config requested to mono if incall
5015 record is being requested for only uplink/downlink */
5016 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
5017 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5018 ret = -EINVAL;
5019 goto err_open;
5020 }
5021 }
5022
Haynes Mathew George569b7482017-05-08 14:44:27 -07005023 if (is_usb_dev && may_use_hifi_record) {
5024 /* HiFi record selects an appropriate format, channel, rate combo
5025 depending on sink capabilities*/
5026 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
5027 &config->format,
5028 &in->supported_formats[0],
5029 MAX_SUPPORTED_FORMATS,
5030 &config->channel_mask,
5031 &in->supported_channel_masks[0],
5032 MAX_SUPPORTED_CHANNEL_MASKS,
5033 &config->sample_rate,
5034 &in->supported_sample_rates[0],
5035 MAX_SUPPORTED_SAMPLE_RATES);
5036 if (ret != 0) {
5037 ret = -EINVAL;
5038 goto err_open;
5039 }
Eric Laurent74b55762017-07-09 17:04:53 -07005040 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005041 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07005042 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07005043 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
5044 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
5045 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5046 bool ret_error = false;
5047 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5048 from HAL is 8_24
5049 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5050 8_24 return error indicating supported format is 8_24
5051 *> In case of any other source requesting 24 bit or float return error
5052 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07005053
vivek mehta57ff9b52016-04-28 14:13:08 -07005054 on error flinger will retry with supported format passed
5055 */
5056 if (source != AUDIO_SOURCE_UNPROCESSED) {
5057 config->format = AUDIO_FORMAT_PCM_16_BIT;
5058 ret_error = true;
5059 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
5060 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
5061 ret_error = true;
5062 }
5063
5064 if (ret_error) {
5065 ret = -EINVAL;
5066 goto err_open;
5067 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005068 }
5069
vivek mehta57ff9b52016-04-28 14:13:08 -07005070 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07005071 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07005072
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005073 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005074 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
5075 if (config->sample_rate == 0)
5076 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5077 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5078 config->sample_rate != 8000) {
5079 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5080 ret = -EINVAL;
5081 goto err_open;
5082 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005083
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005084 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5085 config->format = AUDIO_FORMAT_PCM_16_BIT;
5086 ret = -EINVAL;
5087 goto err_open;
5088 }
5089
5090 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5091 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07005092 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005093 } else if (is_usb_dev && may_use_hifi_record) {
5094 in->usecase = USECASE_AUDIO_RECORD_HIFI;
5095 in->config = pcm_config_audio_capture;
5096 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005097 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5098 config->sample_rate,
5099 config->format,
5100 channel_count,
5101 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005102 in->config.period_size = buffer_size / frame_size;
5103 in->config.rate = config->sample_rate;
5104 in->af_period_multiplier = 1;
5105 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005106 } else {
5107 in->usecase = USECASE_AUDIO_RECORD;
5108 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08005109 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005110 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07005111#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005112 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07005113#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08005114 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005115 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08005116 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005117 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005118 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5119 config->sample_rate,
5120 config->format,
5121 channel_count,
5122 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005123 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005124 in->config.rate = config->sample_rate;
5125 in->af_period_multiplier = 1;
5126 } else {
5127 // period size is left untouched for rt mode playback
5128 in->config = pcm_config_audio_capture_rt;
5129 in->af_period_multiplier = af_period_multiplier;
5130 }
5131 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
5132 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005133 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08005134 in->usecase = USECASE_AUDIO_RECORD_MMAP;
5135 in->config = pcm_config_mmap_capture;
5136 in->stream.start = in_start;
5137 in->stream.stop = in_stop;
5138 in->stream.create_mmap_buffer = in_create_mmap_buffer;
5139 in->stream.get_mmap_position = in_get_mmap_position;
5140 in->af_period_multiplier = 1;
5141 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07005142 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07005143 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07005144 (config->sample_rate == 8000 ||
5145 config->sample_rate == 16000 ||
5146 config->sample_rate == 32000 ||
5147 config->sample_rate == 48000) &&
5148 channel_count == 1) {
5149 in->usecase = USECASE_AUDIO_RECORD_VOIP;
5150 in->config = pcm_config_audio_capture;
5151 frame_size = audio_stream_in_frame_size(&in->stream);
5152 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
5153 config->sample_rate,
5154 config->format,
5155 channel_count, false /*is_low_latency*/);
5156 in->config.period_size = buffer_size / frame_size;
5157 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
5158 in->config.rate = config->sample_rate;
5159 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005160 } else {
5161 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005162 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005163 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5164 config->sample_rate,
5165 config->format,
5166 channel_count,
5167 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005168 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005169 in->config.rate = config->sample_rate;
5170 in->af_period_multiplier = 1;
5171 }
5172 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
5173 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005174 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08005175
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005176 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07005177 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005178
Kevin Rocarda325aa22018-04-03 09:15:52 -07005179
5180 register_format(in->format, in->supported_formats);
5181 register_channel_mask(in->channel_mask, in->supported_channel_masks);
5182 register_sample_rate(in->sample_rate, in->supported_sample_rates);
5183
Andy Hungd13f0d32017-06-12 13:58:37 -07005184 in->error_log = error_log_create(
5185 ERROR_LOG_ENTRIES,
5186 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
5187
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005188 /* This stream could be for sound trigger lab,
5189 get sound trigger pcm if present */
5190 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005191
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005192 lock_input_stream(in);
5193 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5194 pthread_mutex_lock(&adev->lock);
5195 in->card_status = adev->card_status;
5196 pthread_mutex_unlock(&adev->lock);
5197 pthread_mutex_unlock(&in->lock);
5198
vivek mehta4a824772017-06-08 19:05:49 -07005199 stream_app_type_cfg_init(&in->app_type_cfg);
5200
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005201 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005202 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005203 return 0;
5204
5205err_open:
5206 free(in);
5207 *stream_in = NULL;
5208 return ret;
5209}
5210
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005211static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005212 struct audio_stream_in *stream)
5213{
Andy Hungd13f0d32017-06-12 13:58:37 -07005214 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005215 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005216
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005217 // must deregister from sndmonitor first to prevent races
5218 // between the callback and close_stream
5219 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005220 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07005221
5222 error_log_destroy(in->error_log);
5223 in->error_log = NULL;
5224
Andy Hung0dbb52b2017-08-09 13:51:38 -07005225 pthread_mutex_destroy(&in->pre_lock);
5226 pthread_mutex_destroy(&in->lock);
5227
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005228 free(stream);
5229
5230 return;
5231}
5232
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005233static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005234{
5235 return 0;
5236}
5237
Andy Hung31aca912014-03-20 17:14:59 -07005238/* verifies input and output devices and their capabilities.
5239 *
5240 * This verification is required when enabling extended bit-depth or
5241 * sampling rates, as not all qcom products support it.
5242 *
5243 * Suitable for calling only on initialization such as adev_open().
5244 * It fills the audio_device use_case_table[] array.
5245 *
5246 * Has a side-effect that it needs to configure audio routing / devices
5247 * in order to power up the devices and read the device parameters.
5248 * It does not acquire any hw device lock. Should restore the devices
5249 * back to "normal state" upon completion.
5250 */
5251static int adev_verify_devices(struct audio_device *adev)
5252{
5253 /* enumeration is a bit difficult because one really wants to pull
5254 * the use_case, device id, etc from the hidden pcm_device_table[].
5255 * In this case there are the following use cases and device ids.
5256 *
5257 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
5258 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005259 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07005260 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
5261 * [USECASE_AUDIO_RECORD] = {0, 0},
5262 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
5263 * [USECASE_VOICE_CALL] = {2, 2},
5264 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005265 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07005266 * USECASE_VOICE_CALL omitted, but possible for either input or output.
5267 */
5268
5269 /* should be the usecases enabled in adev_open_input_stream() */
5270 static const int test_in_usecases[] = {
5271 USECASE_AUDIO_RECORD,
5272 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
5273 };
5274 /* should be the usecases enabled in adev_open_output_stream()*/
5275 static const int test_out_usecases[] = {
5276 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
5277 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
5278 };
5279 static const usecase_type_t usecase_type_by_dir[] = {
5280 PCM_PLAYBACK,
5281 PCM_CAPTURE,
5282 };
5283 static const unsigned flags_by_dir[] = {
5284 PCM_OUT,
5285 PCM_IN,
5286 };
5287
5288 size_t i;
5289 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005290 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07005291 char info[512]; /* for possible debug info */
5292
5293 for (dir = 0; dir < 2; ++dir) {
5294 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
5295 const unsigned flags_dir = flags_by_dir[dir];
5296 const size_t testsize =
5297 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
5298 const int *testcases =
5299 dir ? test_in_usecases : test_out_usecases;
5300 const audio_devices_t audio_device =
5301 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
5302
5303 for (i = 0; i < testsize; ++i) {
5304 const audio_usecase_t audio_usecase = testcases[i];
5305 int device_id;
5306 snd_device_t snd_device;
5307 struct pcm_params **pparams;
5308 struct stream_out out;
5309 struct stream_in in;
5310 struct audio_usecase uc_info;
5311 int retval;
5312
5313 pparams = &adev->use_case_table[audio_usecase];
5314 pcm_params_free(*pparams); /* can accept null input */
5315 *pparams = NULL;
5316
5317 /* find the device ID for the use case (signed, for error) */
5318 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
5319 if (device_id < 0)
5320 continue;
5321
5322 /* prepare structures for device probing */
5323 memset(&uc_info, 0, sizeof(uc_info));
5324 uc_info.id = audio_usecase;
5325 uc_info.type = usecase_type;
5326 if (dir) {
5327 adev->active_input = &in;
5328 memset(&in, 0, sizeof(in));
5329 in.device = audio_device;
5330 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
5331 uc_info.stream.in = &in;
5332 } else {
5333 adev->active_input = NULL;
5334 }
5335 memset(&out, 0, sizeof(out));
5336 out.devices = audio_device; /* only field needed in select_devices */
5337 uc_info.stream.out = &out;
5338 uc_info.devices = audio_device;
5339 uc_info.in_snd_device = SND_DEVICE_NONE;
5340 uc_info.out_snd_device = SND_DEVICE_NONE;
5341 list_add_tail(&adev->usecase_list, &uc_info.list);
5342
5343 /* select device - similar to start_(in/out)put_stream() */
5344 retval = select_devices(adev, audio_usecase);
5345 if (retval >= 0) {
5346 *pparams = pcm_params_get(card_id, device_id, flags_dir);
5347#if LOG_NDEBUG == 0
5348 if (*pparams) {
5349 ALOGV("%s: (%s) card %d device %d", __func__,
5350 dir ? "input" : "output", card_id, device_id);
5351 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07005352 } else {
5353 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
5354 }
5355#endif
5356 }
5357
5358 /* deselect device - similar to stop_(in/out)put_stream() */
5359 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07005360 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07005361 /* 2. Disable the rx device */
5362 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07005363 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07005364 list_remove(&uc_info.list);
5365 }
5366 }
5367 adev->active_input = NULL; /* restore adev state */
5368 return 0;
5369}
5370
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005371static int adev_close(hw_device_t *device)
5372{
Andy Hung31aca912014-03-20 17:14:59 -07005373 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005374 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005375
5376 if (!adev)
5377 return 0;
5378
5379 pthread_mutex_lock(&adev_init_lock);
5380
5381 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005382 audio_extn_snd_mon_unregister_listener(adev);
5383 audio_extn_tfa_98xx_deinit();
jasmine cha270b7762018-03-30 15:41:33 +08005384 audio_extn_ma_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005385 audio_route_free(adev->audio_route);
5386 free(adev->snd_dev_ref_cnt);
5387 platform_deinit(adev->platform);
5388 audio_extn_extspk_deinit(adev->extspk);
5389 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005390 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005391 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
5392 pcm_params_free(adev->use_case_table[i]);
5393 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005394 if (adev->adm_deinit)
5395 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005396 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005397 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07005398 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07005399
5400 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005401
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005402 return 0;
5403}
5404
Glenn Kasten4f993392014-05-14 07:30:48 -07005405/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5406 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5407 * just that it _might_ work.
5408 */
5409static int period_size_is_plausible_for_low_latency(int period_size)
5410{
5411 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005412 case 48:
5413 case 96:
5414 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07005415 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005416 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07005417 case 240:
5418 case 320:
5419 case 480:
5420 return 1;
5421 default:
5422 return 0;
5423 }
5424}
5425
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005426static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
5427{
5428 int card;
5429 card_status_t status;
5430
5431 if (!parms)
5432 return;
5433
5434 if (parse_snd_card_status(parms, &card, &status) < 0)
5435 return;
5436
5437 pthread_mutex_lock(&adev->lock);
5438 bool valid_cb = (card == adev->snd_card);
5439 if (valid_cb) {
5440 if (adev->card_status != status) {
5441 adev->card_status = status;
5442 platform_snd_card_update(adev->platform, status);
5443 }
5444 }
5445 pthread_mutex_unlock(&adev->lock);
5446 return;
5447}
5448
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005449/* out and adev lock held */
5450static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
5451{
5452 struct audio_usecase *uc_info;
5453 float left_p;
5454 float right_p;
5455 audio_devices_t devices;
5456
5457 uc_info = get_usecase_from_list(adev, out->usecase);
5458 if (uc_info == NULL) {
5459 ALOGE("%s: Could not find the usecase (%d) in the list",
5460 __func__, out->usecase);
5461 return -EINVAL;
5462 }
5463
5464 ALOGD("%s: enter: usecase(%d: %s)", __func__,
5465 out->usecase, use_case_table[out->usecase]);
5466
5467 if (restore) {
5468 // restore A2DP device for active usecases and unmute if required
5469 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
5470 !is_a2dp_device(uc_info->out_snd_device)) {
5471 ALOGD("%s: restoring A2DP and unmuting stream", __func__);
5472 select_devices(adev, uc_info->id);
5473 pthread_mutex_lock(&out->compr_mute_lock);
5474 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5475 (out->a2dp_compress_mute)) {
5476 out->a2dp_compress_mute = false;
5477 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5478 }
5479 pthread_mutex_unlock(&out->compr_mute_lock);
5480 }
5481 } else {
5482 // mute compress stream if suspended
5483 pthread_mutex_lock(&out->compr_mute_lock);
5484 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5485 (!out->a2dp_compress_mute)) {
5486 if (!out->standby) {
5487 ALOGD("%s: selecting speaker and muting stream", __func__);
5488 devices = out->devices;
5489 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
5490 left_p = out->volume_l;
5491 right_p = out->volume_r;
5492 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5493 compress_pause(out->compr);
5494 set_compr_volume(&out->stream, 0.0f, 0.0f);
5495 out->a2dp_compress_mute = true;
5496 select_devices(adev, out->usecase);
5497 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5498 compress_resume(out->compr);
5499 out->devices = devices;
5500 out->volume_l = left_p;
5501 out->volume_r = right_p;
5502 }
5503 }
5504 pthread_mutex_unlock(&out->compr_mute_lock);
5505 }
5506 ALOGV("%s: exit", __func__);
5507 return 0;
5508}
5509
5510int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
5511{
5512 int ret = 0;
5513
5514 lock_output_stream(out);
5515 pthread_mutex_lock(&adev->lock);
5516
5517 ret = check_a2dp_restore_l(adev, out, restore);
5518
5519 pthread_mutex_unlock(&adev->lock);
5520 pthread_mutex_unlock(&out->lock);
5521 return ret;
5522}
5523
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005524static int adev_open(const hw_module_t *module, const char *name,
5525 hw_device_t **device)
5526{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005527 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005528
Eric Laurent2bafff12016-03-17 12:17:23 -07005529 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005530 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005531 pthread_mutex_lock(&adev_init_lock);
5532 if (audio_device_ref_count != 0) {
5533 *device = &adev->device.common;
5534 audio_device_ref_count++;
5535 ALOGV("%s: returning existing instance of adev", __func__);
5536 ALOGV("%s: exit", __func__);
5537 pthread_mutex_unlock(&adev_init_lock);
5538 return 0;
5539 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005540 adev = calloc(1, sizeof(struct audio_device));
5541
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005542 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5543
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005544 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5545 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5546 adev->device.common.module = (struct hw_module_t *)module;
5547 adev->device.common.close = adev_close;
5548
5549 adev->device.init_check = adev_init_check;
5550 adev->device.set_voice_volume = adev_set_voice_volume;
5551 adev->device.set_master_volume = adev_set_master_volume;
5552 adev->device.get_master_volume = adev_get_master_volume;
5553 adev->device.set_master_mute = adev_set_master_mute;
5554 adev->device.get_master_mute = adev_get_master_mute;
5555 adev->device.set_mode = adev_set_mode;
5556 adev->device.set_mic_mute = adev_set_mic_mute;
5557 adev->device.get_mic_mute = adev_get_mic_mute;
5558 adev->device.set_parameters = adev_set_parameters;
5559 adev->device.get_parameters = adev_get_parameters;
5560 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5561 adev->device.open_output_stream = adev_open_output_stream;
5562 adev->device.close_output_stream = adev_close_output_stream;
5563 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005564
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005565 adev->device.close_input_stream = adev_close_input_stream;
5566 adev->device.dump = adev_dump;
jiabin8962a4d2018-03-19 18:21:24 -07005567 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005568
5569 /* Set the default route before the PCM stream is opened */
5570 pthread_mutex_lock(&adev->lock);
5571 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005572 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005573 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005574 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005575 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005576 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005577 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005578 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005579 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005580 pthread_mutex_unlock(&adev->lock);
5581
5582 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005583 adev->platform = platform_init(adev);
5584 if (!adev->platform) {
5585 free(adev->snd_dev_ref_cnt);
5586 free(adev);
5587 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5588 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005589 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005590 return -EINVAL;
5591 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05005592 adev->extspk = audio_extn_extspk_init(adev);
5593
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005594 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5595 if (adev->visualizer_lib == NULL) {
5596 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5597 } else {
5598 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5599 adev->visualizer_start_output =
5600 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5601 "visualizer_hal_start_output");
5602 adev->visualizer_stop_output =
5603 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5604 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07005605 }
5606
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005607 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5608 if (adev->offload_effects_lib == NULL) {
5609 ALOGW("%s: DLOPEN failed for %s", __func__,
5610 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5611 } else {
5612 ALOGV("%s: DLOPEN successful for %s", __func__,
5613 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5614 adev->offload_effects_start_output =
5615 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5616 "offload_effects_bundle_hal_start_output");
5617 adev->offload_effects_stop_output =
5618 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5619 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07005620 }
5621
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005622 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5623 if (adev->adm_lib == NULL) {
5624 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5625 } else {
5626 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5627 adev->adm_init = (adm_init_t)
5628 dlsym(adev->adm_lib, "adm_init");
5629 adev->adm_deinit = (adm_deinit_t)
5630 dlsym(adev->adm_lib, "adm_deinit");
5631 adev->adm_register_input_stream = (adm_register_input_stream_t)
5632 dlsym(adev->adm_lib, "adm_register_input_stream");
5633 adev->adm_register_output_stream = (adm_register_output_stream_t)
5634 dlsym(adev->adm_lib, "adm_register_output_stream");
5635 adev->adm_deregister_stream = (adm_deregister_stream_t)
5636 dlsym(adev->adm_lib, "adm_deregister_stream");
5637 adev->adm_request_focus = (adm_request_focus_t)
5638 dlsym(adev->adm_lib, "adm_request_focus");
5639 adev->adm_abandon_focus = (adm_abandon_focus_t)
5640 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08005641 adev->adm_set_config = (adm_set_config_t)
5642 dlsym(adev->adm_lib, "adm_set_config");
5643 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5644 dlsym(adev->adm_lib, "adm_request_focus_v2");
5645 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5646 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5647 adev->adm_on_routing_change = (adm_on_routing_change_t)
5648 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005649 }
5650
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005651 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005652 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005653
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005654 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005655
Andy Hung31aca912014-03-20 17:14:59 -07005656 if (k_enable_extended_precision)
5657 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005658
Glenn Kasten4f993392014-05-14 07:30:48 -07005659 char value[PROPERTY_VALUE_MAX];
5660 int trial;
5661 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5662 trial = atoi(value);
5663 if (period_size_is_plausible_for_low_latency(trial)) {
5664 pcm_config_low_latency.period_size = trial;
5665 pcm_config_low_latency.start_threshold = trial / 4;
5666 pcm_config_low_latency.avail_min = trial / 4;
5667 configured_low_latency_capture_period_size = trial;
5668 }
5669 }
5670 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5671 trial = atoi(value);
5672 if (period_size_is_plausible_for_low_latency(trial)) {
5673 configured_low_latency_capture_period_size = trial;
5674 }
5675 }
5676
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005677 // commented as full set of app type cfg is sent from platform
5678 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005679 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005680
5681 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5682 af_period_multiplier = atoi(value);
5683 if (af_period_multiplier < 0) {
5684 af_period_multiplier = 2;
5685 } else if (af_period_multiplier > 4) {
5686 af_period_multiplier = 4;
5687 }
5688 ALOGV("new period_multiplier = %d", af_period_multiplier);
5689 }
5690
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005691 audio_extn_tfa_98xx_init(adev);
jasmine cha270b7762018-03-30 15:41:33 +08005692 audio_extn_ma_init(adev->platform);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005693
vivek mehta1a9b7c02015-06-25 11:49:38 -07005694 pthread_mutex_unlock(&adev_init_lock);
5695
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005696 if (adev->adm_init)
5697 adev->adm_data = adev->adm_init();
5698
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005699 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005700 audio_extn_snd_mon_init();
5701 pthread_mutex_lock(&adev->lock);
5702 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
5703 adev->card_status = CARD_STATUS_ONLINE;
5704 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005705 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005706
Eric Laurent2bafff12016-03-17 12:17:23 -07005707 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005708 return 0;
5709}
5710
5711static struct hw_module_methods_t hal_module_methods = {
5712 .open = adev_open,
5713};
5714
5715struct audio_module HAL_MODULE_INFO_SYM = {
5716 .common = {
5717 .tag = HARDWARE_MODULE_TAG,
5718 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5719 .hal_api_version = HARDWARE_HAL_API_VERSION,
5720 .id = AUDIO_HARDWARE_MODULE_ID,
5721 .name = "QCOM Audio HAL",
5722 .author = "Code Aurora Forum",
5723 .methods = &hal_module_methods,
5724 },
5725};