blob: f88dcdd110a1241fc756896f8e5a5d47050ba4a2 [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
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800681 if (is_a2dp_device(snd_device) &&
682 (audio_extn_a2dp_start_playback() < 0)) {
683 ALOGE("%s: failed to configure A2DP control path", __func__);
684 goto on_error;
685 }
686
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700687 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800688 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
juyuchen1d05ba32018-03-31 16:03:51 +0800689 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700690 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
691 audio_extn_spkr_prot_is_enabled()) {
Aniket Kumar Lata9d6679a2018-04-11 18:13:23 -0700692 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800693 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700694 }
695 if (audio_extn_spkr_prot_start_processing(snd_device)) {
696 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800697 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700698 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700699 } else if (platform_can_split_snd_device(snd_device,
700 &num_devices,
701 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700702 for (i = 0; i < num_devices; i++) {
703 enable_snd_device(adev, new_snd_devices[i]);
704 }
vivek mehtab6506412015-08-07 16:55:17 -0700705 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700706 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800707 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
708 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
709 ALOGE(" %s: Invalid sound device returned", __func__);
710 goto on_error;
711 }
Ed Tam70b5c142016-03-21 19:14:29 -0700712
Eric Laurent2e140aa2016-06-30 17:14:46 -0700713 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800714 audio_route_apply_and_update_path(adev->audio_route, device_name);
715 }
716on_success:
717 adev->snd_dev_ref_cnt[snd_device]++;
718 ret_val = 0;
719on_error:
720 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800721}
722
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800723int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700724 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800725{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700726 int i, num_devices = 0;
727 snd_device_t new_snd_devices[2];
728
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800729 if (snd_device < SND_DEVICE_MIN ||
730 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800731 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800732 return -EINVAL;
733 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700734 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
735 ALOGE("%s: device ref cnt is already 0", __func__);
736 return -EINVAL;
737 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800738 audio_extn_tfa_98xx_disable_speaker(snd_device);
739
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700740 adev->snd_dev_ref_cnt[snd_device]--;
741 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800742 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800743
744 if (is_a2dp_device(snd_device))
745 audio_extn_a2dp_stop_playback();
746
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700747 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800748 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700749 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700750 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
751 audio_extn_spkr_prot_is_enabled()) {
752 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700753
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700754 // FIXME b/65363602: bullhead is the only Nexus with audio_extn_spkr_prot_is_enabled()
755 // and does not use speaker swap. As this code causes a problem with device enable ref
756 // counting we remove it for now.
vivek mehtae59cfb22017-06-16 15:57:11 -0700757 // when speaker device is disabled, reset swap.
758 // will be renabled on usecase start
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700759 // platform_set_swap_channels(adev, false);
vivek mehtae59cfb22017-06-16 15:57:11 -0700760
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700761 } else if (platform_can_split_snd_device(snd_device,
762 &num_devices,
763 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700764 for (i = 0; i < num_devices; i++) {
765 disable_snd_device(adev, new_snd_devices[i]);
766 }
vivek mehtab6506412015-08-07 16:55:17 -0700767 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700768 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800769 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
770 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
771 ALOGE(" %s: Invalid sound device returned", __func__);
772 return -EINVAL;
773 }
774
Eric Laurent2e140aa2016-06-30 17:14:46 -0700775 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800776 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700777 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700778 audio_extn_sound_trigger_update_device_status(snd_device,
779 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700780 }
vivek mehtab6506412015-08-07 16:55:17 -0700781
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800782 return 0;
783}
784
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700785/*
786 legend:
787 uc - existing usecase
788 new_uc - new usecase
789 d1, d11, d2 - SND_DEVICE enums
790 a1, a2 - corresponding ANDROID device enums
791 B, B1, B2 - backend strings
792
793case 1
794 uc->dev d1 (a1) B1
795 new_uc->dev d1 (a1), d2 (a2) B1, B2
796
797 resolution: disable and enable uc->dev on d1
798
799case 2
800 uc->dev d1 (a1) B1
801 new_uc->dev d11 (a1) B1
802
803 resolution: need to switch uc since d1 and d11 are related
804 (e.g. speaker and voice-speaker)
805 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
806
807case 3
808 uc->dev d1 (a1) B1
809 new_uc->dev d2 (a2) B2
810
811 resolution: no need to switch uc
812
813case 4
814 uc->dev d1 (a1) B
815 new_uc->dev d2 (a2) B
816
817 resolution: disable enable uc-dev on d2 since backends match
818 we cannot enable two streams on two different devices if they
819 share the same backend. e.g. if offload is on speaker device using
820 QUAD_MI2S backend and a low-latency stream is started on voice-handset
821 using the same backend, offload must also be switched to voice-handset.
822
823case 5
824 uc->dev d1 (a1) B
825 new_uc->dev d1 (a1), d2 (a2) B
826
827 resolution: disable enable uc-dev on d2 since backends match
828 we cannot enable two streams on two different devices if they
829 share the same backend.
830
831case 6
832 uc->dev d1 a1 B1
833 new_uc->dev d2 a1 B2
834
835 resolution: no need to switch
836
837case 7
838
839 uc->dev d1 (a1), d2 (a2) B1, B2
840 new_uc->dev d1 B1
841
842 resolution: no need to switch
843
844*/
845static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
846 struct audio_usecase *new_uc,
847 snd_device_t new_snd_device)
848{
849 audio_devices_t a1 = uc->stream.out->devices;
850 audio_devices_t a2 = new_uc->stream.out->devices;
851
852 snd_device_t d1 = uc->out_snd_device;
853 snd_device_t d2 = new_snd_device;
854
855 // Treat as a special case when a1 and a2 are not disjoint
856 if ((a1 != a2) && (a1 & a2)) {
857 snd_device_t d3[2];
858 int num_devices = 0;
859 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
860 &num_devices,
861 d3);
862 if (ret < 0) {
863 if (ret != -ENOSYS) {
864 ALOGW("%s failed to split snd_device %d",
865 __func__,
866 popcount(a1) > 1 ? d1 : d2);
867 }
868 goto end;
869 }
870
871 // NB: case 7 is hypothetical and isn't a practical usecase yet.
872 // But if it does happen, we need to give priority to d2 if
873 // the combo devices active on the existing usecase share a backend.
874 // This is because we cannot have a usecase active on a combo device
875 // and a new usecase requests one device in this combo pair.
876 if (platform_check_backends_match(d3[0], d3[1])) {
877 return d2; // case 5
878 } else {
879 return d1; // case 1
880 }
881 } else {
882 if (platform_check_backends_match(d1, d2)) {
883 return d2; // case 2, 4
884 } else {
885 return d1; // case 6, 3
886 }
887 }
888
889end:
890 return d2; // return whatever was calculated before.
891}
892
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700893static void check_and_route_playback_usecases(struct audio_device *adev,
894 struct audio_usecase *uc_info,
895 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700896{
897 struct listnode *node;
898 struct audio_usecase *usecase;
899 bool switch_device[AUDIO_USECASE_MAX];
900 int i, num_uc_to_switch = 0;
901
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700902 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
903 uc_info,
904 snd_device);
David Linee3fe402017-03-13 10:00:42 -0700905
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800906 /* For a2dp device reconfigure all active sessions
907 * with new AFE encoder format based on a2dp state
908 */
909 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
910 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
911 audio_extn_a2dp_is_force_device_switch()) {
912 force_routing = true;
913 }
914
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700915 /*
916 * This function is to make sure that all the usecases that are active on
917 * the hardware codec backend are always routed to any one device that is
918 * handled by the hardware codec.
919 * For example, if low-latency and deep-buffer usecases are currently active
920 * on speaker and out_set_parameters(headset) is received on low-latency
921 * output, then we have to make sure deep-buffer is also switched to headset,
922 * because of the limitation that both the devices cannot be enabled
923 * at the same time as they share the same backend.
924 */
925 /* Disable all the usecases on the shared backend other than the
926 specified usecase */
927 for (i = 0; i < AUDIO_USECASE_MAX; i++)
928 switch_device[i] = false;
929
930 list_for_each(node, &adev->usecase_list) {
931 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700932 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
933 continue;
934
935 if (force_routing ||
936 (usecase->out_snd_device != snd_device &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -0700937 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
938 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700939 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700940 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
941 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700942 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700943 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700944 switch_device[usecase->id] = true;
945 num_uc_to_switch++;
946 }
947 }
948
949 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700950 list_for_each(node, &adev->usecase_list) {
951 usecase = node_to_item(node, struct audio_usecase, list);
952 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700953 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900954 }
955 }
956
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700957 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900958 list_for_each(node, &adev->usecase_list) {
959 usecase = node_to_item(node, struct audio_usecase, list);
960 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700961 d_device = derive_playback_snd_device(usecase, uc_info,
962 snd_device);
963 enable_snd_device(adev, d_device);
964 /* Update the out_snd_device before enabling the audio route */
965 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700966 }
967 }
968
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700969 /* Re-route all the usecases on the shared backend other than the
970 specified usecase to new snd devices */
971 list_for_each(node, &adev->usecase_list) {
972 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700973 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700974 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700975 }
976 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700977 }
978}
979
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700980static void check_and_route_capture_usecases(struct audio_device *adev,
981 struct audio_usecase *uc_info,
982 snd_device_t snd_device)
983{
984 struct listnode *node;
985 struct audio_usecase *usecase;
986 bool switch_device[AUDIO_USECASE_MAX];
987 int i, num_uc_to_switch = 0;
988
vivek mehta4ed66e62016-04-15 23:33:34 -0700989 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
990
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700991 /*
992 * This function is to make sure that all the active capture usecases
993 * are always routed to the same input sound device.
994 * For example, if audio-record and voice-call usecases are currently
995 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
996 * is received for voice call then we have to make sure that audio-record
997 * usecase is also switched to earpiece i.e. voice-dmic-ef,
998 * because of the limitation that two devices cannot be enabled
999 * at the same time if they share the same backend.
1000 */
1001 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1002 switch_device[i] = false;
1003
1004 list_for_each(node, &adev->usecase_list) {
1005 usecase = node_to_item(node, struct audio_usecase, list);
1006 if (usecase->type != PCM_PLAYBACK &&
1007 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -07001008 usecase->in_snd_device != snd_device &&
1009 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001010 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1011 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001012 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001013 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001014 switch_device[usecase->id] = true;
1015 num_uc_to_switch++;
1016 }
1017 }
1018
1019 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001020 list_for_each(node, &adev->usecase_list) {
1021 usecase = node_to_item(node, struct audio_usecase, list);
1022 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001023 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001024 }
1025 }
1026
1027 list_for_each(node, &adev->usecase_list) {
1028 usecase = node_to_item(node, struct audio_usecase, list);
1029 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001030 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001031 }
1032 }
1033
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001034 /* Re-route all the usecases on the shared backend other than the
1035 specified usecase to new snd devices */
1036 list_for_each(node, &adev->usecase_list) {
1037 usecase = node_to_item(node, struct audio_usecase, list);
1038 /* Update the in_snd_device only before enabling the audio route */
1039 if (switch_device[usecase->id] ) {
1040 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001041 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001042 }
1043 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001044 }
1045}
1046
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001047/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001048static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001049{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001050 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001051 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001052
1053 switch (channels) {
1054 /*
1055 * Do not handle stereo output in Multi-channel cases
1056 * Stereo case is handled in normal playback path
1057 */
1058 case 6:
1059 ALOGV("%s: HDMI supports 5.1", __func__);
1060 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1061 break;
1062 case 8:
1063 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
1064 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1065 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
1066 break;
1067 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001068 ALOGE("HDMI does not support multi channel playback");
1069 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001070 break;
1071 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001072 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001073}
1074
Andy Hung18859412017-08-09 11:47:21 -07001075static ssize_t read_usb_sup_sample_rates(bool is_playback,
1076 uint32_t *supported_sample_rates,
1077 uint32_t max_rates)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001078{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001079 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1080 supported_sample_rates,
1081 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001082#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001083 for (ssize_t i=0; i<count; i++) {
1084 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1085 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001086 }
1087#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001088 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001089}
1090
Haynes Mathew George569b7482017-05-08 14:44:27 -07001091static int read_usb_sup_channel_masks(bool is_playback,
1092 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001093 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001094{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001095 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001096 int channel_count;
1097 uint32_t num_masks = 0;
1098 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1099 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001100 }
Eric Laurent74b55762017-07-09 17:04:53 -07001101 if (is_playback) {
Andy Hung6c1afb12017-12-22 11:34:41 -08001102 // start from 2 channels as framework currently doesn't support mono.
1103 // TODO: consider only supporting channel index masks beyond stereo here.
1104 for (channel_count = FCC_2;
1105 channel_count <= channels && num_masks < max_masks;
1106 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001107 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1108 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001109 for (channel_count = FCC_2;
1110 channel_count <= channels && num_masks < max_masks;
1111 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001112 supported_channel_masks[num_masks++] =
1113 audio_channel_mask_for_index_assignment_from_count(channel_count);
1114 }
1115 } else {
1116 // For capture we report all supported channel masks from 1 channel up.
1117 channel_count = MIN_CHANNEL_COUNT;
1118 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1119 // indexed mask
1120 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1121 supported_channel_masks[num_masks++] =
1122 audio_channel_in_mask_from_count(channel_count);
1123 }
1124 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001125#ifdef NDEBUG
1126 for (size_t i = 0; i < num_masks; ++i) {
1127 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1128 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
1129 }
1130#endif
Eric Laurent74b55762017-07-09 17:04:53 -07001131 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001132}
1133
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001134static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001135 audio_format_t *supported_formats,
1136 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001137{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001138 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001139 switch (bitwidth) {
1140 case 24:
1141 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001142 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001143 break;
1144 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001145 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001146 break;
1147 case 16:
1148 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001149 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001150 break;
1151 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001152 ALOGV("%s: %s supported format %d", __func__,
1153 is_playback ? "P" : "C", bitwidth);
1154 return 1;
1155}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001156
Haynes Mathew George569b7482017-05-08 14:44:27 -07001157static int read_usb_sup_params_and_compare(bool is_playback,
1158 audio_format_t *format,
1159 audio_format_t *supported_formats,
1160 uint32_t max_formats,
1161 audio_channel_mask_t *mask,
1162 audio_channel_mask_t *supported_channel_masks,
1163 uint32_t max_masks,
1164 uint32_t *rate,
1165 uint32_t *supported_sample_rates,
1166 uint32_t max_rates) {
1167 int ret = 0;
1168 int num_formats;
1169 int num_masks;
1170 int num_rates;
1171 int i;
1172
1173 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1174 max_formats);
1175 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1176 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001177
Haynes Mathew George569b7482017-05-08 14:44:27 -07001178 num_rates = read_usb_sup_sample_rates(is_playback,
1179 supported_sample_rates, max_rates);
1180
1181#define LUT(table, len, what, dflt) \
1182 for (i=0; i<len && (table[i] != what); i++); \
1183 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1184
1185 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1186 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1187 LUT(supported_sample_rates, num_rates, *rate, 0);
1188
1189#undef LUT
1190 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001191}
1192
Andy Hungd9653bd2017-08-01 19:31:39 -07001193static bool is_usb_ready(struct audio_device *adev, bool is_playback)
1194{
1195 // Check if usb is ready.
1196 // The usb device may have been removed quickly after insertion and hence
1197 // no longer available. This will show up as empty channel masks, or rates.
1198
1199 pthread_mutex_lock(&adev->lock);
1200 uint32_t supported_sample_rate;
1201
1202 // we consider usb ready if we can fetch at least one sample rate.
1203 const bool ready = read_usb_sup_sample_rates(
1204 is_playback, &supported_sample_rate, 1 /* max_rates */) > 0;
1205 pthread_mutex_unlock(&adev->lock);
1206 return ready;
1207}
1208
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001209static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1210{
1211 struct audio_usecase *usecase;
1212 struct listnode *node;
1213
1214 list_for_each(node, &adev->usecase_list) {
1215 usecase = node_to_item(node, struct audio_usecase, list);
1216 if (usecase->type == VOICE_CALL) {
1217 ALOGV("%s: usecase id %d", __func__, usecase->id);
1218 return usecase->id;
1219 }
1220 }
1221 return USECASE_INVALID;
1222}
1223
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001224struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1225 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001226{
1227 struct audio_usecase *usecase;
1228 struct listnode *node;
1229
1230 list_for_each(node, &adev->usecase_list) {
1231 usecase = node_to_item(node, struct audio_usecase, list);
1232 if (usecase->id == uc_id)
1233 return usecase;
1234 }
1235 return NULL;
1236}
1237
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001238static bool force_device_switch(struct audio_usecase *usecase)
1239{
1240 if (usecase->stream.out == NULL) {
1241 ALOGE("%s: stream.out is NULL", __func__);
1242 return false;
1243 }
1244
1245 // Force all A2DP output devices to reconfigure for proper AFE encode format
1246 // Also handle a case where in earlier A2DP start failed as A2DP stream was
1247 // in suspended state, hence try to trigger a retry when we again get a routing request.
1248 if ((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
1249 audio_extn_a2dp_is_force_device_switch()) {
1250 ALOGD("%s: Force A2DP device switch to update new encoder config", __func__);
1251 return true;
1252 }
1253
1254 return false;
1255}
1256
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001257int select_devices(struct audio_device *adev,
1258 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001259{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001260 snd_device_t out_snd_device = SND_DEVICE_NONE;
1261 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001262 struct audio_usecase *usecase = NULL;
1263 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001264 struct audio_usecase *hfp_usecase = NULL;
1265 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001266 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001267 int status = 0;
Eric Laurentf4520b02017-09-20 18:31:58 -07001268 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1269 USECASE_AUDIO_PLAYBACK_VOIP);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001270
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001271 usecase = get_usecase_from_list(adev, uc_id);
1272 if (usecase == NULL) {
1273 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1274 return -EINVAL;
1275 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001276
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001277 if ((usecase->type == VOICE_CALL) ||
1278 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001279 out_snd_device = platform_get_output_snd_device(adev->platform,
1280 usecase->stream.out->devices);
1281 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001282 usecase->devices = usecase->stream.out->devices;
1283 } else {
1284 /*
1285 * If the voice call is active, use the sound devices of voice call usecase
1286 * so that it would not result any device switch. All the usecases will
1287 * be switched to new device when select_devices() is called for voice call
1288 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001289 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001290 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001291 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001292 vc_usecase = get_usecase_from_list(adev,
1293 get_voice_usecase_id_from_list(adev));
1294 if ((vc_usecase != NULL) &&
1295 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1296 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001297 in_snd_device = vc_usecase->in_snd_device;
1298 out_snd_device = vc_usecase->out_snd_device;
1299 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001300 } else if (audio_extn_hfp_is_active(adev)) {
1301 hfp_ucid = audio_extn_hfp_get_usecase();
1302 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1303 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1304 in_snd_device = hfp_usecase->in_snd_device;
1305 out_snd_device = hfp_usecase->out_snd_device;
1306 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001307 }
1308 if (usecase->type == PCM_PLAYBACK) {
1309 usecase->devices = usecase->stream.out->devices;
1310 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001311 if (out_snd_device == SND_DEVICE_NONE) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001312 struct stream_out *voip_out = adev->primary_output;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001313
Eric Laurentb23d5282013-05-14 15:27:20 -07001314 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001315 usecase->stream.out->devices);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001316
1317 if (voip_usecase)
1318 voip_out = voip_usecase->stream.out;
1319
1320 if (usecase->stream.out == voip_out &&
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001321 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001322 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001323 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001324 select_devices(adev, adev->active_input->usecase);
1325 }
1326 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001327 } else if (usecase->type == PCM_CAPTURE) {
1328 usecase->devices = usecase->stream.in->device;
1329 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001330 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001331 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001332 if (adev->active_input &&
1333 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1334 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001335
1336 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1337 USECASE_AUDIO_PLAYBACK_VOIP);
1338
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001339 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001340 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1341 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001342 } else if (voip_usecase) {
1343 out_device = voip_usecase->stream.out->devices;
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001344 } else if (adev->primary_output) {
1345 out_device = adev->primary_output->devices;
1346 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001347 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001348 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001349 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001350 }
1351 }
1352
1353 if (out_snd_device == usecase->out_snd_device &&
1354 in_snd_device == usecase->in_snd_device) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001355 if (!force_device_switch(usecase))
1356 return 0;
1357 }
1358
1359 if (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready()) {
1360 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1361 return 0;
1362 }
1363
1364 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP) &&
1365 (!audio_extn_a2dp_is_ready())) {
1366 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
1367 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001368 }
1369
Eric Laurent2bafff12016-03-17 12:17:23 -07001370 if (out_snd_device != SND_DEVICE_NONE &&
1371 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1372 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1373 __func__,
1374 use_case_table[uc_id],
1375 adev->last_logged_snd_device[uc_id][0],
1376 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1377 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1378 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1379 -1,
1380 out_snd_device,
1381 platform_get_snd_device_name(out_snd_device),
1382 platform_get_snd_device_acdb_id(out_snd_device));
1383 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1384 }
1385 if (in_snd_device != SND_DEVICE_NONE &&
1386 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1387 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1388 __func__,
1389 use_case_table[uc_id],
1390 adev->last_logged_snd_device[uc_id][1],
1391 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1392 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1393 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1394 -1,
1395 in_snd_device,
1396 platform_get_snd_device_name(in_snd_device),
1397 platform_get_snd_device_acdb_id(in_snd_device));
1398 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1399 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001400
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001401 /*
1402 * Limitation: While in call, to do a device switch we need to disable
1403 * and enable both RX and TX devices though one of them is same as current
1404 * device.
1405 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001406 if ((usecase->type == VOICE_CALL) &&
1407 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1408 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001409 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001410 /* Disable sidetone only if voice call already exists */
1411 if (voice_is_call_state_active(adev))
1412 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001413 }
1414
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001415 /* Disable current sound devices */
1416 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001417 disable_audio_route(adev, usecase);
1418 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001419 }
1420
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001421 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001422 disable_audio_route(adev, usecase);
1423 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001424 }
1425
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001426 /* Applicable only on the targets that has external modem.
1427 * New device information should be sent to modem before enabling
1428 * the devices to reduce in-call device switch time.
1429 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001430 if ((usecase->type == VOICE_CALL) &&
1431 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1432 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001433 status = platform_switch_voice_call_enable_device_config(adev->platform,
1434 out_snd_device,
1435 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001436 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001437
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001438 /* Enable new sound devices */
1439 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001440 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001441 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) ||
1442 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001443 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001444 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001445 }
1446
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001447 if (in_snd_device != SND_DEVICE_NONE) {
1448 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001449 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001450 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001451
Eric Laurentb23d5282013-05-14 15:27:20 -07001452 if (usecase->type == VOICE_CALL)
1453 status = platform_switch_voice_call_device_post(adev->platform,
1454 out_snd_device,
1455 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001456
sangwoo170731f2013-06-08 15:36:36 +09001457 usecase->in_snd_device = in_snd_device;
1458 usecase->out_snd_device = out_snd_device;
1459
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001460 audio_extn_tfa_98xx_set_mode();
1461
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001462 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001463
jasmine cha270b7762018-03-30 15:41:33 +08001464 audio_extn_ma_set_device(adev, usecase);
1465
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001466 /* Applicable only on the targets that has external modem.
1467 * Enable device command should be sent to modem only after
1468 * enabling voice call mixer controls
1469 */
vivek mehta765eb642015-08-07 19:46:06 -07001470 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001471 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1472 out_snd_device,
1473 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001474 /* Enable sidetone only if voice call already exists */
1475 if (voice_is_call_state_active(adev))
1476 voice_set_sidetone(adev, out_snd_device, true);
1477 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001478
Eric Laurentf4520b02017-09-20 18:31:58 -07001479 if (usecase == voip_usecase) {
1480 struct stream_out *voip_out = voip_usecase->stream.out;
1481 audio_extn_utils_send_app_type_gain(adev,
1482 voip_out->app_type_cfg.app_type,
1483 &voip_out->app_type_cfg.gain[0]);
1484 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001485 return status;
1486}
1487
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001488static int stop_input_stream(struct stream_in *in)
1489{
1490 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001491 struct audio_usecase *uc_info;
1492 struct audio_device *adev = in->dev;
1493
Eric Laurent994a6932013-07-17 11:51:42 -07001494 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001495 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001496
1497 if (adev->active_input) {
1498 if (adev->active_input->usecase == in->usecase) {
1499 adev->active_input = NULL;
1500 } else {
1501 ALOGW("%s adev->active_input->usecase %s, v/s in->usecase %s",
1502 __func__,
1503 use_case_table[adev->active_input->usecase],
1504 use_case_table[in->usecase]);
1505 }
1506 }
1507
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001508 uc_info = get_usecase_from_list(adev, in->usecase);
1509 if (uc_info == NULL) {
1510 ALOGE("%s: Could not find the usecase (%d) in the list",
1511 __func__, in->usecase);
1512 return -EINVAL;
1513 }
1514
vivek mehta781065c2017-04-04 12:55:01 -07001515 /* Close in-call recording streams */
1516 voice_check_and_stop_incall_rec_usecase(adev, in);
1517
Eric Laurent150dbfe2013-02-27 14:31:02 -08001518 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001519 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001520
1521 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001522 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001523
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001524 list_remove(&uc_info->list);
1525 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001526
Eric Laurent994a6932013-07-17 11:51:42 -07001527 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001528 return ret;
1529}
1530
1531int start_input_stream(struct stream_in *in)
1532{
1533 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001534 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001535 struct audio_usecase *uc_info;
1536 struct audio_device *adev = in->dev;
1537
Eric Laurent994a6932013-07-17 11:51:42 -07001538 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001539
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001540 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1541 return -EIO;
1542
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001543 if (in->card_status == CARD_STATUS_OFFLINE ||
1544 adev->card_status == CARD_STATUS_OFFLINE) {
1545 ALOGW("in->card_status or adev->card_status offline, try again");
1546 ret = -EAGAIN;
1547 goto error_config;
1548 }
1549
vivek mehta781065c2017-04-04 12:55:01 -07001550 /* Check if source matches incall recording usecase criteria */
1551 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1552 if (ret)
1553 goto error_config;
1554 else
1555 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1556
Eric Laurentb23d5282013-05-14 15:27:20 -07001557 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001558 if (in->pcm_device_id < 0) {
1559 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1560 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001561 ret = -EINVAL;
1562 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001563 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001564
1565 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001566 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1567 uc_info->id = in->usecase;
1568 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001569 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001570 uc_info->devices = in->device;
1571 uc_info->in_snd_device = SND_DEVICE_NONE;
1572 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001573
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001574 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001575
Wei Wangf4837d52017-11-21 14:51:20 -08001576 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001577 audio_extn_perf_lock_acquire();
1578
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001579 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001580
Eric Laurent0e46adf2016-12-16 12:49:24 -08001581 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001582 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001583 ALOGE("%s: pcm stream not ready", __func__);
1584 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001585 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001586 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001587 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001588 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1589 goto error_open;
1590 }
1591 } else {
1592 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1593 unsigned int pcm_open_retry_count = 0;
1594
1595 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1596 flags |= PCM_MMAP | PCM_NOIRQ;
1597 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1598 } else if (in->realtime) {
1599 flags |= PCM_MMAP | PCM_NOIRQ;
1600 }
1601
1602 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1603 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1604
1605 while (1) {
1606 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1607 flags, &in->config);
1608 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1609 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1610 if (in->pcm != NULL) {
1611 pcm_close(in->pcm);
1612 in->pcm = NULL;
1613 }
1614 if (pcm_open_retry_count-- == 0) {
1615 ret = -EIO;
1616 goto error_open;
1617 }
1618 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1619 continue;
1620 }
1621 break;
1622 }
1623
1624 ALOGV("%s: pcm_prepare", __func__);
1625 ret = pcm_prepare(in->pcm);
1626 if (ret < 0) {
1627 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001628 pcm_close(in->pcm);
1629 in->pcm = NULL;
1630 goto error_open;
1631 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001632 if (in->realtime) {
1633 ret = pcm_start(in->pcm);
1634 if (ret < 0) {
1635 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1636 pcm_close(in->pcm);
1637 in->pcm = NULL;
1638 goto error_open;
1639 }
1640 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001641 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001642 register_in_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001643 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001644 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001645 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001646
Eric Laurent0e46adf2016-12-16 12:49:24 -08001647 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001648
1649error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001650 stop_input_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001651 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001652 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001653
1654error_config:
1655 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001656 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001657 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001658}
1659
Eric Laurenta1478072015-09-21 17:21:52 -07001660void lock_input_stream(struct stream_in *in)
1661{
1662 pthread_mutex_lock(&in->pre_lock);
1663 pthread_mutex_lock(&in->lock);
1664 pthread_mutex_unlock(&in->pre_lock);
1665}
1666
1667void lock_output_stream(struct stream_out *out)
1668{
1669 pthread_mutex_lock(&out->pre_lock);
1670 pthread_mutex_lock(&out->lock);
1671 pthread_mutex_unlock(&out->pre_lock);
1672}
1673
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001674/* must be called with out->lock locked */
1675static int send_offload_cmd_l(struct stream_out* out, int command)
1676{
1677 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1678
1679 ALOGVV("%s %d", __func__, command);
1680
1681 cmd->cmd = command;
1682 list_add_tail(&out->offload_cmd_list, &cmd->node);
1683 pthread_cond_signal(&out->offload_cond);
1684 return 0;
1685}
1686
1687/* must be called iwth out->lock locked */
1688static void stop_compressed_output_l(struct stream_out *out)
1689{
1690 out->offload_state = OFFLOAD_STATE_IDLE;
1691 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001692 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001693 if (out->compr != NULL) {
1694 compress_stop(out->compr);
1695 while (out->offload_thread_blocked) {
1696 pthread_cond_wait(&out->cond, &out->lock);
1697 }
1698 }
1699}
1700
1701static void *offload_thread_loop(void *context)
1702{
1703 struct stream_out *out = (struct stream_out *) context;
1704 struct listnode *item;
1705
1706 out->offload_state = OFFLOAD_STATE_IDLE;
1707 out->playback_started = 0;
1708
1709 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1710 set_sched_policy(0, SP_FOREGROUND);
1711 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1712
1713 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001714 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001715 for (;;) {
1716 struct offload_cmd *cmd = NULL;
1717 stream_callback_event_t event;
1718 bool send_callback = false;
1719
1720 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1721 __func__, list_empty(&out->offload_cmd_list),
1722 out->offload_state);
1723 if (list_empty(&out->offload_cmd_list)) {
1724 ALOGV("%s SLEEPING", __func__);
1725 pthread_cond_wait(&out->offload_cond, &out->lock);
1726 ALOGV("%s RUNNING", __func__);
1727 continue;
1728 }
1729
1730 item = list_head(&out->offload_cmd_list);
1731 cmd = node_to_item(item, struct offload_cmd, node);
1732 list_remove(item);
1733
1734 ALOGVV("%s STATE %d CMD %d out->compr %p",
1735 __func__, out->offload_state, cmd->cmd, out->compr);
1736
1737 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1738 free(cmd);
1739 break;
1740 }
1741
1742 if (out->compr == NULL) {
1743 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001744 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001745 pthread_cond_signal(&out->cond);
1746 continue;
1747 }
1748 out->offload_thread_blocked = true;
1749 pthread_mutex_unlock(&out->lock);
1750 send_callback = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001751 switch (cmd->cmd) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001752 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1753 compress_wait(out->compr, -1);
1754 send_callback = true;
1755 event = STREAM_CBK_EVENT_WRITE_READY;
1756 break;
1757 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001758 compress_next_track(out->compr);
1759 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001760 send_callback = true;
1761 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001762 /* Resend the metadata for next iteration */
1763 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001764 break;
1765 case OFFLOAD_CMD_DRAIN:
1766 compress_drain(out->compr);
1767 send_callback = true;
1768 event = STREAM_CBK_EVENT_DRAIN_READY;
1769 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001770 case OFFLOAD_CMD_ERROR:
1771 send_callback = true;
1772 event = STREAM_CBK_EVENT_ERROR;
1773 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001774 default:
1775 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1776 break;
1777 }
Eric Laurenta1478072015-09-21 17:21:52 -07001778 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001779 out->offload_thread_blocked = false;
1780 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001781 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001782 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001783 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001784 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001785 free(cmd);
1786 }
1787
1788 pthread_cond_signal(&out->cond);
1789 while (!list_empty(&out->offload_cmd_list)) {
1790 item = list_head(&out->offload_cmd_list);
1791 list_remove(item);
1792 free(node_to_item(item, struct offload_cmd, node));
1793 }
1794 pthread_mutex_unlock(&out->lock);
1795
1796 return NULL;
1797}
1798
1799static int create_offload_callback_thread(struct stream_out *out)
1800{
1801 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1802 list_init(&out->offload_cmd_list);
1803 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1804 offload_thread_loop, out);
1805 return 0;
1806}
1807
1808static int destroy_offload_callback_thread(struct stream_out *out)
1809{
Eric Laurenta1478072015-09-21 17:21:52 -07001810 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001811 stop_compressed_output_l(out);
1812 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1813
1814 pthread_mutex_unlock(&out->lock);
1815 pthread_join(out->offload_thread, (void **) NULL);
1816 pthread_cond_destroy(&out->offload_cond);
1817
1818 return 0;
1819}
1820
Eric Laurent07eeafd2013-10-06 12:52:49 -07001821static bool allow_hdmi_channel_config(struct audio_device *adev)
1822{
1823 struct listnode *node;
1824 struct audio_usecase *usecase;
1825 bool ret = true;
1826
1827 list_for_each(node, &adev->usecase_list) {
1828 usecase = node_to_item(node, struct audio_usecase, list);
1829 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1830 /*
1831 * If voice call is already existing, do not proceed further to avoid
1832 * disabling/enabling both RX and TX devices, CSD calls, etc.
1833 * Once the voice call done, the HDMI channels can be configured to
1834 * max channels of remaining use cases.
1835 */
1836 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001837 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001838 __func__);
1839 ret = false;
1840 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001841 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1842 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001843 "no change in HDMI channels", __func__);
1844 ret = false;
1845 break;
1846 }
1847 }
1848 }
1849 return ret;
1850}
1851
1852static int check_and_set_hdmi_channels(struct audio_device *adev,
1853 unsigned int channels)
1854{
1855 struct listnode *node;
1856 struct audio_usecase *usecase;
1857
1858 /* Check if change in HDMI channel config is allowed */
1859 if (!allow_hdmi_channel_config(adev))
1860 return 0;
1861
1862 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001863 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001864 return 0;
1865 }
1866
1867 platform_set_hdmi_channels(adev->platform, channels);
1868 adev->cur_hdmi_channels = channels;
1869
1870 /*
1871 * Deroute all the playback streams routed to HDMI so that
1872 * the back end is deactivated. Note that backend will not
1873 * be deactivated if any one stream is connected to it.
1874 */
1875 list_for_each(node, &adev->usecase_list) {
1876 usecase = node_to_item(node, struct audio_usecase, list);
1877 if (usecase->type == PCM_PLAYBACK &&
1878 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001879 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001880 }
1881 }
1882
1883 /*
1884 * Enable all the streams disabled above. Now the HDMI backend
1885 * will be activated with new channel configuration
1886 */
1887 list_for_each(node, &adev->usecase_list) {
1888 usecase = node_to_item(node, struct audio_usecase, list);
1889 if (usecase->type == PCM_PLAYBACK &&
1890 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001891 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001892 }
1893 }
1894
1895 return 0;
1896}
1897
Haynes Mathew George65f6b432018-02-27 17:44:55 -08001898static int check_and_set_usb_service_interval(struct audio_device *adev,
1899 struct audio_usecase *uc_info,
1900 bool min)
1901{
1902 struct listnode *node;
1903 struct audio_usecase *usecase;
1904 bool switch_usecases = false;
1905 bool reconfig = false;
1906
1907 if ((uc_info->id != USECASE_AUDIO_PLAYBACK_MMAP) &&
1908 (uc_info->id != USECASE_AUDIO_PLAYBACK_ULL))
1909 return -1;
1910
1911 /* set if the valid usecase do not already exist */
1912 list_for_each(node, &adev->usecase_list) {
1913 usecase = node_to_item(node, struct audio_usecase, list);
1914 if (usecase->type == PCM_PLAYBACK &&
1915 (audio_is_usb_out_device(usecase->devices & AUDIO_DEVICE_OUT_ALL_USB))) {
1916 switch (usecase->id) {
1917 case USECASE_AUDIO_PLAYBACK_MMAP:
1918 case USECASE_AUDIO_PLAYBACK_ULL:
1919 // cannot reconfig while mmap/ull is present.
1920 return -1;
1921 default:
1922 switch_usecases = true;
1923 break;
1924 }
1925 }
1926 if (switch_usecases)
1927 break;
1928 }
1929 /*
1930 * client can try to set service interval in start_output_stream
1931 * to min or to 0 (i.e reset) in stop_output_stream .
1932 */
1933 unsigned long service_interval =
1934 audio_extn_usb_find_service_interval(min, true /*playback*/);
1935 int ret = platform_set_usb_service_interval(adev->platform,
1936 true /*playback*/,
1937 service_interval,
1938 &reconfig);
1939 /* no change or not supported or no active usecases */
1940 if (ret || !reconfig || !switch_usecases)
1941 return -1;
1942 return 0;
1943#undef VALID_USECASE
1944}
1945
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001946static int stop_output_stream(struct stream_out *out)
1947{
1948 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001949 struct audio_usecase *uc_info;
1950 struct audio_device *adev = out->dev;
1951
Eric Laurent994a6932013-07-17 11:51:42 -07001952 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001953 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001954 uc_info = get_usecase_from_list(adev, out->usecase);
1955 if (uc_info == NULL) {
1956 ALOGE("%s: Could not find the usecase (%d) in the list",
1957 __func__, out->usecase);
1958 return -EINVAL;
1959 }
1960
Haynes Mathew George41f86652014-06-17 14:22:15 -07001961 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1962 if (adev->visualizer_stop_output != NULL)
1963 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1964 if (adev->offload_effects_stop_output != NULL)
1965 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08001966 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
1967 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
1968 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07001969 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001970
Eric Laurent150dbfe2013-02-27 14:31:02 -08001971 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001972 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001973
1974 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001975 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001976
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001977 list_remove(&uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001978
Eric Laurent0499d4f2014-08-25 22:39:29 -05001979 audio_extn_extspk_update(adev->extspk);
1980
Eric Laurent07eeafd2013-10-06 12:52:49 -07001981 /* Must be called after removing the usecase from list */
1982 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1983 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07001984 else if (out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
1985 struct listnode *node;
1986 struct audio_usecase *usecase;
1987 list_for_each(node, &adev->usecase_list) {
1988 usecase = node_to_item(node, struct audio_usecase, list);
1989 if (usecase->devices & AUDIO_DEVICE_OUT_SPEAKER)
1990 select_devices(adev, usecase->id);
1991 }
Haynes Mathew George65f6b432018-02-27 17:44:55 -08001992 } else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
1993 ret = check_and_set_usb_service_interval(adev, uc_info, false /*min*/);
1994 if (ret == 0) {
1995 /* default service interval was successfully updated,
1996 reopen USB backend with new service interval */
1997 check_and_route_playback_usecases(adev, uc_info, uc_info->out_snd_device);
1998 }
1999 ret = 0;
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07002000 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002001
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002002 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07002003 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002004 return ret;
2005}
2006
2007int start_output_stream(struct stream_out *out)
2008{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002009 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002010 struct audio_usecase *uc_info;
2011 struct audio_device *adev = out->dev;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002012 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002013
Eric Laurent994a6932013-07-17 11:51:42 -07002014 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002015 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002016
2017 if (out->card_status == CARD_STATUS_OFFLINE ||
2018 adev->card_status == CARD_STATUS_OFFLINE) {
2019 ALOGW("out->card_status or adev->card_status offline, try again");
2020 ret = -EAGAIN;
2021 goto error_config;
2022 }
2023
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002024 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2025 if (!audio_extn_a2dp_is_ready()) {
2026 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2027 a2dp_combo = true;
2028 } else {
2029 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2030 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2031 ret = -EAGAIN;
2032 goto error_config;
2033 }
2034 }
2035 }
2036 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002037 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002038 if (out->pcm_device_id < 0) {
2039 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2040 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002041 ret = -EINVAL;
2042 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002043 }
2044
2045 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
2046 uc_info->id = out->usecase;
2047 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002048 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002049 uc_info->devices = out->devices;
2050 uc_info->in_snd_device = SND_DEVICE_NONE;
2051 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002052
Eric Laurent07eeafd2013-10-06 12:52:49 -07002053 /* This must be called before adding this usecase to the list */
2054 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2055 check_and_set_hdmi_channels(adev, out->config.channels);
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002056 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
2057 check_and_set_usb_service_interval(adev, uc_info, true /*min*/);
2058 /* USB backend is not reopened immediately.
2059 This is eventually done as part of select_devices */
2060 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002061
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002062 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002063
Wei Wangf4837d52017-11-21 14:51:20 -08002064 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002065 audio_extn_perf_lock_acquire();
2066
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002067 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2068 (!audio_extn_a2dp_is_ready())) {
2069 if (!a2dp_combo) {
2070 check_a2dp_restore_l(adev, out, false);
2071 } else {
2072 audio_devices_t dev = out->devices;
2073 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2074 select_devices(adev, out->usecase);
2075 out->devices = dev;
2076 }
2077 } else {
2078 select_devices(adev, out->usecase);
2079 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002080
Eric Laurent0499d4f2014-08-25 22:39:29 -05002081 audio_extn_extspk_update(adev->extspk);
2082
Andy Hung31aca912014-03-20 17:14:59 -07002083 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002084 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002085 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2086 out->pcm = NULL;
2087 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
2088 COMPRESS_IN, &out->compr_config);
2089 if (out->compr && !is_compress_ready(out->compr)) {
2090 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2091 compress_close(out->compr);
2092 out->compr = NULL;
2093 ret = -EIO;
2094 goto error_open;
2095 }
2096 if (out->offload_callback)
2097 compress_nonblock(out->compr, out->non_blocking);
2098
2099 if (adev->visualizer_start_output != NULL)
2100 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2101 if (adev->offload_effects_start_output != NULL)
2102 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
2103 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002104 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002105 ALOGE("%s: pcm stream not ready", __func__);
2106 goto error_open;
2107 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002108 ret = pcm_start(out->pcm);
2109 if (ret < 0) {
2110 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2111 goto error_open;
2112 }
2113 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07002114 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002115 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002116
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002117 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2118 flags |= PCM_MMAP | PCM_NOIRQ;
2119 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002120 } else if (out->realtime) {
2121 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07002122 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002123
2124 while (1) {
2125 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2126 flags, &out->config);
2127 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2128 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2129 if (out->pcm != NULL) {
2130 pcm_close(out->pcm);
2131 out->pcm = NULL;
2132 }
2133 if (pcm_open_retry_count-- == 0) {
2134 ret = -EIO;
2135 goto error_open;
2136 }
2137 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2138 continue;
2139 }
2140 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002141 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002142 ALOGV("%s: pcm_prepare", __func__);
2143 if (pcm_is_ready(out->pcm)) {
2144 ret = pcm_prepare(out->pcm);
2145 if (ret < 0) {
2146 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2147 pcm_close(out->pcm);
2148 out->pcm = NULL;
2149 goto error_open;
2150 }
2151 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002152 if (out->realtime) {
2153 ret = pcm_start(out->pcm);
2154 if (ret < 0) {
2155 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
2156 pcm_close(out->pcm);
2157 out->pcm = NULL;
2158 goto error_open;
2159 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002160 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002161 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002162 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08002163 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002164 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002165 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07002166
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002167 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2168 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2169 audio_low_latency_hint_start();
2170 }
2171
vivek mehtae59cfb22017-06-16 15:57:11 -07002172 // consider a scenario where on pause lower layers are tear down.
2173 // so on resume, swap mixer control need to be sent only when
2174 // backend is active, hence rather than sending from enable device
2175 // sending it from start of streamtream
2176
2177 platform_set_swap_channels(adev, true);
2178
Eric Laurent994a6932013-07-17 11:51:42 -07002179 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002180 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002181error_open:
Wei Wangf4837d52017-11-21 14:51:20 -08002182 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002183 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002184 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002185error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002186 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002187}
2188
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002189static int check_input_parameters(uint32_t sample_rate,
2190 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07002191 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002192{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002193 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2194 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002195 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2196 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002197 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2198 return -EINVAL;
2199 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002200
Eric Laurent74b55762017-07-09 17:04:53 -07002201 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2202 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002203 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002204 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002205 return -EINVAL;
2206 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002207
2208 switch (sample_rate) {
2209 case 8000:
2210 case 11025:
2211 case 12000:
2212 case 16000:
2213 case 22050:
2214 case 24000:
2215 case 32000:
2216 case 44100:
2217 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002218 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002219 break;
2220 default:
vivek mehtadae44712015-07-27 14:13:18 -07002221 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002222 return -EINVAL;
2223 }
2224
2225 return 0;
2226}
2227
Kevin Rocarda325aa22018-04-03 09:15:52 -07002228/** Add a value in a list if not already present.
2229 * @return true if value was successfully inserted or already present,
2230 * false if the list is full and does not contain the value.
2231 */
2232static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
2233 for (size_t i = 0; i < list_length; i++) {
2234 if (list[i] == value) return true; // value is already present
2235 if (list[i] == 0) { // no values in this slot
2236 list[i] = value;
2237 return true; // value inserted
2238 }
2239 }
2240 return false; // could not insert value
2241}
2242
2243/** Add channel_mask in supported_channel_masks if not already present.
2244 * @return true if channel_mask was successfully inserted or already present,
2245 * false if supported_channel_masks is full and does not contain channel_mask.
2246 */
2247static void register_channel_mask(audio_channel_mask_t channel_mask,
2248 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
2249 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
2250 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
2251}
2252
2253/** Add format in supported_formats if not already present.
2254 * @return true if format was successfully inserted or already present,
2255 * false if supported_formats is full and does not contain format.
2256 */
2257static void register_format(audio_format_t format,
2258 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
2259 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
2260 "%s: stream can not declare supporting its format %x", __func__, format);
2261}
2262/** Add sample_rate in supported_sample_rates if not already present.
2263 * @return true if sample_rate was successfully inserted or already present,
2264 * false if supported_sample_rates is full and does not contain sample_rate.
2265 */
2266static void register_sample_rate(uint32_t sample_rate,
2267 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
2268 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
2269 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
2270}
2271
vivek mehtaa68fea62017-06-08 19:04:02 -07002272static size_t get_stream_buffer_size(size_t duration_ms,
2273 uint32_t sample_rate,
2274 audio_format_t format,
2275 int channel_count,
2276 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002277{
2278 size_t size = 0;
2279
vivek mehtaa68fea62017-06-08 19:04:02 -07002280 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002281 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002282 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002283
2284 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002285
Glenn Kasten4f993392014-05-14 07:30:48 -07002286 /* make sure the size is multiple of 32 bytes
2287 * At 48 kHz mono 16-bit PCM:
2288 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2289 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2290 */
2291 size += 0x1f;
2292 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002293
2294 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002295}
2296
2297static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2298{
2299 struct stream_out *out = (struct stream_out *)stream;
2300
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002301 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002302}
2303
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002304static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002305{
2306 return -ENOSYS;
2307}
2308
2309static size_t out_get_buffer_size(const struct audio_stream *stream)
2310{
2311 struct stream_out *out = (struct stream_out *)stream;
2312
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002313 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2314 return out->compr_config.fragment_size;
2315 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002316 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002317 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002318}
2319
2320static uint32_t out_get_channels(const struct audio_stream *stream)
2321{
2322 struct stream_out *out = (struct stream_out *)stream;
2323
2324 return out->channel_mask;
2325}
2326
2327static audio_format_t out_get_format(const struct audio_stream *stream)
2328{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002329 struct stream_out *out = (struct stream_out *)stream;
2330
2331 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002332}
2333
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002334static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002335{
2336 return -ENOSYS;
2337}
2338
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002339/* must be called with out->lock locked */
2340static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002341{
2342 struct stream_out *out = (struct stream_out *)stream;
2343 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002344 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002345
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002346 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002347 if (adev->adm_deregister_stream)
2348 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002349 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002350 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002351 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2352 if (out->pcm) {
2353 pcm_close(out->pcm);
2354 out->pcm = NULL;
2355 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002356 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002357 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002358 out->playback_started = false;
2359 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002360 } else {
2361 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002362 out->gapless_mdata.encoder_delay = 0;
2363 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002364 if (out->compr != NULL) {
2365 compress_close(out->compr);
2366 out->compr = NULL;
2367 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002368 }
Phil Burkbc991042017-02-24 08:06:44 -08002369 if (do_stop) {
2370 stop_output_stream(out);
2371 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002372 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002373 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002374 return 0;
2375}
2376
2377static int out_standby(struct audio_stream *stream)
2378{
2379 struct stream_out *out = (struct stream_out *)stream;
2380
2381 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2382 out->usecase, use_case_table[out->usecase]);
2383
2384 lock_output_stream(out);
2385 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002386 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002387 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002388 return 0;
2389}
2390
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002391static int out_on_error(struct audio_stream *stream)
2392{
2393 struct stream_out *out = (struct stream_out *)stream;
2394 struct audio_device *adev = out->dev;
2395 bool do_standby = false;
2396
2397 lock_output_stream(out);
2398 if (!out->standby) {
2399 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2400 stop_compressed_output_l(out);
2401 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2402 } else
2403 do_standby = true;
2404 }
2405 pthread_mutex_unlock(&out->lock);
2406
2407 if (do_standby)
2408 return out_standby(&out->stream.common);
2409
2410 return 0;
2411}
2412
Andy Hung7401c7c2016-09-21 12:41:21 -07002413static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002414{
Andy Hung7401c7c2016-09-21 12:41:21 -07002415 struct stream_out *out = (struct stream_out *)stream;
2416
2417 // We try to get the lock for consistency,
2418 // but it isn't necessary for these variables.
2419 // If we're not in standby, we may be blocked on a write.
2420 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2421 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2422 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2423
2424 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002425 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002426 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002427
2428 // dump error info
2429 (void)error_log_dump(
2430 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002431
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002432 return 0;
2433}
2434
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002435static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2436{
2437 int ret = 0;
2438 char value[32];
2439 struct compr_gapless_mdata tmp_mdata;
2440
2441 if (!out || !parms) {
2442 return -EINVAL;
2443 }
2444
2445 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2446 if (ret >= 0) {
2447 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2448 } else {
2449 return -EINVAL;
2450 }
2451
2452 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2453 if (ret >= 0) {
2454 tmp_mdata.encoder_padding = atoi(value);
2455 } else {
2456 return -EINVAL;
2457 }
2458
2459 out->gapless_mdata = tmp_mdata;
2460 out->send_new_metadata = 1;
2461 ALOGV("%s new encoder delay %u and padding %u", __func__,
2462 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2463
2464 return 0;
2465}
2466
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002467static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2468{
2469 return out == adev->primary_output || out == adev->voice_tx_output;
2470}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002471
Kevin Rocard1e02c882017-08-09 15:26:07 -07002472static int get_alive_usb_card(struct str_parms* parms) {
2473 int card;
2474 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2475 !audio_extn_usb_alive(card)) {
2476 return card;
2477 }
2478 return -ENODEV;
2479}
2480
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002481static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2482{
2483 struct stream_out *out = (struct stream_out *)stream;
2484 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002485 struct audio_usecase *usecase;
2486 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002487 struct str_parms *parms;
2488 char value[32];
2489 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002490 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002491 int status = 0;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002492 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002493
Eric Laurent2e140aa2016-06-30 17:14:46 -07002494 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002495 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002496 parms = str_parms_create_str(kvpairs);
2497 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2498 if (ret >= 0) {
2499 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002500
Eric Laurenta1478072015-09-21 17:21:52 -07002501 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002502
2503 // The usb driver needs to be closed after usb device disconnection
2504 // otherwise audio is no longer played on the new usb devices.
2505 // By forcing the stream in standby, the usb stack refcount drops to 0
2506 // and the driver is closed.
2507 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD && val == AUDIO_DEVICE_NONE &&
2508 audio_is_usb_out_device(out->devices)) {
2509 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2510 out_standby_l(&out->stream.common);
2511 }
2512
Eric Laurent150dbfe2013-02-27 14:31:02 -08002513 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002514
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002515 /*
2516 * When HDMI cable is unplugged the music playback is paused and
2517 * the policy manager sends routing=0. But the audioflinger
2518 * continues to write data until standby time (3sec).
2519 * As the HDMI core is turned off, the write gets blocked.
2520 * Avoid this by routing audio to speaker until standby.
2521 */
2522 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2523 val == AUDIO_DEVICE_NONE) {
2524 val = AUDIO_DEVICE_OUT_SPEAKER;
2525 }
2526
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002527 /*
2528 * When A2DP is disconnected the
2529 * music playback is paused and the policy manager sends routing=0
2530 * But the audioflingercontinues to write data until standby time
2531 * (3sec). As BT is turned off, the write gets blocked.
2532 * Avoid this by routing audio to speaker until standby.
2533 */
2534 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2535 (val == AUDIO_DEVICE_NONE) &&
2536 !audio_extn_a2dp_is_ready()) {
2537 val = AUDIO_DEVICE_OUT_SPEAKER;
2538 }
2539
2540 /* To avoid a2dp to sco overlapping / BT device improper state
2541 * check with BT lib about a2dp streaming support before routing
2542 */
2543 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2544 if (!audio_extn_a2dp_is_ready()) {
2545 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
2546 //combo usecase just by pass a2dp
2547 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2548 bypass_a2dp = true;
2549 } else {
2550 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2551 /* update device to a2dp and don't route as BT returned error
2552 * However it is still possible a2dp routing called because
2553 * of current active device disconnection (like wired headset)
2554 */
2555 out->devices = val;
2556 pthread_mutex_unlock(&out->lock);
2557 pthread_mutex_unlock(&adev->lock);
2558 status = -ENOSYS;
2559 goto routing_fail;
2560 }
2561 }
2562 }
2563
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002564 audio_devices_t new_dev = val;
2565
2566 // Workaround: If routing to an non existing usb device, fail gracefully
2567 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002568 int card;
2569 if (audio_is_usb_out_device(new_dev) &&
2570 (card = get_alive_usb_card(parms)) >= 0) {
2571
2572 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002573 pthread_mutex_unlock(&adev->lock);
2574 pthread_mutex_unlock(&out->lock);
2575 status = -ENOSYS;
2576 goto routing_fail;
2577 }
2578
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002579 /*
2580 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002581 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002582 * the select_devices(). But how do we undo this?
2583 *
2584 * For example, music playback is active on headset (deep-buffer usecase)
2585 * and if we go to ringtones and select a ringtone, low-latency usecase
2586 * will be started on headset+speaker. As we can't enable headset+speaker
2587 * and headset devices at the same time, select_devices() switches the music
2588 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2589 * So when the ringtone playback is completed, how do we undo the same?
2590 *
2591 * We are relying on the out_set_parameters() call on deep-buffer output,
2592 * once the ringtone playback is ended.
2593 * NOTE: We should not check if the current devices are same as new devices.
2594 * Because select_devices() must be called to switch back the music
2595 * playback to headset.
2596 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002597 if (new_dev != AUDIO_DEVICE_NONE) {
2598 bool same_dev = out->devices == new_dev;
2599 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002600
Eric Laurenta7657192014-10-09 21:09:33 -07002601 if (output_drives_call(adev, out)) {
2602 if (!voice_is_in_call(adev)) {
2603 if (adev->mode == AUDIO_MODE_IN_CALL) {
2604 adev->current_call_output = out;
2605 ret = voice_start_call(adev);
2606 }
2607 } else {
2608 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002609 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002610 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002611 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002612
2613 if (!out->standby) {
2614 if (!same_dev) {
2615 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002616 // inform adm before actual routing to prevent glitches.
2617 if (adev->adm_on_routing_change) {
2618 adev->adm_on_routing_change(adev->adm_data,
2619 out->handle);
2620 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002621 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002622 if (!bypass_a2dp) {
2623 select_devices(adev, out->usecase);
2624 } else {
2625 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2626 select_devices(adev, out->usecase);
2627 out->devices = new_dev;
2628 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002629 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002630
2631 // on device switch force swap, lower functions will make sure
2632 // to check if swap is allowed or not.
2633
2634 if (!same_dev)
2635 platform_set_swap_channels(adev, true);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002636
2637 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2638 out->a2dp_compress_mute &&
2639 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
2640 pthread_mutex_lock(&out->compr_mute_lock);
2641 out->a2dp_compress_mute = false;
2642 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
2643 pthread_mutex_unlock(&out->compr_mute_lock);
2644 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002645 }
2646
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002647 }
2648
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002649 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002650 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002651
2652 /*handles device and call state changes*/
2653 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002654 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002655 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002656
2657 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2658 parse_compress_metadata(out, parms);
2659 }
2660
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002661 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002662 ALOGV("%s: exit: code(%d)", __func__, status);
2663 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002664}
2665
Haynes Mathew George569b7482017-05-08 14:44:27 -07002666static bool stream_get_parameter_channels(struct str_parms *query,
2667 struct str_parms *reply,
2668 audio_channel_mask_t *supported_channel_masks) {
2669 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002670 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002671 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002672 size_t i, j;
2673
2674 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2675 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002676 value[0] = '\0';
2677 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002678 while (supported_channel_masks[i] != 0) {
2679 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2680 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002681 if (!first) {
2682 strcat(value, "|");
2683 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002684 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002685 first = false;
2686 break;
2687 }
2688 }
2689 i++;
2690 }
2691 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002692 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002693 return ret >= 0;
2694}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002695
Haynes Mathew George569b7482017-05-08 14:44:27 -07002696static bool stream_get_parameter_formats(struct str_parms *query,
2697 struct str_parms *reply,
2698 audio_format_t *supported_formats) {
2699 int ret = -1;
2700 char value[256];
2701 int i;
2702
2703 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2704 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002705 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002706 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002707 case AUDIO_FORMAT_PCM_16_BIT:
2708 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2709 break;
2710 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2711 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2712 break;
2713 case AUDIO_FORMAT_PCM_32_BIT:
2714 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2715 break;
2716 default:
2717 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002718 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002719 break;
2720 }
2721 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002722 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002723 return ret >= 0;
2724}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002725
Haynes Mathew George569b7482017-05-08 14:44:27 -07002726static bool stream_get_parameter_rates(struct str_parms *query,
2727 struct str_parms *reply,
2728 uint32_t *supported_sample_rates) {
2729
2730 int i;
2731 char value[256];
2732 int ret = -1;
2733 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2734 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002735 value[0] = '\0';
2736 i=0;
2737 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002738 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002739 int avail = sizeof(value) - cursor;
2740 ret = snprintf(value + cursor, avail, "%s%d",
2741 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002742 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002743 if (ret < 0 || ret >= avail) {
2744 // if cursor is at the last element of the array
2745 // overwrite with \0 is duplicate work as
2746 // snprintf already put a \0 in place.
2747 // else
2748 // we had space to write the '|' at value[cursor]
2749 // (which will be overwritten) or no space to fill
2750 // the first element (=> cursor == 0)
2751 value[cursor] = '\0';
2752 break;
2753 }
2754 cursor += ret;
2755 ++i;
2756 }
2757 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2758 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002759 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002760 return ret >= 0;
2761}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002762
Haynes Mathew George569b7482017-05-08 14:44:27 -07002763static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2764{
2765 struct stream_out *out = (struct stream_out *)stream;
2766 struct str_parms *query = str_parms_create_str(keys);
2767 char *str;
2768 struct str_parms *reply = str_parms_create();
2769 bool replied = false;
2770 ALOGV("%s: enter: keys - %s", __func__, keys);
2771
2772 replied |= stream_get_parameter_channels(query, reply,
2773 &out->supported_channel_masks[0]);
2774 replied |= stream_get_parameter_formats(query, reply,
2775 &out->supported_formats[0]);
2776 replied |= stream_get_parameter_rates(query, reply,
2777 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002778 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002779 str = str_parms_to_str(reply);
2780 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002781 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002782 }
2783 str_parms_destroy(query);
2784 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002785 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002786 return str;
2787}
2788
2789static uint32_t out_get_latency(const struct audio_stream_out *stream)
2790{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002791 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002792 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002793 uint32_t latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002794
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002795 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2796 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002797 else if ((out->realtime) ||
2798 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002799 // since the buffer won't be filled up faster than realtime,
2800 // return a smaller number
2801 period_ms = (out->af_period_multiplier * out->config.period_size *
2802 1000) / (out->config.rate);
2803 hw_delay = platform_render_latency(out->usecase)/1000;
2804 return period_ms + hw_delay;
2805 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002806
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002807 latency = (out->config.period_count * out->config.period_size * 1000) /
2808 (out->config.rate);
2809
2810 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
2811 latency += audio_extn_a2dp_get_encoder_latency();
2812
2813 return latency;
2814}
2815
2816static int set_compr_volume(struct audio_stream_out *stream, float left,
2817 float right)
2818{
2819 struct stream_out *out = (struct stream_out *)stream;
2820 int volume[2];
2821 char mixer_ctl_name[128];
2822 struct audio_device *adev = out->dev;
2823 struct mixer_ctl *ctl;
2824 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2825 PCM_PLAYBACK);
2826
2827 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2828 "Compress Playback %d Volume", pcm_device_id);
2829 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2830 if (!ctl) {
2831 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2832 __func__, mixer_ctl_name);
2833 return -EINVAL;
2834 }
2835 ALOGV("%s: ctl for mixer cmd - %s, left %f, right %f",
2836 __func__, mixer_ctl_name, left, right);
2837 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2838 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2839 mixer_ctl_set_array(ctl, volume, sizeof(volume) / sizeof(volume[0]));
2840
2841 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002842}
2843
2844static int out_set_volume(struct audio_stream_out *stream, float left,
2845 float right)
2846{
Eric Laurenta9024de2013-04-04 09:19:12 -07002847 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002848 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002849
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002850 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002851 /* only take left channel into account: the API is for stereo anyway */
2852 out->muted = (left == 0.0f);
2853 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002854 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002855 pthread_mutex_lock(&out->compr_mute_lock);
2856 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
2857 if (!out->a2dp_compress_mute)
2858 ret = set_compr_volume(stream, left, right);
2859 out->volume_l = left;
2860 out->volume_r = right;
2861 pthread_mutex_unlock(&out->compr_mute_lock);
2862 return ret;
vivek mehtaa68fea62017-06-08 19:04:02 -07002863 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002864 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2865 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2866 if (!out->standby) {
2867 // if in standby, cached volume will be sent after stream is opened
2868 audio_extn_utils_send_app_type_gain(out->dev,
2869 out->app_type_cfg.app_type,
2870 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002871 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002872 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002873 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002874
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002875 return -ENOSYS;
2876}
2877
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002878// note: this call is safe only if the stream_cb is
2879// removed first in close_output_stream (as is done now).
2880static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2881{
2882 if (!stream || !parms)
2883 return;
2884
2885 struct stream_out *out = (struct stream_out *)stream;
2886 struct audio_device *adev = out->dev;
2887
2888 card_status_t status;
2889 int card;
2890 if (parse_snd_card_status(parms, &card, &status) < 0)
2891 return;
2892
2893 pthread_mutex_lock(&adev->lock);
2894 bool valid_cb = (card == adev->snd_card);
2895 pthread_mutex_unlock(&adev->lock);
2896
2897 if (!valid_cb)
2898 return;
2899
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002900 lock_output_stream(out);
2901 if (out->card_status != status)
2902 out->card_status = status;
2903 pthread_mutex_unlock(&out->lock);
2904
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002905 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2906 use_case_table[out->usecase],
2907 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2908
2909 if (status == CARD_STATUS_OFFLINE)
2910 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002911
2912 return;
2913}
2914
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002915#ifdef NO_AUDIO_OUT
2916static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002917 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002918{
2919 struct stream_out *out = (struct stream_out *)stream;
2920
2921 /* No Output device supported other than BT for playback.
2922 * Sleep for the amount of buffer duration
2923 */
Eric Laurenta1478072015-09-21 17:21:52 -07002924 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002925 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2926 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002927 out_get_sample_rate(&out->stream.common));
2928 pthread_mutex_unlock(&out->lock);
2929 return bytes;
2930}
2931#endif
2932
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002933static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2934 size_t bytes)
2935{
2936 struct stream_out *out = (struct stream_out *)stream;
2937 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002938 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002939 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002940
Eric Laurenta1478072015-09-21 17:21:52 -07002941 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002942 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07002943 const size_t frame_size = audio_stream_out_frame_size(stream);
2944 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002945
Eric Laurent0e46adf2016-12-16 12:49:24 -08002946 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2947 error_code = ERROR_CODE_WRITE;
2948 goto exit;
2949 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002950
2951 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2952 (audio_extn_a2dp_is_suspended())) {
2953 if (!(out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2954 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2955 ret = -EIO;
2956 goto exit;
2957 }
2958 }
2959 }
2960
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002961 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002962 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002963 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002964 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07002965
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002966 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002967 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002968 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07002969 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002970 goto exit;
2971 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002972
vivek mehta40125092017-08-21 18:48:51 -07002973 // after standby always force set last known cal step
2974 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
2975 ALOGD("%s: retry previous failed cal level set", __func__);
2976 send_gain_dep_calibration_l();
2977 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002978 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002979
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002980 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002981 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002982 if (out->send_new_metadata) {
2983 ALOGVV("send new gapless metadata");
2984 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2985 out->send_new_metadata = 0;
2986 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002987 unsigned int avail;
2988 struct timespec tstamp;
2989 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2990 /* Do not limit write size if the available frames count is unknown */
2991 if (ret != 0) {
2992 avail = bytes;
2993 }
2994 if (avail == 0) {
2995 ret = 0;
2996 } else {
2997 if (avail > bytes) {
2998 avail = bytes;
2999 }
3000 ret = compress_write(out->compr, buffer, avail);
3001 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
3002 __func__, avail, ret);
3003 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003004
Eric Laurent6e895242013-09-05 16:10:57 -07003005 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003006 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
3007 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003008 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003009 compress_start(out->compr);
3010 out->playback_started = 1;
3011 out->offload_state = OFFLOAD_STATE_PLAYING;
3012 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003013 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07003014 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07003015 } else {
3016 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07003017 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003018 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07003019 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003020 return ret;
3021 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07003022 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003023 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003024 size_t bytes_to_write = bytes;
3025
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003026 if (out->muted)
3027 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07003028 // FIXME: this can be removed once audio flinger mixer supports mono output
Nadav Bar3d72cfc2018-01-07 12:19:24 +02003029 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP || out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003030 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3031 int16_t *src = (int16_t *)buffer;
3032 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003033
Eric Laurentad2dde92017-09-20 18:27:31 -07003034 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
3035 out->format != AUDIO_FORMAT_PCM_16_BIT,
3036 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003037
Eric Laurentad2dde92017-09-20 18:27:31 -07003038 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
3039 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
3040 }
3041 bytes_to_write /= 2;
3042 }
3043 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes_to_write);
3044
Glenn Kasten5a59dff2018-02-22 08:05:35 -08003045 long ns = (frames * (int64_t) NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003046 request_out_focus(out, ns);
3047
3048 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3049 if (use_mmap)
Eric Laurentad2dde92017-09-20 18:27:31 -07003050 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003051 else
Eric Laurentad2dde92017-09-20 18:27:31 -07003052 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003053
Haynes Mathew George03c40102016-01-29 17:57:48 -08003054 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07003055 } else {
3056 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003057 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003058 }
3059
3060exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07003061 // For PCM we always consume the buffer and return #bytes regardless of ret.
3062 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003063 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07003064 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003065 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07003066
Andy Hung7401c7c2016-09-21 12:41:21 -07003067 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07003068 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07003069 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3070 ALOGE_IF(out->pcm != NULL,
3071 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07003072 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003073 // usleep not guaranteed for values over 1 second but we don't limit here.
3074 }
3075 }
Andy Hungda9b56b2016-09-16 20:06:35 -07003076
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003077 pthread_mutex_unlock(&out->lock);
3078
3079 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07003080 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003081 if (sleeptime_us != 0)
3082 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003083 }
3084 return bytes;
3085}
3086
3087static int out_get_render_position(const struct audio_stream_out *stream,
3088 uint32_t *dsp_frames)
3089{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003090 struct stream_out *out = (struct stream_out *)stream;
3091 *dsp_frames = 0;
3092 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07003093 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003094 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003095 unsigned long frames = 0;
3096 // TODO: check return value
3097 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
3098 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003099 ALOGVV("%s rendered frames %d sample_rate %d",
3100 __func__, *dsp_frames, out->sample_rate);
3101 }
3102 pthread_mutex_unlock(&out->lock);
3103 return 0;
3104 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003105 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003106}
3107
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003108static int out_add_audio_effect(const struct audio_stream *stream __unused,
3109 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003110{
3111 return 0;
3112}
3113
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003114static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3115 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003116{
3117 return 0;
3118}
3119
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003120static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3121 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003122{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003123 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003124}
3125
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003126static int out_get_presentation_position(const struct audio_stream_out *stream,
3127 uint64_t *frames, struct timespec *timestamp)
3128{
3129 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003130 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07003131 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003132
Eric Laurenta1478072015-09-21 17:21:52 -07003133 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003134
Eric Laurent949a0892013-09-20 09:20:13 -07003135 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3136 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003137 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07003138 compress_get_tstamp(out->compr, &dsp_frames,
3139 &out->sample_rate);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003140 // Adjustment accounts for A2DP encoder latency with offload usecases
3141 // Note: Encoder latency is returned in ms.
3142 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3143 unsigned long offset =
3144 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3145 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
3146 }
Eric Laurent949a0892013-09-20 09:20:13 -07003147 ALOGVV("%s rendered frames %ld sample_rate %d",
3148 __func__, dsp_frames, out->sample_rate);
3149 *frames = dsp_frames;
3150 ret = 0;
3151 /* this is the best we can do */
3152 clock_gettime(CLOCK_MONOTONIC, timestamp);
3153 }
3154 } else {
3155 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07003156 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003157 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3158 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003159 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003160 // This adjustment accounts for buffering after app processor.
3161 // It is based on estimated DSP latency per use case, rather than exact.
3162 signed_frames -=
3163 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3164
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003165 // Adjustment accounts for A2DP encoder latency with non-offload usecases
3166 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3167 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3168 signed_frames -=
3169 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3170 }
3171
Eric Laurent949a0892013-09-20 09:20:13 -07003172 // It would be unusual for this value to be negative, but check just in case ...
3173 if (signed_frames >= 0) {
3174 *frames = signed_frames;
3175 ret = 0;
3176 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003177 }
3178 }
3179 }
3180
3181 pthread_mutex_unlock(&out->lock);
3182
3183 return ret;
3184}
3185
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003186static int out_set_callback(struct audio_stream_out *stream,
3187 stream_callback_t callback, void *cookie)
3188{
3189 struct stream_out *out = (struct stream_out *)stream;
3190
3191 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003192 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003193 out->offload_callback = callback;
3194 out->offload_cookie = cookie;
3195 pthread_mutex_unlock(&out->lock);
3196 return 0;
3197}
3198
3199static int out_pause(struct audio_stream_out* stream)
3200{
3201 struct stream_out *out = (struct stream_out *)stream;
3202 int status = -ENOSYS;
3203 ALOGV("%s", __func__);
3204 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003205 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003206 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
3207 status = compress_pause(out->compr);
3208 out->offload_state = OFFLOAD_STATE_PAUSED;
3209 }
3210 pthread_mutex_unlock(&out->lock);
3211 }
3212 return status;
3213}
3214
3215static int out_resume(struct audio_stream_out* stream)
3216{
3217 struct stream_out *out = (struct stream_out *)stream;
3218 int status = -ENOSYS;
3219 ALOGV("%s", __func__);
3220 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3221 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07003222 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003223 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
3224 status = compress_resume(out->compr);
3225 out->offload_state = OFFLOAD_STATE_PLAYING;
3226 }
3227 pthread_mutex_unlock(&out->lock);
3228 }
3229 return status;
3230}
3231
3232static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3233{
3234 struct stream_out *out = (struct stream_out *)stream;
3235 int status = -ENOSYS;
3236 ALOGV("%s", __func__);
3237 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003238 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003239 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3240 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3241 else
3242 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3243 pthread_mutex_unlock(&out->lock);
3244 }
3245 return status;
3246}
3247
3248static int out_flush(struct audio_stream_out* stream)
3249{
3250 struct stream_out *out = (struct stream_out *)stream;
3251 ALOGV("%s", __func__);
3252 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003253 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003254 stop_compressed_output_l(out);
3255 pthread_mutex_unlock(&out->lock);
3256 return 0;
3257 }
3258 return -ENOSYS;
3259}
3260
Eric Laurent0e46adf2016-12-16 12:49:24 -08003261static int out_stop(const struct audio_stream_out* stream)
3262{
3263 struct stream_out *out = (struct stream_out *)stream;
3264 struct audio_device *adev = out->dev;
3265 int ret = -ENOSYS;
3266
3267 ALOGV("%s", __func__);
3268 pthread_mutex_lock(&adev->lock);
3269 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3270 out->playback_started && out->pcm != NULL) {
3271 pcm_stop(out->pcm);
3272 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08003273 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003274 }
3275 pthread_mutex_unlock(&adev->lock);
3276 return ret;
3277}
3278
3279static int out_start(const struct audio_stream_out* stream)
3280{
3281 struct stream_out *out = (struct stream_out *)stream;
3282 struct audio_device *adev = out->dev;
3283 int ret = -ENOSYS;
3284
3285 ALOGV("%s", __func__);
3286 pthread_mutex_lock(&adev->lock);
3287 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3288 !out->playback_started && out->pcm != NULL) {
3289 ret = start_output_stream(out);
3290 if (ret == 0) {
3291 out->playback_started = true;
3292 }
3293 }
3294 pthread_mutex_unlock(&adev->lock);
3295 return ret;
3296}
3297
Phil Burkbc991042017-02-24 08:06:44 -08003298/*
3299 * Modify config->period_count based on min_size_frames
3300 */
3301static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
3302{
3303 int periodCountRequested = (min_size_frames + config->period_size - 1)
3304 / config->period_size;
3305 int periodCount = MMAP_PERIOD_COUNT_MIN;
3306
3307 ALOGV("%s original config.period_size = %d config.period_count = %d",
3308 __func__, config->period_size, config->period_count);
3309
3310 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
3311 periodCount *= 2;
3312 }
3313 config->period_count = periodCount;
3314
3315 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
3316}
3317
Eric Laurent0e46adf2016-12-16 12:49:24 -08003318static int out_create_mmap_buffer(const struct audio_stream_out *stream,
3319 int32_t min_size_frames,
3320 struct audio_mmap_buffer_info *info)
3321{
3322 struct stream_out *out = (struct stream_out *)stream;
3323 struct audio_device *adev = out->dev;
3324 int ret = 0;
3325 unsigned int offset1;
3326 unsigned int frames1;
3327 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003328 uint32_t mmap_size;
3329 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003330
3331 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003332 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003333 pthread_mutex_lock(&adev->lock);
3334
3335 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003336 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003337 ret = -EINVAL;
3338 goto exit;
3339 }
3340 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003341 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003342 ret = -ENOSYS;
3343 goto exit;
3344 }
3345 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3346 if (out->pcm_device_id < 0) {
3347 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3348 __func__, out->pcm_device_id, out->usecase);
3349 ret = -EINVAL;
3350 goto exit;
3351 }
Phil Burkbc991042017-02-24 08:06:44 -08003352
3353 adjust_mmap_period_count(&out->config, min_size_frames);
3354
Eric Laurent0e46adf2016-12-16 12:49:24 -08003355 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3356 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3357 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3358 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3359 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3360 step = "open";
3361 ret = -ENODEV;
3362 goto exit;
3363 }
3364 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3365 if (ret < 0) {
3366 step = "begin";
3367 goto exit;
3368 }
3369 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003370 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003371 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003372 ret = platform_get_mmap_data_fd(adev->platform,
3373 out->pcm_device_id, 0 /*playback*/,
3374 &info->shared_memory_fd,
3375 &mmap_size);
3376 if (ret < 0) {
3377 // Fall back to non exclusive mode
3378 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3379 } else {
3380 if (mmap_size < buffer_size) {
3381 step = "mmap";
3382 goto exit;
3383 }
3384 // FIXME: indicate exclusive mode support by returning a negative buffer size
3385 info->buffer_size_frames *= -1;
3386 }
3387 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003388
3389 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3390 if (ret < 0) {
3391 step = "commit";
3392 goto exit;
3393 }
Phil Burkbc991042017-02-24 08:06:44 -08003394
3395 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003396 ret = 0;
3397
3398 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3399 __func__, info->shared_memory_address, info->buffer_size_frames);
3400
3401exit:
3402 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003403 if (out->pcm == NULL) {
3404 ALOGE("%s: %s - %d", __func__, step, ret);
3405 } else {
3406 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003407 pcm_close(out->pcm);
3408 out->pcm = NULL;
3409 }
3410 }
3411 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003412 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003413 return ret;
3414}
3415
3416static int out_get_mmap_position(const struct audio_stream_out *stream,
3417 struct audio_mmap_position *position)
3418{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003419 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003420 struct stream_out *out = (struct stream_out *)stream;
3421 ALOGVV("%s", __func__);
3422 if (position == NULL) {
3423 return -EINVAL;
3424 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003425 lock_output_stream(out);
3426 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3427 out->pcm == NULL) {
3428 ret = -ENOSYS;
3429 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003430 }
3431
3432 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003433 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003434 if (ret < 0) {
3435 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003436 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003437 }
Andy Hungfc044e12017-03-20 09:24:22 -07003438 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003439exit:
3440 pthread_mutex_unlock(&out->lock);
3441 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003442}
3443
3444
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003445/** audio_stream_in implementation **/
3446static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3447{
3448 struct stream_in *in = (struct stream_in *)stream;
3449
3450 return in->config.rate;
3451}
3452
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003453static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003454{
3455 return -ENOSYS;
3456}
3457
3458static size_t in_get_buffer_size(const struct audio_stream *stream)
3459{
3460 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003461 return in->config.period_size * in->af_period_multiplier *
3462 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003463}
3464
3465static uint32_t in_get_channels(const struct audio_stream *stream)
3466{
3467 struct stream_in *in = (struct stream_in *)stream;
3468
3469 return in->channel_mask;
3470}
3471
vivek mehta4ed66e62016-04-15 23:33:34 -07003472static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003473{
vivek mehta4ed66e62016-04-15 23:33:34 -07003474 struct stream_in *in = (struct stream_in *)stream;
3475 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003476}
3477
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003478static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003479{
3480 return -ENOSYS;
3481}
3482
3483static int in_standby(struct audio_stream *stream)
3484{
3485 struct stream_in *in = (struct stream_in *)stream;
3486 struct audio_device *adev = in->dev;
3487 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003488 bool do_stop = true;
3489
Eric Laurent994a6932013-07-17 11:51:42 -07003490 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003491
3492 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003493
3494 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003495 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003496 audio_extn_sound_trigger_stop_lab(in);
3497 in->standby = true;
3498 }
3499
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003500 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003501 if (adev->adm_deregister_stream)
3502 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3503
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003504 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003505 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003506 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003507 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003508 in->capture_started = false;
3509 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003510 if (in->pcm) {
3511 pcm_close(in->pcm);
3512 in->pcm = NULL;
3513 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003514 adev->enable_voicerx = false;
3515 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003516 if (do_stop) {
3517 status = stop_input_stream(in);
3518 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003519 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003520 }
3521 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003522 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003523 return status;
3524}
3525
Andy Hungd13f0d32017-06-12 13:58:37 -07003526static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003527{
Andy Hungd13f0d32017-06-12 13:58:37 -07003528 struct stream_in *in = (struct stream_in *)stream;
3529
3530 // We try to get the lock for consistency,
3531 // but it isn't necessary for these variables.
3532 // If we're not in standby, we may be blocked on a read.
3533 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3534 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3535 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3536 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3537
3538 if (locked) {
3539 pthread_mutex_unlock(&in->lock);
3540 }
3541
3542 // dump error info
3543 (void)error_log_dump(
3544 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003545 return 0;
3546}
3547
3548static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3549{
3550 struct stream_in *in = (struct stream_in *)stream;
3551 struct audio_device *adev = in->dev;
3552 struct str_parms *parms;
3553 char *str;
3554 char value[32];
3555 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003556 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003557
Eric Laurent994a6932013-07-17 11:51:42 -07003558 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003559 parms = str_parms_create_str(kvpairs);
3560
3561 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3562
Eric Laurenta1478072015-09-21 17:21:52 -07003563 lock_input_stream(in);
3564
Eric Laurent150dbfe2013-02-27 14:31:02 -08003565 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003566 if (ret >= 0) {
3567 val = atoi(value);
3568 /* no audio source uses val == 0 */
3569 if ((in->source != val) && (val != 0)) {
3570 in->source = val;
3571 }
3572 }
3573
3574 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003575
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003576 if (ret >= 0) {
3577 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003578 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003579
3580 // Workaround: If routing to an non existing usb device, fail gracefully
3581 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003582 int card;
3583 if (audio_is_usb_in_device(val) &&
3584 (card = get_alive_usb_card(parms)) >= 0) {
3585
3586 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003587 status = -ENOSYS;
3588 } else {
3589
3590 in->device = val;
3591 /* If recording is in progress, change the tx device to new device */
3592 if (!in->standby) {
3593 ALOGV("update input routing change");
3594 // inform adm before actual routing to prevent glitches.
3595 if (adev->adm_on_routing_change) {
3596 adev->adm_on_routing_change(adev->adm_data,
3597 in->capture_handle);
3598 }
3599 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003600 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003601 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003602 }
3603 }
3604
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003605 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003606 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003607
3608 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003609 ALOGV("%s: exit: status(%d)", __func__, status);
3610 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003611}
3612
Haynes Mathew George569b7482017-05-08 14:44:27 -07003613static char* in_get_parameters(const struct audio_stream *stream,
3614 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003615{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003616 struct stream_in *in = (struct stream_in *)stream;
3617 struct str_parms *query = str_parms_create_str(keys);
3618 char *str;
3619 struct str_parms *reply = str_parms_create();
3620 bool replied = false;
3621
3622 ALOGV("%s: enter: keys - %s", __func__, keys);
3623 replied |= stream_get_parameter_channels(query, reply,
3624 &in->supported_channel_masks[0]);
3625 replied |= stream_get_parameter_formats(query, reply,
3626 &in->supported_formats[0]);
3627 replied |= stream_get_parameter_rates(query, reply,
3628 &in->supported_sample_rates[0]);
3629 if (replied) {
3630 str = str_parms_to_str(reply);
3631 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003632 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003633 }
3634 str_parms_destroy(query);
3635 str_parms_destroy(reply);
3636 ALOGV("%s: exit: returns - %s", __func__, str);
3637 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003638}
3639
Eric Laurent51f3c662018-04-10 18:21:34 -07003640static int in_set_gain(struct audio_stream_in *stream, float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003641{
Eric Laurent51f3c662018-04-10 18:21:34 -07003642 struct stream_in *in = (struct stream_in *)stream;
3643 char mixer_ctl_name[128];
3644 struct mixer_ctl *ctl;
3645 int ctl_value;
3646
3647 ALOGV("%s: gain %f", __func__, gain);
3648
3649 if (stream == NULL)
3650 return -EINVAL;
3651
3652 /* in_set_gain() only used to silence MMAP capture for now */
3653 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
3654 return -ENOSYS;
3655
3656 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
3657
3658 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
3659 if (!ctl) {
3660 ALOGW("%s: Could not get ctl for mixer cmd - %s",
3661 __func__, mixer_ctl_name);
3662 return -ENOSYS;
3663 }
3664
3665 if (gain < RECORD_GAIN_MIN)
3666 gain = RECORD_GAIN_MIN;
3667 else if (gain > RECORD_GAIN_MAX)
3668 gain = RECORD_GAIN_MAX;
3669 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
3670
3671 mixer_ctl_set_value(ctl, 0, ctl_value);
3672 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003673}
3674
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003675static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3676{
3677 if (!stream || !parms)
3678 return;
3679
3680 struct stream_in *in = (struct stream_in *)stream;
3681 struct audio_device *adev = in->dev;
3682
3683 card_status_t status;
3684 int card;
3685 if (parse_snd_card_status(parms, &card, &status) < 0)
3686 return;
3687
3688 pthread_mutex_lock(&adev->lock);
3689 bool valid_cb = (card == adev->snd_card);
3690 pthread_mutex_unlock(&adev->lock);
3691
3692 if (!valid_cb)
3693 return;
3694
3695 lock_input_stream(in);
3696 if (in->card_status != status)
3697 in->card_status = status;
3698 pthread_mutex_unlock(&in->lock);
3699
3700 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3701 use_case_table[in->usecase],
3702 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3703
3704 // a better solution would be to report error back to AF and let
3705 // it put the stream to standby
3706 if (status == CARD_STATUS_OFFLINE)
3707 in_standby(&in->stream.common);
3708
3709 return;
3710}
3711
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003712static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3713 size_t bytes)
3714{
3715 struct stream_in *in = (struct stream_in *)stream;
3716 struct audio_device *adev = in->dev;
3717 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003718 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003719 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003720
Eric Laurenta1478072015-09-21 17:21:52 -07003721 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003722 const size_t frame_size = audio_stream_in_frame_size(stream);
3723 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003724
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003725 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003726 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003727 /* Read from sound trigger HAL */
3728 audio_extn_sound_trigger_read(in, buffer, bytes);
3729 pthread_mutex_unlock(&in->lock);
3730 return bytes;
3731 }
3732
Eric Laurent0e46adf2016-12-16 12:49:24 -08003733 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3734 ret = -ENOSYS;
3735 goto exit;
3736 }
3737
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003738 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003739 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003740 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003741 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003742 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003743 goto exit;
3744 }
3745 in->standby = 0;
3746 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003747
Andy Hungd13f0d32017-06-12 13:58:37 -07003748 // errors that occur here are read errors.
3749 error_code = ERROR_CODE_READ;
3750
Haynes Mathew George03c40102016-01-29 17:57:48 -08003751 //what's the duration requested by the client?
3752 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3753 in->config.rate;
3754 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003755
Haynes Mathew George03c40102016-01-29 17:57:48 -08003756 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003757 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003758 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003759 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003760 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003761 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003762 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003763 if (ret < 0) {
3764 ALOGE("Failed to read w/err %s", strerror(errno));
3765 ret = -errno;
3766 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003767 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3768 if (bytes % 4 == 0) {
3769 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3770 int_buf_stream = buffer;
3771 for (size_t itt=0; itt < bytes/4 ; itt++) {
3772 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003773 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003774 } else {
3775 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3776 ret = -EINVAL;
3777 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003778 }
3779 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003780 }
3781
Haynes Mathew George03c40102016-01-29 17:57:48 -08003782 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003783
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003784 /*
3785 * Instead of writing zeroes here, we could trust the hardware
3786 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003787 * 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 -08003788 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08003789 if (ret == 0 && adev->mic_muted &&
3790 !voice_is_in_call_rec_stream(in) &&
3791 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003792 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07003793 in->frames_muted += frames;
3794 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003795
3796exit:
3797 pthread_mutex_unlock(&in->lock);
3798
3799 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07003800 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003801 in_standby(&in->stream.common);
3802 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003803 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003804 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07003805 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08003806 }
3807 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003808 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003809 }
3810 return bytes;
3811}
3812
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003813static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003814{
3815 return 0;
3816}
3817
Andy Hung6ebe5962016-01-15 17:46:57 -08003818static int in_get_capture_position(const struct audio_stream_in *stream,
3819 int64_t *frames, int64_t *time)
3820{
3821 if (stream == NULL || frames == NULL || time == NULL) {
3822 return -EINVAL;
3823 }
3824 struct stream_in *in = (struct stream_in *)stream;
3825 int ret = -ENOSYS;
3826
3827 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003828 // note: ST sessions do not close the alsa pcm driver synchronously
3829 // on standby. Therefore, we may return an error even though the
3830 // pcm stream is still opened.
3831 if (in->standby) {
3832 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
3833 "%s stream in standby but pcm not NULL for non ST session", __func__);
3834 goto exit;
3835 }
Andy Hung6ebe5962016-01-15 17:46:57 -08003836 if (in->pcm) {
3837 struct timespec timestamp;
3838 unsigned int avail;
3839 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3840 *frames = in->frames_read + avail;
3841 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3842 ret = 0;
3843 }
3844 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003845exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08003846 pthread_mutex_unlock(&in->lock);
3847 return ret;
3848}
3849
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003850static int add_remove_audio_effect(const struct audio_stream *stream,
3851 effect_handle_t effect,
3852 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003853{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003854 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003855 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003856 int status = 0;
3857 effect_descriptor_t desc;
3858
3859 status = (*effect)->get_descriptor(effect, &desc);
3860 if (status != 0)
3861 return status;
3862
Eric Laurenta1478072015-09-21 17:21:52 -07003863 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003864 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003865 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003866 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003867 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003868 in->enable_aec != enable &&
3869 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3870 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003871 if (!enable)
3872 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003873 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3874 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3875 adev->enable_voicerx = enable;
3876 struct audio_usecase *usecase;
3877 struct listnode *node;
3878 list_for_each(node, &adev->usecase_list) {
3879 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07003880 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07003881 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05003882 }
3883 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003884 if (!in->standby)
3885 select_devices(in->dev, in->usecase);
3886 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003887 if (in->enable_ns != enable &&
3888 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3889 in->enable_ns = enable;
3890 if (!in->standby)
3891 select_devices(in->dev, in->usecase);
3892 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003893 pthread_mutex_unlock(&in->dev->lock);
3894 pthread_mutex_unlock(&in->lock);
3895
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003896 return 0;
3897}
3898
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003899static int in_add_audio_effect(const struct audio_stream *stream,
3900 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003901{
Eric Laurent994a6932013-07-17 11:51:42 -07003902 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003903 return add_remove_audio_effect(stream, effect, true);
3904}
3905
3906static int in_remove_audio_effect(const struct audio_stream *stream,
3907 effect_handle_t effect)
3908{
Eric Laurent994a6932013-07-17 11:51:42 -07003909 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003910 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003911}
3912
Eric Laurent0e46adf2016-12-16 12:49:24 -08003913static int in_stop(const struct audio_stream_in* stream)
3914{
3915 struct stream_in *in = (struct stream_in *)stream;
3916 struct audio_device *adev = in->dev;
3917
3918 int ret = -ENOSYS;
3919 ALOGV("%s", __func__);
3920 pthread_mutex_lock(&adev->lock);
3921 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3922 in->capture_started && in->pcm != NULL) {
3923 pcm_stop(in->pcm);
3924 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003925 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003926 }
3927 pthread_mutex_unlock(&adev->lock);
3928 return ret;
3929}
3930
3931static int in_start(const struct audio_stream_in* stream)
3932{
3933 struct stream_in *in = (struct stream_in *)stream;
3934 struct audio_device *adev = in->dev;
3935 int ret = -ENOSYS;
3936
3937 ALOGV("%s in %p", __func__, in);
3938 pthread_mutex_lock(&adev->lock);
3939 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3940 !in->capture_started && in->pcm != NULL) {
3941 if (!in->capture_started) {
3942 ret = start_input_stream(in);
3943 if (ret == 0) {
3944 in->capture_started = true;
3945 }
3946 }
3947 }
3948 pthread_mutex_unlock(&adev->lock);
3949 return ret;
3950}
3951
3952static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3953 int32_t min_size_frames,
3954 struct audio_mmap_buffer_info *info)
3955{
3956 struct stream_in *in = (struct stream_in *)stream;
3957 struct audio_device *adev = in->dev;
3958 int ret = 0;
3959 unsigned int offset1;
3960 unsigned int frames1;
3961 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003962 uint32_t mmap_size;
3963 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003964
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003965 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003966 pthread_mutex_lock(&adev->lock);
3967 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003968
Eric Laurent0e46adf2016-12-16 12:49:24 -08003969 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003970 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003971 ret = -EINVAL;
3972 goto exit;
3973 }
3974 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003975 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003976 ALOGV("%s in %p", __func__, in);
3977 ret = -ENOSYS;
3978 goto exit;
3979 }
3980 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3981 if (in->pcm_device_id < 0) {
3982 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3983 __func__, in->pcm_device_id, in->usecase);
3984 ret = -EINVAL;
3985 goto exit;
3986 }
Phil Burkbc991042017-02-24 08:06:44 -08003987
3988 adjust_mmap_period_count(&in->config, min_size_frames);
3989
Eric Laurent0e46adf2016-12-16 12:49:24 -08003990 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3991 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3992 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3993 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3994 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3995 step = "open";
3996 ret = -ENODEV;
3997 goto exit;
3998 }
3999
4000 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
4001 if (ret < 0) {
4002 step = "begin";
4003 goto exit;
4004 }
4005 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07004006 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004007 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07004008 ret = platform_get_mmap_data_fd(adev->platform,
4009 in->pcm_device_id, 1 /*capture*/,
4010 &info->shared_memory_fd,
4011 &mmap_size);
4012 if (ret < 0) {
4013 // Fall back to non exclusive mode
4014 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
4015 } else {
4016 if (mmap_size < buffer_size) {
4017 step = "mmap";
4018 goto exit;
4019 }
4020 // FIXME: indicate exclusive mode support by returning a negative buffer size
4021 info->buffer_size_frames *= -1;
4022 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08004023
Haynes Mathew George96483a22017-03-28 14:52:47 -07004024 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004025
4026 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4027 if (ret < 0) {
4028 step = "commit";
4029 goto exit;
4030 }
4031
Phil Burkbc991042017-02-24 08:06:44 -08004032 in->standby = false;
4033 ret = 0;
4034
Eric Laurent0e46adf2016-12-16 12:49:24 -08004035 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4036 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004037
4038exit:
4039 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004040 if (in->pcm == NULL) {
4041 ALOGE("%s: %s - %d", __func__, step, ret);
4042 } else {
4043 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08004044 pcm_close(in->pcm);
4045 in->pcm = NULL;
4046 }
4047 }
4048 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004049 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004050 return ret;
4051}
4052
4053static int in_get_mmap_position(const struct audio_stream_in *stream,
4054 struct audio_mmap_position *position)
4055{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004056 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004057 struct stream_in *in = (struct stream_in *)stream;
4058 ALOGVV("%s", __func__);
4059 if (position == NULL) {
4060 return -EINVAL;
4061 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004062 lock_input_stream(in);
4063 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
4064 in->pcm == NULL) {
4065 ret = -ENOSYS;
4066 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004067 }
4068 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004069 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004070 if (ret < 0) {
4071 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004072 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004073 }
Andy Hungfc044e12017-03-20 09:24:22 -07004074 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004075exit:
4076 pthread_mutex_unlock(&in->lock);
4077 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004078}
4079
jiabin8962a4d2018-03-19 18:21:24 -07004080static int in_get_active_microphones(const struct audio_stream_in *stream,
4081 struct audio_microphone_characteristic_t *mic_array,
4082 size_t *mic_count) {
4083 struct stream_in *in = (struct stream_in *)stream;
4084 struct audio_device *adev = in->dev;
4085 ALOGVV("%s", __func__);
4086
4087 lock_input_stream(in);
4088 pthread_mutex_lock(&adev->lock);
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004089 int ret = platform_get_active_microphones(adev->platform,
jiabin8962a4d2018-03-19 18:21:24 -07004090 audio_channel_count_from_in_mask(in->channel_mask),
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004091 in->usecase, mic_array, mic_count);
jiabin8962a4d2018-03-19 18:21:24 -07004092 pthread_mutex_unlock(&adev->lock);
4093 pthread_mutex_unlock(&in->lock);
4094
4095 return ret;
4096}
4097
4098static int adev_get_microphones(const struct audio_hw_device *dev,
4099 struct audio_microphone_characteristic_t *mic_array,
4100 size_t *mic_count) {
4101 struct audio_device *adev = (struct audio_device *)dev;
4102 ALOGVV("%s", __func__);
4103
4104 pthread_mutex_lock(&adev->lock);
4105 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
4106 pthread_mutex_unlock(&adev->lock);
4107
4108 return ret;
4109}
Eric Laurent0e46adf2016-12-16 12:49:24 -08004110
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004111static int adev_open_output_stream(struct audio_hw_device *dev,
4112 audio_io_handle_t handle,
4113 audio_devices_t devices,
4114 audio_output_flags_t flags,
4115 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07004116 struct audio_stream_out **stream_out,
4117 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004118{
4119 struct audio_device *adev = (struct audio_device *)dev;
4120 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004121 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004122 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
4123 bool is_usb_dev = audio_is_usb_out_device(devices) &&
4124 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004125
Andy Hungd9653bd2017-08-01 19:31:39 -07004126 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
4127 return -ENOSYS;
4128 }
4129
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004130 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
4131 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004132 *stream_out = NULL;
4133 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4134
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004135 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
4136
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004137 if (devices == AUDIO_DEVICE_NONE)
4138 devices = AUDIO_DEVICE_OUT_SPEAKER;
4139
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004140 out->flags = flags;
4141 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004142 out->dev = adev;
Eric Laurentc4aef752013-09-12 17:45:53 -07004143 out->handle = handle;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004144 out->a2dp_compress_mute = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004145
4146 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004147 if ((is_hdmi || is_usb_dev) &&
4148 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
4149 (flags == AUDIO_OUTPUT_FLAG_NONE ||
4150 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Eric Laurentab805ee2018-03-30 12:20:38 -07004151 audio_format_t req_format = config->format;
4152 audio_channel_mask_t req_channel_mask = config->channel_mask;
4153 uint32_t req_sample_rate = config->sample_rate;
4154
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004155 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004156 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004157 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004158 if (config->sample_rate == 0)
4159 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Eric Laurentab805ee2018-03-30 12:20:38 -07004160 if (config->channel_mask == AUDIO_CHANNEL_NONE)
Haynes Mathew George569b7482017-05-08 14:44:27 -07004161 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
4162 if (config->format == AUDIO_FORMAT_DEFAULT)
4163 config->format = AUDIO_FORMAT_PCM_16_BIT;
4164 } else if (is_usb_dev) {
4165 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
4166 &config->format,
4167 &out->supported_formats[0],
4168 MAX_SUPPORTED_FORMATS,
4169 &config->channel_mask,
4170 &out->supported_channel_masks[0],
4171 MAX_SUPPORTED_CHANNEL_MASKS,
4172 &config->sample_rate,
4173 &out->supported_sample_rates[0],
4174 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004175 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004176 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004177 pthread_mutex_unlock(&adev->lock);
Eric Laurentab805ee2018-03-30 12:20:38 -07004178 if (ret != 0) {
4179 // For MMAP NO IRQ, allow conversions in ADSP
4180 if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
4181 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004182
Eric Laurentab805ee2018-03-30 12:20:38 -07004183 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
4184 config->sample_rate = req_sample_rate;
4185 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
4186 config->channel_mask = req_channel_mask;
4187 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
4188 config->format = req_format;
4189 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004190
Haynes Mathew George569b7482017-05-08 14:44:27 -07004191 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004192 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004193 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004194 if (is_hdmi) {
4195 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4196 out->config = pcm_config_hdmi_multi;
4197 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
4198 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4199 out->config = pcm_config_mmap_playback;
4200 out->stream.start = out_start;
4201 out->stream.stop = out_stop;
4202 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4203 out->stream.get_mmap_position = out_get_mmap_position;
4204 } else {
4205 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4206 out->config = pcm_config_hifi;
4207 }
4208
4209 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004210 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004211 if (is_hdmi) {
4212 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
4213 audio_bytes_per_sample(out->format));
4214 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004215 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004216 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07004217 pthread_mutex_lock(&adev->lock);
4218 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4219 pthread_mutex_unlock(&adev->lock);
4220
4221 // reject offload during card offline to allow
4222 // fallback to s/w paths
4223 if (offline) {
4224 ret = -ENODEV;
4225 goto error_open;
4226 }
4227
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004228 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4229 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4230 ALOGE("%s: Unsupported Offload information", __func__);
4231 ret = -EINVAL;
4232 goto error_open;
4233 }
4234 if (!is_supported_format(config->offload_info.format)) {
4235 ALOGE("%s: Unsupported audio format", __func__);
4236 ret = -EINVAL;
4237 goto error_open;
4238 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004239 out->sample_rate = config->offload_info.sample_rate;
4240 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
4241 out->channel_mask = config->offload_info.channel_mask;
4242 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
4243 out->channel_mask = config->channel_mask;
4244 else
4245 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4246
4247 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004248
4249 out->compr_config.codec = (struct snd_codec *)
4250 calloc(1, sizeof(struct snd_codec));
4251
4252 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004253
4254 out->stream.set_callback = out_set_callback;
4255 out->stream.pause = out_pause;
4256 out->stream.resume = out_resume;
4257 out->stream.drain = out_drain;
4258 out->stream.flush = out_flush;
4259
4260 out->compr_config.codec->id =
4261 get_snd_codec_id(config->offload_info.format);
4262 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
4263 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004264 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004265 out->compr_config.codec->bit_rate =
4266 config->offload_info.bit_rate;
4267 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004268 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004269 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
4270
4271 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4272 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004273
4274 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004275 create_offload_callback_thread(out);
4276 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4277 __func__, config->offload_info.version,
4278 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02004279 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4280 switch (config->sample_rate) {
4281 case 0:
4282 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4283 break;
4284 case 8000:
4285 case 16000:
4286 case 48000:
4287 out->sample_rate = config->sample_rate;
4288 break;
4289 default:
4290 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
4291 config->sample_rate);
4292 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4293 ret = -EINVAL;
4294 goto error_open;
4295 }
4296 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4297 switch (config->channel_mask) {
4298 case AUDIO_CHANNEL_NONE:
4299 case AUDIO_CHANNEL_OUT_STEREO:
4300 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4301 break;
4302 default:
4303 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
4304 config->channel_mask);
4305 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4306 ret = -EINVAL;
4307 goto error_open;
4308 }
4309 switch (config->format) {
4310 case AUDIO_FORMAT_DEFAULT:
4311 case AUDIO_FORMAT_PCM_16_BIT:
4312 out->format = AUDIO_FORMAT_PCM_16_BIT;
4313 break;
4314 default:
4315 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
4316 config->format);
4317 config->format = AUDIO_FORMAT_PCM_16_BIT;
4318 ret = -EINVAL;
4319 goto error_open;
4320 }
4321
4322 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004323 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004324 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004325 case 0:
4326 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
4327 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07004328 case 8000:
4329 case 16000:
4330 case 48000:
4331 out->sample_rate = config->sample_rate;
4332 break;
4333 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004334 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
4335 config->sample_rate);
4336 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4337 ret = -EINVAL;
4338 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004339 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004340 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4341 switch (config->channel_mask) {
4342 case AUDIO_CHANNEL_NONE:
4343 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4344 break;
4345 case AUDIO_CHANNEL_OUT_STEREO:
4346 out->channel_mask = config->channel_mask;
4347 break;
4348 default:
4349 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
4350 config->channel_mask);
4351 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4352 ret = -EINVAL;
4353 break;
4354 }
4355 switch (config->format) {
4356 case AUDIO_FORMAT_DEFAULT:
4357 out->format = AUDIO_FORMAT_PCM_16_BIT;
4358 break;
4359 case AUDIO_FORMAT_PCM_16_BIT:
4360 out->format = config->format;
4361 break;
4362 default:
4363 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
4364 config->format);
4365 config->format = AUDIO_FORMAT_PCM_16_BIT;
4366 ret = -EINVAL;
4367 break;
4368 }
4369 if (ret != 0)
4370 goto error_open;
4371
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004372 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4373 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004374 out->config.rate = out->sample_rate;
4375 out->config.channels =
4376 audio_channel_count_from_out_mask(out->channel_mask);
4377 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004378 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004379 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
4380 switch (config->sample_rate) {
4381 case 0:
4382 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4383 break;
4384 case 8000:
4385 case 16000:
4386 case 32000:
4387 case 48000:
4388 out->sample_rate = config->sample_rate;
4389 break;
4390 default:
4391 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
4392 config->sample_rate);
4393 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4394 ret = -EINVAL;
4395 break;
4396 }
Eric Laurentad2dde92017-09-20 18:27:31 -07004397 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004398 switch (config->channel_mask) {
4399 case AUDIO_CHANNEL_NONE:
4400 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4401 break;
4402 case AUDIO_CHANNEL_OUT_STEREO:
4403 out->channel_mask = config->channel_mask;
4404 break;
4405 default:
4406 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
4407 config->channel_mask);
4408 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4409 ret = -EINVAL;
4410 break;
4411 }
4412 switch (config->format) {
4413 case AUDIO_FORMAT_DEFAULT:
4414 out->format = AUDIO_FORMAT_PCM_16_BIT;
4415 break;
4416 case AUDIO_FORMAT_PCM_16_BIT:
4417 out->format = config->format;
4418 break;
4419 default:
4420 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
4421 config->format);
4422 config->format = AUDIO_FORMAT_PCM_16_BIT;
4423 ret = -EINVAL;
4424 break;
4425 }
4426 if (ret != 0)
4427 goto error_open;
4428
vivek mehtaa68fea62017-06-08 19:04:02 -07004429 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07004430 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4431 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004432 out->config.rate = out->sample_rate;
4433 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07004434 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004435 out->sample_rate,
4436 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07004437 out->config.channels,
4438 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004439 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07004440 out->config.period_size = buffer_size / frame_size;
4441 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
4442 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004443 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004444 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07004445 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4446 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004447 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07004448 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
4449 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004450 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07004451 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004452 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004453 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004454 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004455 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4456 out->config = pcm_config_mmap_playback;
4457 out->stream.start = out_start;
4458 out->stream.stop = out_stop;
4459 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4460 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004461 } else {
4462 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4463 out->config = pcm_config_low_latency;
4464 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004465
4466 if (config->sample_rate == 0) {
4467 out->sample_rate = out->config.rate;
4468 } else {
4469 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004470 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004471 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
4472 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
4473 } else {
4474 out->channel_mask = config->channel_mask;
4475 }
4476 if (config->format == AUDIO_FORMAT_DEFAULT)
4477 out->format = audio_format_from_pcm_format(out->config.format);
4478 else if (!audio_is_linear_pcm(config->format)) {
4479 config->format = AUDIO_FORMAT_PCM_16_BIT;
4480 ret = -EINVAL;
4481 goto error_open;
4482 } else {
4483 out->format = config->format;
4484 }
4485
4486 out->config.rate = out->sample_rate;
4487 out->config.channels =
4488 audio_channel_count_from_out_mask(out->channel_mask);
4489 if (out->format != audio_format_from_pcm_format(out->config.format)) {
4490 out->config.format = pcm_format_from_audio_format(out->format);
4491 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004492 }
Kevin Rocard50eff892017-05-02 16:52:05 -07004493
4494 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
4495 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004496 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004497 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
4498 __func__, config->sample_rate, config->format, config->channel_mask);
4499 config->sample_rate = out->sample_rate;
4500 config->format = out->format;
4501 config->channel_mask = out->channel_mask;
4502 ret = -EINVAL;
4503 goto error_open;
4504 }
4505
Andy Hung6fcba9c2014-03-18 11:53:32 -07004506 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
4507 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004508
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004509 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004510 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004511 adev->primary_output = out;
4512 else {
4513 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004514 ret = -EEXIST;
4515 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004516 }
4517 }
4518
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004519 /* Check if this usecase is already existing */
4520 pthread_mutex_lock(&adev->lock);
4521 if (get_usecase_from_list(adev, out->usecase) != NULL) {
4522 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004523 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004524 ret = -EEXIST;
4525 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004526 }
4527 pthread_mutex_unlock(&adev->lock);
4528
4529 out->stream.common.get_sample_rate = out_get_sample_rate;
4530 out->stream.common.set_sample_rate = out_set_sample_rate;
4531 out->stream.common.get_buffer_size = out_get_buffer_size;
4532 out->stream.common.get_channels = out_get_channels;
4533 out->stream.common.get_format = out_get_format;
4534 out->stream.common.set_format = out_set_format;
4535 out->stream.common.standby = out_standby;
4536 out->stream.common.dump = out_dump;
4537 out->stream.common.set_parameters = out_set_parameters;
4538 out->stream.common.get_parameters = out_get_parameters;
4539 out->stream.common.add_audio_effect = out_add_audio_effect;
4540 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4541 out->stream.get_latency = out_get_latency;
4542 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004543#ifdef NO_AUDIO_OUT
4544 out->stream.write = out_write_for_no_output;
4545#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004546 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004547#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004548 out->stream.get_render_position = out_get_render_position;
4549 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004550 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004551
Eric Laurent0e46adf2016-12-16 12:49:24 -08004552 if (out->realtime)
4553 out->af_period_multiplier = af_period_multiplier;
4554 else
4555 out->af_period_multiplier = 1;
4556
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004557 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004558 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004559 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004560
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004561 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004562 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004563 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4564
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004565 config->format = out->stream.common.get_format(&out->stream.common);
4566 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4567 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4568
Kevin Rocarda325aa22018-04-03 09:15:52 -07004569 register_format(out->format, out->supported_formats);
4570 register_channel_mask(out->channel_mask, out->supported_channel_masks);
4571 register_sample_rate(out->sample_rate, out->supported_sample_rates);
4572
Andy Hunga452b0a2017-03-15 14:51:15 -07004573 out->error_log = error_log_create(
4574 ERROR_LOG_ENTRIES,
4575 1000000000 /* aggregate consecutive identical errors within one second in ns */);
4576
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004577 /*
4578 By locking output stream before registering, we allow the callback
4579 to update stream's state only after stream's initial state is set to
4580 adev state.
4581 */
4582 lock_output_stream(out);
4583 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4584 pthread_mutex_lock(&adev->lock);
4585 out->card_status = adev->card_status;
4586 pthread_mutex_unlock(&adev->lock);
4587 pthread_mutex_unlock(&out->lock);
4588
vivek mehta4a824772017-06-08 19:05:49 -07004589 stream_app_type_cfg_init(&out->app_type_cfg);
4590
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004591 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004592
Eric Laurent994a6932013-07-17 11:51:42 -07004593 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004594 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004595
4596error_open:
4597 free(out);
4598 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07004599 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004600 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004601}
4602
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004603static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004604 struct audio_stream_out *stream)
4605{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004606 struct stream_out *out = (struct stream_out *)stream;
4607 struct audio_device *adev = out->dev;
4608
Eric Laurent994a6932013-07-17 11:51:42 -07004609 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004610
4611 // must deregister from sndmonitor first to prevent races
4612 // between the callback and close_stream
4613 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004614 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004615 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
4616 destroy_offload_callback_thread(out);
4617
4618 if (out->compr_config.codec != NULL)
4619 free(out->compr_config.codec);
4620 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004621
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004622 out->a2dp_compress_mute = false;
4623
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004624 if (adev->voice_tx_output == out)
4625 adev->voice_tx_output = NULL;
4626
Andy Hunga452b0a2017-03-15 14:51:15 -07004627 error_log_destroy(out->error_log);
4628 out->error_log = NULL;
4629
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004630 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004631 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004632 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004633 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004634 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004635}
4636
4637static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4638{
4639 struct audio_device *adev = (struct audio_device *)dev;
4640 struct str_parms *parms;
4641 char *str;
4642 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004643 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004644 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07004645 int status = 0;
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004646 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004647
Joe Onorato188b6222016-03-01 11:02:27 -08004648 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004649
4650 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004651
4652 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004653 status = voice_set_parameters(adev, parms);
4654 if (status != 0) {
4655 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004656 }
4657
4658 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4659 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07004660 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004661 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4662 adev->bluetooth_nrec = true;
4663 else
4664 adev->bluetooth_nrec = false;
4665 }
4666
4667 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4668 if (ret >= 0) {
4669 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4670 adev->screen_off = false;
4671 else
4672 adev->screen_off = true;
4673 }
4674
jasmine cha270b7762018-03-30 15:41:33 +08004675#ifndef MAXXAUDIO_QDSP_ENABLED
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004676 ret = str_parms_get_int(parms, "rotation", &val);
4677 if (ret >= 0) {
4678 bool reverse_speakers = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004679 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004680 // FIXME: note that the code below assumes that the speakers are in the correct placement
4681 // relative to the user when the device is rotated 90deg from its default rotation. This
4682 // assumption is device-specific, not platform-specific like this code.
4683 case 270:
4684 reverse_speakers = true;
4685 break;
4686 case 0:
4687 case 90:
4688 case 180:
4689 break;
4690 default:
4691 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07004692 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004693 }
Eric Laurent03f09432014-03-25 18:09:11 -07004694 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004695 // check and set swap
4696 // - check if orientation changed and speaker active
4697 // - set rotation and cache the rotation value
4698 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004699 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004700 }
jasmine cha270b7762018-03-30 15:41:33 +08004701#endif
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004702
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004703 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4704 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004705 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004706 }
4707
David Linee3fe402017-03-13 10:00:42 -07004708 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4709 if (ret >= 0) {
4710 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004711 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004712 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4713 if (ret >= 0) {
4714 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004715 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004716 }
Eric Laurent99dab492017-06-17 15:19:08 -07004717 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004718 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4719 if (ret >= 0) {
4720 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004721 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004722 }
4723 }
4724 }
4725
4726 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4727 if (ret >= 0) {
4728 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004729 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004730 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4731 if (ret >= 0) {
4732 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004733 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004734 }
Eric Laurent99dab492017-06-17 15:19:08 -07004735 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004736 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4737 if (ret >= 0) {
4738 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004739 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004740 }
4741 }
4742 }
4743
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004744 audio_extn_hfp_set_parameters(adev, parms);
jasmine cha270b7762018-03-30 15:41:33 +08004745 audio_extn_ma_set_parameters(adev, parms);
4746
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004747 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
4748 if (status >= 0 && a2dp_reconfig) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004749 struct audio_usecase *usecase;
4750 struct listnode *node;
4751 list_for_each(node, &adev->usecase_list) {
4752 usecase = node_to_item(node, struct audio_usecase, list);
4753 if ((usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004754 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004755 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
4756
4757 pthread_mutex_unlock(&adev->lock);
4758 lock_output_stream(usecase->stream.out);
4759 pthread_mutex_lock(&adev->lock);
4760 audio_extn_a2dp_set_handoff_mode(true);
4761 // force device switch to reconfigure encoder
4762 select_devices(adev, usecase->id);
4763 audio_extn_a2dp_set_handoff_mode(false);
4764 pthread_mutex_unlock(&usecase->stream.out->lock);
4765 break;
4766 }
4767 }
4768 }
4769
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004770done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004771 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004772 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004773 ALOGV("%s: exit with code(%d)", __func__, status);
4774 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004775}
4776
4777static char* adev_get_parameters(const struct audio_hw_device *dev,
4778 const char *keys)
4779{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004780 struct audio_device *adev = (struct audio_device *)dev;
4781 struct str_parms *reply = str_parms_create();
4782 struct str_parms *query = str_parms_create_str(keys);
4783 char *str;
4784
4785 pthread_mutex_lock(&adev->lock);
4786
4787 voice_get_parameters(adev, query, reply);
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004788 audio_extn_a2dp_get_parameters(query, reply);
4789
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004790 str = str_parms_to_str(reply);
4791 str_parms_destroy(query);
4792 str_parms_destroy(reply);
4793
4794 pthread_mutex_unlock(&adev->lock);
4795 ALOGV("%s: exit: returns - %s", __func__, str);
4796 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004797}
4798
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004799static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004800{
4801 return 0;
4802}
4803
Haynes Mathew George5191a852013-09-11 14:19:36 -07004804static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4805{
4806 int ret;
4807 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004808
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004809 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4810
Haynes Mathew George5191a852013-09-11 14:19:36 -07004811 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004812 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004813 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004814
Haynes Mathew George5191a852013-09-11 14:19:36 -07004815 return ret;
4816}
4817
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004818static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004819{
4820 return -ENOSYS;
4821}
4822
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004823static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4824 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004825{
4826 return -ENOSYS;
4827}
4828
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004829static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004830{
4831 return -ENOSYS;
4832}
4833
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004834static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004835{
4836 return -ENOSYS;
4837}
4838
4839static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4840{
4841 struct audio_device *adev = (struct audio_device *)dev;
4842
4843 pthread_mutex_lock(&adev->lock);
4844 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004845 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004846 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004847 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4848 voice_is_in_call(adev)) {
4849 voice_stop_call(adev);
4850 adev->current_call_output = NULL;
4851 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004852 }
4853 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004854
4855 audio_extn_extspk_set_mode(adev->extspk, mode);
4856
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004857 return 0;
4858}
4859
4860static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4861{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004862 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004863 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004864
Eric Laurent2bafff12016-03-17 12:17:23 -07004865 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004866 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004867 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4868 ret = audio_extn_hfp_set_mic_mute(adev, state);
4869 } else {
4870 ret = voice_set_mic_mute(adev, state);
4871 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004872 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004873 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004874
4875 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004876}
4877
4878static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4879{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004880 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004881 return 0;
4882}
4883
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004884static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004885 const struct audio_config *config)
4886{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004887 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004888
Eric Laurent74b55762017-07-09 17:04:53 -07004889 /* Don't know if USB HIFI in this context so use true to be conservative */
4890 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4891 true /*is_usb_hifi */) != 0)
4892 return 0;
4893
vivek mehtaa68fea62017-06-08 19:04:02 -07004894 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4895 config->sample_rate, config->format,
4896 channel_count,
4897 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004898}
4899
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004900static bool adev_input_allow_hifi_record(struct audio_device *adev,
4901 audio_devices_t devices,
4902 audio_input_flags_t flags,
4903 audio_source_t source) {
4904 const bool allowed = true;
4905
4906 if (!audio_is_usb_in_device(devices))
4907 return !allowed;
4908
4909 switch (flags) {
4910 case AUDIO_INPUT_FLAG_NONE:
4911 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4912 break;
4913 default:
4914 return !allowed;
4915 }
4916
4917 switch (source) {
4918 case AUDIO_SOURCE_DEFAULT:
4919 case AUDIO_SOURCE_MIC:
4920 case AUDIO_SOURCE_UNPROCESSED:
4921 break;
4922 default:
4923 return !allowed;
4924 }
4925
4926 switch (adev->mode) {
4927 case 0:
4928 break;
4929 default:
4930 return !allowed;
4931 }
4932
4933 return allowed;
4934}
4935
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004936static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004937 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004938 audio_devices_t devices,
4939 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004940 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004941 audio_input_flags_t flags,
4942 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004943 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004944{
4945 struct audio_device *adev = (struct audio_device *)dev;
4946 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004947 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004948 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004949 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004950 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004951 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4952 devices,
4953 flags,
4954 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004955 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004956 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004957
Andy Hungd9653bd2017-08-01 19:31:39 -07004958 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
4959 return -ENOSYS;
4960 }
4961
Eric Laurent74b55762017-07-09 17:04:53 -07004962 if (!(is_usb_dev && may_use_hifi_record)) {
4963 if (config->sample_rate == 0)
4964 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4965 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4966 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4967 if (config->format == AUDIO_FORMAT_DEFAULT)
4968 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004969
Eric Laurent74b55762017-07-09 17:04:53 -07004970 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
4971
4972 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
4973 return -EINVAL;
4974 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004975
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004976 if (audio_extn_tfa_98xx_is_supported() &&
4977 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004978 return -EINVAL;
4979
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004980 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4981
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004982 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004983 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004984
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004985 in->stream.common.get_sample_rate = in_get_sample_rate;
4986 in->stream.common.set_sample_rate = in_set_sample_rate;
4987 in->stream.common.get_buffer_size = in_get_buffer_size;
4988 in->stream.common.get_channels = in_get_channels;
4989 in->stream.common.get_format = in_get_format;
4990 in->stream.common.set_format = in_set_format;
4991 in->stream.common.standby = in_standby;
4992 in->stream.common.dump = in_dump;
4993 in->stream.common.set_parameters = in_set_parameters;
4994 in->stream.common.get_parameters = in_get_parameters;
4995 in->stream.common.add_audio_effect = in_add_audio_effect;
4996 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4997 in->stream.set_gain = in_set_gain;
4998 in->stream.read = in_read;
4999 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08005000 in->stream.get_capture_position = in_get_capture_position;
jiabin8962a4d2018-03-19 18:21:24 -07005001 in->stream.get_active_microphones = in_get_active_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005002
5003 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005004 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005005 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005006 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005007 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005008 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005009
Arun Mirpuriba2749a2018-04-17 14:32:24 -07005010 ALOGV("%s: source = %d, config->channel_mask = %d", __func__, source, config->channel_mask);
5011 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
5012 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
5013 /* Force channel config requested to mono if incall
5014 record is being requested for only uplink/downlink */
5015 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
5016 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5017 ret = -EINVAL;
5018 goto err_open;
5019 }
5020 }
5021
Haynes Mathew George569b7482017-05-08 14:44:27 -07005022 if (is_usb_dev && may_use_hifi_record) {
5023 /* HiFi record selects an appropriate format, channel, rate combo
5024 depending on sink capabilities*/
5025 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
5026 &config->format,
5027 &in->supported_formats[0],
5028 MAX_SUPPORTED_FORMATS,
5029 &config->channel_mask,
5030 &in->supported_channel_masks[0],
5031 MAX_SUPPORTED_CHANNEL_MASKS,
5032 &config->sample_rate,
5033 &in->supported_sample_rates[0],
5034 MAX_SUPPORTED_SAMPLE_RATES);
5035 if (ret != 0) {
5036 ret = -EINVAL;
5037 goto err_open;
5038 }
Eric Laurent74b55762017-07-09 17:04:53 -07005039 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005040 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07005041 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07005042 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
5043 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
5044 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5045 bool ret_error = false;
5046 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5047 from HAL is 8_24
5048 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5049 8_24 return error indicating supported format is 8_24
5050 *> In case of any other source requesting 24 bit or float return error
5051 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07005052
vivek mehta57ff9b52016-04-28 14:13:08 -07005053 on error flinger will retry with supported format passed
5054 */
5055 if (source != AUDIO_SOURCE_UNPROCESSED) {
5056 config->format = AUDIO_FORMAT_PCM_16_BIT;
5057 ret_error = true;
5058 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
5059 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
5060 ret_error = true;
5061 }
5062
5063 if (ret_error) {
5064 ret = -EINVAL;
5065 goto err_open;
5066 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005067 }
5068
vivek mehta57ff9b52016-04-28 14:13:08 -07005069 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07005070 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07005071
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005072 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005073 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
5074 if (config->sample_rate == 0)
5075 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5076 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5077 config->sample_rate != 8000) {
5078 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5079 ret = -EINVAL;
5080 goto err_open;
5081 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005082
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005083 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5084 config->format = AUDIO_FORMAT_PCM_16_BIT;
5085 ret = -EINVAL;
5086 goto err_open;
5087 }
5088
5089 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5090 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07005091 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005092 } else if (is_usb_dev && may_use_hifi_record) {
5093 in->usecase = USECASE_AUDIO_RECORD_HIFI;
5094 in->config = pcm_config_audio_capture;
5095 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005096 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5097 config->sample_rate,
5098 config->format,
5099 channel_count,
5100 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005101 in->config.period_size = buffer_size / frame_size;
5102 in->config.rate = config->sample_rate;
5103 in->af_period_multiplier = 1;
5104 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005105 } else {
5106 in->usecase = USECASE_AUDIO_RECORD;
5107 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08005108 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005109 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07005110#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005111 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07005112#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08005113 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005114 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08005115 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005116 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005117 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5118 config->sample_rate,
5119 config->format,
5120 channel_count,
5121 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005122 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005123 in->config.rate = config->sample_rate;
5124 in->af_period_multiplier = 1;
5125 } else {
5126 // period size is left untouched for rt mode playback
5127 in->config = pcm_config_audio_capture_rt;
5128 in->af_period_multiplier = af_period_multiplier;
5129 }
5130 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
5131 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005132 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08005133 in->usecase = USECASE_AUDIO_RECORD_MMAP;
5134 in->config = pcm_config_mmap_capture;
5135 in->stream.start = in_start;
5136 in->stream.stop = in_stop;
5137 in->stream.create_mmap_buffer = in_create_mmap_buffer;
5138 in->stream.get_mmap_position = in_get_mmap_position;
5139 in->af_period_multiplier = 1;
5140 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07005141 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07005142 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07005143 (config->sample_rate == 8000 ||
5144 config->sample_rate == 16000 ||
5145 config->sample_rate == 32000 ||
5146 config->sample_rate == 48000) &&
5147 channel_count == 1) {
5148 in->usecase = USECASE_AUDIO_RECORD_VOIP;
5149 in->config = pcm_config_audio_capture;
5150 frame_size = audio_stream_in_frame_size(&in->stream);
5151 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
5152 config->sample_rate,
5153 config->format,
5154 channel_count, false /*is_low_latency*/);
5155 in->config.period_size = buffer_size / frame_size;
5156 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
5157 in->config.rate = config->sample_rate;
5158 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005159 } else {
5160 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005161 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005162 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5163 config->sample_rate,
5164 config->format,
5165 channel_count,
5166 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005167 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005168 in->config.rate = config->sample_rate;
5169 in->af_period_multiplier = 1;
5170 }
5171 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
5172 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005173 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08005174
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005175 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07005176 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005177
Kevin Rocarda325aa22018-04-03 09:15:52 -07005178
5179 register_format(in->format, in->supported_formats);
5180 register_channel_mask(in->channel_mask, in->supported_channel_masks);
5181 register_sample_rate(in->sample_rate, in->supported_sample_rates);
5182
Andy Hungd13f0d32017-06-12 13:58:37 -07005183 in->error_log = error_log_create(
5184 ERROR_LOG_ENTRIES,
5185 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
5186
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005187 /* This stream could be for sound trigger lab,
5188 get sound trigger pcm if present */
5189 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005190
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005191 lock_input_stream(in);
5192 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5193 pthread_mutex_lock(&adev->lock);
5194 in->card_status = adev->card_status;
5195 pthread_mutex_unlock(&adev->lock);
5196 pthread_mutex_unlock(&in->lock);
5197
vivek mehta4a824772017-06-08 19:05:49 -07005198 stream_app_type_cfg_init(&in->app_type_cfg);
5199
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005200 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005201 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005202 return 0;
5203
5204err_open:
5205 free(in);
5206 *stream_in = NULL;
5207 return ret;
5208}
5209
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005210static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005211 struct audio_stream_in *stream)
5212{
Andy Hungd13f0d32017-06-12 13:58:37 -07005213 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005214 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005215
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005216 // must deregister from sndmonitor first to prevent races
5217 // between the callback and close_stream
5218 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005219 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07005220
5221 error_log_destroy(in->error_log);
5222 in->error_log = NULL;
5223
Andy Hung0dbb52b2017-08-09 13:51:38 -07005224 pthread_mutex_destroy(&in->pre_lock);
5225 pthread_mutex_destroy(&in->lock);
5226
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005227 free(stream);
5228
5229 return;
5230}
5231
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005232static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005233{
5234 return 0;
5235}
5236
Andy Hung31aca912014-03-20 17:14:59 -07005237/* verifies input and output devices and their capabilities.
5238 *
5239 * This verification is required when enabling extended bit-depth or
5240 * sampling rates, as not all qcom products support it.
5241 *
5242 * Suitable for calling only on initialization such as adev_open().
5243 * It fills the audio_device use_case_table[] array.
5244 *
5245 * Has a side-effect that it needs to configure audio routing / devices
5246 * in order to power up the devices and read the device parameters.
5247 * It does not acquire any hw device lock. Should restore the devices
5248 * back to "normal state" upon completion.
5249 */
5250static int adev_verify_devices(struct audio_device *adev)
5251{
5252 /* enumeration is a bit difficult because one really wants to pull
5253 * the use_case, device id, etc from the hidden pcm_device_table[].
5254 * In this case there are the following use cases and device ids.
5255 *
5256 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
5257 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005258 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07005259 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
5260 * [USECASE_AUDIO_RECORD] = {0, 0},
5261 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
5262 * [USECASE_VOICE_CALL] = {2, 2},
5263 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005264 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07005265 * USECASE_VOICE_CALL omitted, but possible for either input or output.
5266 */
5267
5268 /* should be the usecases enabled in adev_open_input_stream() */
5269 static const int test_in_usecases[] = {
5270 USECASE_AUDIO_RECORD,
5271 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
5272 };
5273 /* should be the usecases enabled in adev_open_output_stream()*/
5274 static const int test_out_usecases[] = {
5275 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
5276 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
5277 };
5278 static const usecase_type_t usecase_type_by_dir[] = {
5279 PCM_PLAYBACK,
5280 PCM_CAPTURE,
5281 };
5282 static const unsigned flags_by_dir[] = {
5283 PCM_OUT,
5284 PCM_IN,
5285 };
5286
5287 size_t i;
5288 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005289 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07005290 char info[512]; /* for possible debug info */
5291
5292 for (dir = 0; dir < 2; ++dir) {
5293 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
5294 const unsigned flags_dir = flags_by_dir[dir];
5295 const size_t testsize =
5296 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
5297 const int *testcases =
5298 dir ? test_in_usecases : test_out_usecases;
5299 const audio_devices_t audio_device =
5300 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
5301
5302 for (i = 0; i < testsize; ++i) {
5303 const audio_usecase_t audio_usecase = testcases[i];
5304 int device_id;
5305 snd_device_t snd_device;
5306 struct pcm_params **pparams;
5307 struct stream_out out;
5308 struct stream_in in;
5309 struct audio_usecase uc_info;
5310 int retval;
5311
5312 pparams = &adev->use_case_table[audio_usecase];
5313 pcm_params_free(*pparams); /* can accept null input */
5314 *pparams = NULL;
5315
5316 /* find the device ID for the use case (signed, for error) */
5317 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
5318 if (device_id < 0)
5319 continue;
5320
5321 /* prepare structures for device probing */
5322 memset(&uc_info, 0, sizeof(uc_info));
5323 uc_info.id = audio_usecase;
5324 uc_info.type = usecase_type;
5325 if (dir) {
5326 adev->active_input = &in;
5327 memset(&in, 0, sizeof(in));
5328 in.device = audio_device;
5329 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
5330 uc_info.stream.in = &in;
5331 } else {
5332 adev->active_input = NULL;
5333 }
5334 memset(&out, 0, sizeof(out));
5335 out.devices = audio_device; /* only field needed in select_devices */
5336 uc_info.stream.out = &out;
5337 uc_info.devices = audio_device;
5338 uc_info.in_snd_device = SND_DEVICE_NONE;
5339 uc_info.out_snd_device = SND_DEVICE_NONE;
5340 list_add_tail(&adev->usecase_list, &uc_info.list);
5341
5342 /* select device - similar to start_(in/out)put_stream() */
5343 retval = select_devices(adev, audio_usecase);
5344 if (retval >= 0) {
5345 *pparams = pcm_params_get(card_id, device_id, flags_dir);
5346#if LOG_NDEBUG == 0
5347 if (*pparams) {
5348 ALOGV("%s: (%s) card %d device %d", __func__,
5349 dir ? "input" : "output", card_id, device_id);
5350 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07005351 } else {
5352 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
5353 }
5354#endif
5355 }
5356
5357 /* deselect device - similar to stop_(in/out)put_stream() */
5358 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07005359 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07005360 /* 2. Disable the rx device */
5361 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07005362 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07005363 list_remove(&uc_info.list);
5364 }
5365 }
5366 adev->active_input = NULL; /* restore adev state */
5367 return 0;
5368}
5369
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005370static int adev_close(hw_device_t *device)
5371{
Andy Hung31aca912014-03-20 17:14:59 -07005372 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005373 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005374
5375 if (!adev)
5376 return 0;
5377
5378 pthread_mutex_lock(&adev_init_lock);
5379
5380 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005381 audio_extn_snd_mon_unregister_listener(adev);
5382 audio_extn_tfa_98xx_deinit();
jasmine cha270b7762018-03-30 15:41:33 +08005383 audio_extn_ma_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005384 audio_route_free(adev->audio_route);
5385 free(adev->snd_dev_ref_cnt);
5386 platform_deinit(adev->platform);
5387 audio_extn_extspk_deinit(adev->extspk);
5388 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005389 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005390 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
5391 pcm_params_free(adev->use_case_table[i]);
5392 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005393 if (adev->adm_deinit)
5394 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005395 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005396 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07005397 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07005398
5399 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005400
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005401 return 0;
5402}
5403
Glenn Kasten4f993392014-05-14 07:30:48 -07005404/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5405 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5406 * just that it _might_ work.
5407 */
5408static int period_size_is_plausible_for_low_latency(int period_size)
5409{
5410 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005411 case 48:
5412 case 96:
5413 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07005414 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005415 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07005416 case 240:
5417 case 320:
5418 case 480:
5419 return 1;
5420 default:
5421 return 0;
5422 }
5423}
5424
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005425static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
5426{
5427 int card;
5428 card_status_t status;
5429
5430 if (!parms)
5431 return;
5432
5433 if (parse_snd_card_status(parms, &card, &status) < 0)
5434 return;
5435
5436 pthread_mutex_lock(&adev->lock);
5437 bool valid_cb = (card == adev->snd_card);
5438 if (valid_cb) {
5439 if (adev->card_status != status) {
5440 adev->card_status = status;
5441 platform_snd_card_update(adev->platform, status);
5442 }
5443 }
5444 pthread_mutex_unlock(&adev->lock);
5445 return;
5446}
5447
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005448/* out and adev lock held */
5449static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
5450{
5451 struct audio_usecase *uc_info;
5452 float left_p;
5453 float right_p;
5454 audio_devices_t devices;
5455
5456 uc_info = get_usecase_from_list(adev, out->usecase);
5457 if (uc_info == NULL) {
5458 ALOGE("%s: Could not find the usecase (%d) in the list",
5459 __func__, out->usecase);
5460 return -EINVAL;
5461 }
5462
5463 ALOGD("%s: enter: usecase(%d: %s)", __func__,
5464 out->usecase, use_case_table[out->usecase]);
5465
5466 if (restore) {
5467 // restore A2DP device for active usecases and unmute if required
5468 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
5469 !is_a2dp_device(uc_info->out_snd_device)) {
5470 ALOGD("%s: restoring A2DP and unmuting stream", __func__);
5471 select_devices(adev, uc_info->id);
5472 pthread_mutex_lock(&out->compr_mute_lock);
5473 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5474 (out->a2dp_compress_mute)) {
5475 out->a2dp_compress_mute = false;
5476 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5477 }
5478 pthread_mutex_unlock(&out->compr_mute_lock);
5479 }
5480 } else {
5481 // mute compress stream if suspended
5482 pthread_mutex_lock(&out->compr_mute_lock);
5483 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5484 (!out->a2dp_compress_mute)) {
5485 if (!out->standby) {
5486 ALOGD("%s: selecting speaker and muting stream", __func__);
5487 devices = out->devices;
5488 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
5489 left_p = out->volume_l;
5490 right_p = out->volume_r;
5491 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5492 compress_pause(out->compr);
5493 set_compr_volume(&out->stream, 0.0f, 0.0f);
5494 out->a2dp_compress_mute = true;
5495 select_devices(adev, out->usecase);
5496 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5497 compress_resume(out->compr);
5498 out->devices = devices;
5499 out->volume_l = left_p;
5500 out->volume_r = right_p;
5501 }
5502 }
5503 pthread_mutex_unlock(&out->compr_mute_lock);
5504 }
5505 ALOGV("%s: exit", __func__);
5506 return 0;
5507}
5508
5509int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
5510{
5511 int ret = 0;
5512
5513 lock_output_stream(out);
5514 pthread_mutex_lock(&adev->lock);
5515
5516 ret = check_a2dp_restore_l(adev, out, restore);
5517
5518 pthread_mutex_unlock(&adev->lock);
5519 pthread_mutex_unlock(&out->lock);
5520 return ret;
5521}
5522
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005523static int adev_open(const hw_module_t *module, const char *name,
5524 hw_device_t **device)
5525{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005526 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005527
Eric Laurent2bafff12016-03-17 12:17:23 -07005528 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005529 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005530 pthread_mutex_lock(&adev_init_lock);
5531 if (audio_device_ref_count != 0) {
5532 *device = &adev->device.common;
5533 audio_device_ref_count++;
5534 ALOGV("%s: returning existing instance of adev", __func__);
5535 ALOGV("%s: exit", __func__);
5536 pthread_mutex_unlock(&adev_init_lock);
5537 return 0;
5538 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005539 adev = calloc(1, sizeof(struct audio_device));
5540
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005541 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5542
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005543 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5544 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5545 adev->device.common.module = (struct hw_module_t *)module;
5546 adev->device.common.close = adev_close;
5547
5548 adev->device.init_check = adev_init_check;
5549 adev->device.set_voice_volume = adev_set_voice_volume;
5550 adev->device.set_master_volume = adev_set_master_volume;
5551 adev->device.get_master_volume = adev_get_master_volume;
5552 adev->device.set_master_mute = adev_set_master_mute;
5553 adev->device.get_master_mute = adev_get_master_mute;
5554 adev->device.set_mode = adev_set_mode;
5555 adev->device.set_mic_mute = adev_set_mic_mute;
5556 adev->device.get_mic_mute = adev_get_mic_mute;
5557 adev->device.set_parameters = adev_set_parameters;
5558 adev->device.get_parameters = adev_get_parameters;
5559 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5560 adev->device.open_output_stream = adev_open_output_stream;
5561 adev->device.close_output_stream = adev_close_output_stream;
5562 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005563
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005564 adev->device.close_input_stream = adev_close_input_stream;
5565 adev->device.dump = adev_dump;
jiabin8962a4d2018-03-19 18:21:24 -07005566 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005567
5568 /* Set the default route before the PCM stream is opened */
5569 pthread_mutex_lock(&adev->lock);
5570 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005571 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005572 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005573 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005574 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005575 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005576 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005577 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005578 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005579 pthread_mutex_unlock(&adev->lock);
5580
5581 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005582 adev->platform = platform_init(adev);
5583 if (!adev->platform) {
5584 free(adev->snd_dev_ref_cnt);
5585 free(adev);
5586 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5587 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005588 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005589 return -EINVAL;
5590 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05005591 adev->extspk = audio_extn_extspk_init(adev);
5592
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005593 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5594 if (adev->visualizer_lib == NULL) {
5595 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5596 } else {
5597 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5598 adev->visualizer_start_output =
5599 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5600 "visualizer_hal_start_output");
5601 adev->visualizer_stop_output =
5602 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5603 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07005604 }
5605
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005606 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5607 if (adev->offload_effects_lib == NULL) {
5608 ALOGW("%s: DLOPEN failed for %s", __func__,
5609 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5610 } else {
5611 ALOGV("%s: DLOPEN successful for %s", __func__,
5612 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5613 adev->offload_effects_start_output =
5614 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5615 "offload_effects_bundle_hal_start_output");
5616 adev->offload_effects_stop_output =
5617 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5618 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07005619 }
5620
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005621 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5622 if (adev->adm_lib == NULL) {
5623 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5624 } else {
5625 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5626 adev->adm_init = (adm_init_t)
5627 dlsym(adev->adm_lib, "adm_init");
5628 adev->adm_deinit = (adm_deinit_t)
5629 dlsym(adev->adm_lib, "adm_deinit");
5630 adev->adm_register_input_stream = (adm_register_input_stream_t)
5631 dlsym(adev->adm_lib, "adm_register_input_stream");
5632 adev->adm_register_output_stream = (adm_register_output_stream_t)
5633 dlsym(adev->adm_lib, "adm_register_output_stream");
5634 adev->adm_deregister_stream = (adm_deregister_stream_t)
5635 dlsym(adev->adm_lib, "adm_deregister_stream");
5636 adev->adm_request_focus = (adm_request_focus_t)
5637 dlsym(adev->adm_lib, "adm_request_focus");
5638 adev->adm_abandon_focus = (adm_abandon_focus_t)
5639 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08005640 adev->adm_set_config = (adm_set_config_t)
5641 dlsym(adev->adm_lib, "adm_set_config");
5642 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5643 dlsym(adev->adm_lib, "adm_request_focus_v2");
5644 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5645 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5646 adev->adm_on_routing_change = (adm_on_routing_change_t)
5647 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005648 }
5649
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005650 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005651 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005652
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005653 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005654
Andy Hung31aca912014-03-20 17:14:59 -07005655 if (k_enable_extended_precision)
5656 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005657
Glenn Kasten4f993392014-05-14 07:30:48 -07005658 char value[PROPERTY_VALUE_MAX];
5659 int trial;
5660 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5661 trial = atoi(value);
5662 if (period_size_is_plausible_for_low_latency(trial)) {
5663 pcm_config_low_latency.period_size = trial;
5664 pcm_config_low_latency.start_threshold = trial / 4;
5665 pcm_config_low_latency.avail_min = trial / 4;
5666 configured_low_latency_capture_period_size = trial;
5667 }
5668 }
5669 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5670 trial = atoi(value);
5671 if (period_size_is_plausible_for_low_latency(trial)) {
5672 configured_low_latency_capture_period_size = trial;
5673 }
5674 }
5675
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005676 // commented as full set of app type cfg is sent from platform
5677 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005678 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005679
5680 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5681 af_period_multiplier = atoi(value);
5682 if (af_period_multiplier < 0) {
5683 af_period_multiplier = 2;
5684 } else if (af_period_multiplier > 4) {
5685 af_period_multiplier = 4;
5686 }
5687 ALOGV("new period_multiplier = %d", af_period_multiplier);
5688 }
5689
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005690 audio_extn_tfa_98xx_init(adev);
jasmine cha270b7762018-03-30 15:41:33 +08005691 audio_extn_ma_init(adev->platform);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005692
vivek mehta1a9b7c02015-06-25 11:49:38 -07005693 pthread_mutex_unlock(&adev_init_lock);
5694
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005695 if (adev->adm_init)
5696 adev->adm_data = adev->adm_init();
5697
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005698 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005699 audio_extn_snd_mon_init();
5700 pthread_mutex_lock(&adev->lock);
5701 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
5702 adev->card_status = CARD_STATUS_ONLINE;
5703 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005704 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005705
Eric Laurent2bafff12016-03-17 12:17:23 -07005706 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005707 return 0;
5708}
5709
5710static struct hw_module_methods_t hal_module_methods = {
5711 .open = adev_open,
5712};
5713
5714struct audio_module HAL_MODULE_INFO_SYM = {
5715 .common = {
5716 .tag = HARDWARE_MODULE_TAG,
5717 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5718 .hal_api_version = HARDWARE_HAL_API_VERSION,
5719 .id = AUDIO_HARDWARE_MODULE_ID,
5720 .name = "QCOM Audio HAL",
5721 .author = "Code Aurora Forum",
5722 .methods = &hal_module_methods,
5723 },
5724};