blob: b104319a3b3afc68101d1ca57ffcbe749d8a3c00 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
vivek mehtaa51fd402016-02-04 19:49:33 -08002 * Copyright (C) 2013-2016 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "audio_hw_primary"
Haynes Mathew George03c40102016-01-29 17:57:48 -080018#define ATRACE_TAG ATRACE_TAG_AUDIO
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080019/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070020/*#define VERY_VERY_VERBOSE_LOGGING*/
21#ifdef VERY_VERY_VERBOSE_LOGGING
22#define ALOGVV ALOGV
23#else
24#define ALOGVV(a...) do { } while(0)
25#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080026
27#include <errno.h>
28#include <pthread.h>
29#include <stdint.h>
30#include <sys/time.h>
31#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080032#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070033#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070034#include <sys/resource.h>
35#include <sys/prctl.h>
Kevin Rocardb5c28192017-05-02 15:30:20 -070036#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080037
Haynes Mathew Georgee6e2d442018-02-22 18:51:56 -080038#include <log/log.h>
Haynes Mathew George03c40102016-01-29 17:57:48 -080039#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040#include <cutils/str_parms.h>
41#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070042#include <cutils/atomic.h>
43#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080044
Eric Laurentb23d5282013-05-14 15:27:20 -070045#include <hardware/audio_effect.h>
Andy Hung31aca912014-03-20 17:14:59 -070046#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070047#include <system/thread_defs.h>
Phil Burkbc991042017-02-24 08:06:44 -080048#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070049#include <audio_effects/effect_aec.h>
50#include <audio_effects/effect_ns.h>
Andy Hungfc044e12017-03-20 09:24:22 -070051#include <audio_utils/clock.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052#include "audio_hw.h"
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -080053#include "audio_extn.h"
Wei Wangf4837d52017-11-21 14:51:20 -080054#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070055#include "platform_api.h"
56#include <platform.h>
Vineeta Srivastava4b89e372014-06-19 14:21:42 -070057#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080058
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070059#include "sound/compress_params.h"
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -080060#include "audio_extn/tfa_98xx.h"
jasmine cha270b7762018-03-30 15:41:33 +080061#include "audio_extn/maxxaudio.h"
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062
Eric Laurent397db572016-05-11 11:31:47 -070063/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
64 * COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
Marco Nelissen32093f52015-04-08 15:14:02 -070065#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070066// 2 buffers causes problems with high bitrate files
67#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070068/* ToDo: Check and update a proper value in msec */
69#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
vivek mehta4a824772017-06-08 19:05:49 -070070/* treat as unsigned Q1.13 */
71#define APP_TYPE_GAIN_DEFAULT 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070072#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
vivek mehta4a824772017-06-08 19:05:49 -070073
74/* treat as unsigned Q1.13 */
vivek mehtaa68fea62017-06-08 19:04:02 -070075#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076
Eric Laurent51f3c662018-04-10 18:21:34 -070077#define RECORD_GAIN_MIN 0.0f
78#define RECORD_GAIN_MAX 1.0f
79#define RECORD_VOLUME_CTL_MAX 0x2000
80
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070081#define PROXY_OPEN_RETRY_COUNT 100
82#define PROXY_OPEN_WAIT_TIME 20
83
vivek mehtadae44712015-07-27 14:13:18 -070084#define MIN_CHANNEL_COUNT 1
85#define DEFAULT_CHANNEL_COUNT 2
86
Jean-Michel Trivic0750692015-10-12 12:12:32 -070087#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
88#define MAX_CHANNEL_COUNT 1
89#else
vivek mehtadae44712015-07-27 14:13:18 -070090#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
91#define XSTR(x) STR(x)
92#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070093#endif
Eric Laurent74b55762017-07-09 17:04:53 -070094#define MAX_HIFI_CHANNEL_COUNT 8
vivek mehtadae44712015-07-27 14:13:18 -070095
Haynes Mathew George03c40102016-01-29 17:57:48 -080096#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
97
Glenn Kasten4f993392014-05-14 07:30:48 -070098static unsigned int configured_low_latency_capture_period_size =
99 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
100
Eric Laurent0e46adf2016-12-16 12:49:24 -0800101
102#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Phil Burkbc991042017-02-24 08:06:44 -0800103#define MMAP_PERIOD_COUNT_MIN 32
104#define MMAP_PERIOD_COUNT_MAX 512
105#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
Eric Laurent0e46adf2016-12-16 12:49:24 -0800106
Andy Hung31aca912014-03-20 17:14:59 -0700107/* This constant enables extended precision handling.
108 * TODO The flag is off until more testing is done.
109 */
110static const bool k_enable_extended_precision = false;
111
Eric Laurentb23d5282013-05-14 15:27:20 -0700112struct pcm_config pcm_config_deep_buffer = {
vivek mehtadae44712015-07-27 14:13:18 -0700113 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700114 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
115 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
116 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
117 .format = PCM_FORMAT_S16_LE,
118 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
119 .stop_threshold = INT_MAX,
120 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
121};
122
123struct pcm_config pcm_config_low_latency = {
vivek mehtadae44712015-07-27 14:13:18 -0700124 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700125 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
126 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
127 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
128 .format = PCM_FORMAT_S16_LE,
129 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
130 .stop_threshold = INT_MAX,
131 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
132};
133
Haynes Mathew George03c40102016-01-29 17:57:48 -0800134static int af_period_multiplier = 4;
135struct pcm_config pcm_config_rt = {
136 .channels = DEFAULT_CHANNEL_COUNT,
137 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
138 .period_size = ULL_PERIOD_SIZE, //1 ms
139 .period_count = 512, //=> buffer size is 512ms
140 .format = PCM_FORMAT_S16_LE,
141 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
142 .stop_threshold = INT_MAX,
143 .silence_threshold = 0,
144 .silence_size = 0,
145 .avail_min = ULL_PERIOD_SIZE, //1 ms
146};
147
Eric Laurentb23d5282013-05-14 15:27:20 -0700148struct pcm_config pcm_config_hdmi_multi = {
149 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
150 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
151 .period_size = HDMI_MULTI_PERIOD_SIZE,
152 .period_count = HDMI_MULTI_PERIOD_COUNT,
153 .format = PCM_FORMAT_S16_LE,
154 .start_threshold = 0,
155 .stop_threshold = INT_MAX,
156 .avail_min = 0,
157};
158
Eric Laurent0e46adf2016-12-16 12:49:24 -0800159struct pcm_config pcm_config_mmap_playback = {
160 .channels = DEFAULT_CHANNEL_COUNT,
161 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
162 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800163 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800164 .format = PCM_FORMAT_S16_LE,
165 .start_threshold = MMAP_PERIOD_SIZE*8,
166 .stop_threshold = INT32_MAX,
167 .silence_threshold = 0,
168 .silence_size = 0,
169 .avail_min = MMAP_PERIOD_SIZE, //1 ms
170};
171
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800172struct pcm_config pcm_config_hifi = {
173 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
174 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
175 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
176 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
177 .format = PCM_FORMAT_S24_3LE,
178 .start_threshold = 0,
179 .stop_threshold = INT_MAX,
180 .avail_min = 0,
181};
182
Eric Laurentb23d5282013-05-14 15:27:20 -0700183struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700184 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700185 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
186 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700187 .stop_threshold = INT_MAX,
188 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700189};
190
Haynes Mathew George03c40102016-01-29 17:57:48 -0800191struct pcm_config pcm_config_audio_capture_rt = {
192 .channels = DEFAULT_CHANNEL_COUNT,
193 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
194 .period_size = ULL_PERIOD_SIZE,
195 .period_count = 512,
196 .format = PCM_FORMAT_S16_LE,
197 .start_threshold = 0,
198 .stop_threshold = INT_MAX,
199 .silence_threshold = 0,
200 .silence_size = 0,
201 .avail_min = ULL_PERIOD_SIZE, //1 ms
202};
203
Eric Laurent0e46adf2016-12-16 12:49:24 -0800204struct pcm_config pcm_config_mmap_capture = {
205 .channels = DEFAULT_CHANNEL_COUNT,
206 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
207 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800208 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800209 .format = PCM_FORMAT_S16_LE,
210 .start_threshold = 0,
211 .stop_threshold = INT_MAX,
212 .silence_threshold = 0,
213 .silence_size = 0,
214 .avail_min = MMAP_PERIOD_SIZE, //1 ms
215};
216
vivek mehtaa68fea62017-06-08 19:04:02 -0700217struct pcm_config pcm_config_voip = {
218 .channels = 1,
219 .period_count = 2,
220 .format = PCM_FORMAT_S16_LE,
221 .stop_threshold = INT_MAX,
222 .avail_min = 0,
223};
224
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700225#define AFE_PROXY_CHANNEL_COUNT 2
226#define AFE_PROXY_SAMPLING_RATE 48000
227
228#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
229#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
230
231struct pcm_config pcm_config_afe_proxy_playback = {
232 .channels = AFE_PROXY_CHANNEL_COUNT,
233 .rate = AFE_PROXY_SAMPLING_RATE,
234 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
235 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
236 .format = PCM_FORMAT_S16_LE,
237 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
238 .stop_threshold = INT_MAX,
239 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
240};
241
242#define AFE_PROXY_RECORD_PERIOD_SIZE 768
243#define AFE_PROXY_RECORD_PERIOD_COUNT 4
244
245struct pcm_config pcm_config_afe_proxy_record = {
246 .channels = AFE_PROXY_CHANNEL_COUNT,
247 .rate = AFE_PROXY_SAMPLING_RATE,
248 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
249 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
250 .format = PCM_FORMAT_S16_LE,
251 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
252 .stop_threshold = INT_MAX,
253 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
254};
255
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700256const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700257 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
258 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800259 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700260 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700261 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700262 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800263 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700264
Eric Laurentb23d5282013-05-14 15:27:20 -0700265 [USECASE_AUDIO_RECORD] = "audio-record",
266 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800267 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George569b7482017-05-08 14:44:27 -0700268 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700269
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800270 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
271 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700272
Eric Laurentb23d5282013-05-14 15:27:20 -0700273 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700274 [USECASE_VOICE2_CALL] = "voice2-call",
275 [USECASE_VOLTE_CALL] = "volte-call",
276 [USECASE_QCHAT_CALL] = "qchat-call",
277 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800278 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
279 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700280
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700281 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
282 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
283
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700284 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
285 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
vivek mehta781065c2017-04-04 12:55:01 -0700286
287 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
288 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
289 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
290
vivek mehtaa68fea62017-06-08 19:04:02 -0700291 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
292 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Nadav Bar3d72cfc2018-01-07 12:19:24 +0200293
294 [USECASE_INCALL_MUSIC_UPLINK] = "incall-music-uplink",
Aniket Kumar Lata99546312018-03-19 21:38:38 -0700295
296 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700297};
298
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800299
300#define STRING_TO_ENUM(string) { #string, string }
301
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800302struct string_to_enum {
303 const char *name;
304 uint32_t value;
305};
306
Haynes Mathew George569b7482017-05-08 14:44:27 -0700307static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800308 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
309 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
310 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Eric Laurent74b55762017-07-09 17:04:53 -0700311 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
Haynes Mathew George569b7482017-05-08 14:44:27 -0700312 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
Eric Laurent74b55762017-07-09 17:04:53 -0700313 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
314 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
315 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
316 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
317 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
318 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
319 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
320 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
321 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800322};
323
Haynes Mathew George5191a852013-09-11 14:19:36 -0700324static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700325static struct audio_device *adev = NULL;
Andy Hung9e737de2017-05-22 10:51:22 -0700326static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700327static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700328//cache last MBDRC cal step level
329static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700330
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800331static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
332static int set_compr_volume(struct audio_stream_out *stream, float left, float right);
333
Haynes Mathew George03c40102016-01-29 17:57:48 -0800334static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
335 int flags __unused)
336{
337 int dir = 0;
338 switch (uc_id) {
339 case USECASE_AUDIO_RECORD_LOW_LATENCY:
340 dir = 1;
341 case USECASE_AUDIO_PLAYBACK_ULL:
342 break;
343 default:
344 return false;
345 }
346
347 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
348 PCM_PLAYBACK : PCM_CAPTURE);
349 if (adev->adm_is_noirq_avail)
350 return adev->adm_is_noirq_avail(adev->adm_data,
351 adev->snd_card, dev_id, dir);
352 return false;
353}
354
355static void register_out_stream(struct stream_out *out)
356{
357 struct audio_device *adev = out->dev;
358 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
359 return;
360
361 if (!adev->adm_register_output_stream)
362 return;
363
364 adev->adm_register_output_stream(adev->adm_data,
365 out->handle,
366 out->flags);
367
368 if (!adev->adm_set_config)
369 return;
370
371 if (out->realtime) {
372 adev->adm_set_config(adev->adm_data,
373 out->handle,
374 out->pcm, &out->config);
375 }
376}
377
378static void register_in_stream(struct stream_in *in)
379{
380 struct audio_device *adev = in->dev;
381 if (!adev->adm_register_input_stream)
382 return;
383
384 adev->adm_register_input_stream(adev->adm_data,
385 in->capture_handle,
386 in->flags);
387
388 if (!adev->adm_set_config)
389 return;
390
391 if (in->realtime) {
392 adev->adm_set_config(adev->adm_data,
393 in->capture_handle,
394 in->pcm,
395 &in->config);
396 }
397}
398
399static void request_out_focus(struct stream_out *out, long ns)
400{
401 struct audio_device *adev = out->dev;
402
Haynes Mathew George03c40102016-01-29 17:57:48 -0800403 if (adev->adm_request_focus_v2) {
404 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
405 } else if (adev->adm_request_focus) {
406 adev->adm_request_focus(adev->adm_data, out->handle);
407 }
408}
409
410static void request_in_focus(struct stream_in *in, long ns)
411{
412 struct audio_device *adev = in->dev;
413
Haynes Mathew George03c40102016-01-29 17:57:48 -0800414 if (adev->adm_request_focus_v2) {
415 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
416 } else if (adev->adm_request_focus) {
417 adev->adm_request_focus(adev->adm_data, in->capture_handle);
418 }
419}
420
421static void release_out_focus(struct stream_out *out, long ns __unused)
422{
423 struct audio_device *adev = out->dev;
424
425 if (adev->adm_abandon_focus)
426 adev->adm_abandon_focus(adev->adm_data, out->handle);
427}
428
429static void release_in_focus(struct stream_in *in, long ns __unused)
430{
431 struct audio_device *adev = in->dev;
432 if (adev->adm_abandon_focus)
433 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
434}
435
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700436static int parse_snd_card_status(struct str_parms * parms, int * card,
437 card_status_t * status)
438{
439 char value[32]={0};
440 char state[32]={0};
441
442 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
443
444 if (ret < 0)
445 return -1;
446
447 // sscanf should be okay as value is of max length 32.
448 // same as sizeof state.
449 if (sscanf(value, "%d,%s", card, state) < 2)
450 return -1;
451
452 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
453 CARD_STATUS_OFFLINE;
454 return 0;
455}
456
vivek mehta40125092017-08-21 18:48:51 -0700457// always call with adev lock held
458void send_gain_dep_calibration_l() {
459 if (last_known_cal_step >= 0)
460 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
461}
462
vivek mehta1a9b7c02015-06-25 11:49:38 -0700463__attribute__ ((visibility ("default")))
464bool audio_hw_send_gain_dep_calibration(int level) {
465 bool ret_val = false;
466 ALOGV("%s: enter ... ", __func__);
467
468 pthread_mutex_lock(&adev_init_lock);
469
470 if (adev != NULL && adev->platform != NULL) {
471 pthread_mutex_lock(&adev->lock);
vivek mehta40125092017-08-21 18:48:51 -0700472 last_known_cal_step = level;
473 send_gain_dep_calibration_l();
vivek mehta1a9b7c02015-06-25 11:49:38 -0700474 pthread_mutex_unlock(&adev->lock);
475 } else {
476 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
477 }
478
479 pthread_mutex_unlock(&adev_init_lock);
480
481 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
482 return ret_val;
483}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700484
jasmine cha270b7762018-03-30 15:41:33 +0800485#ifdef MAXXAUDIO_QDSP_ENABLED
486bool audio_hw_send_ma_parameter(int stream_type, float vol, bool active)
487{
488 bool ret = false;
489 ALOGV("%s: enter ...", __func__);
490
491 pthread_mutex_lock(&adev_init_lock);
492
493 if (adev != NULL && adev->platform != NULL) {
494 pthread_mutex_lock(&adev->lock);
495 ret = audio_extn_ma_set_state(adev, stream_type, vol, active);
496 pthread_mutex_unlock(&adev->lock);
497 }
498
499 pthread_mutex_unlock(&adev_init_lock);
500
501 ALOGV("%s: exit with ret %d", __func__, ret);
502 return ret;
503}
504#else
505#define audio_hw_send_ma_parameter(stream_type, vol, active) (0)
506#endif
507
vivek mehtaa8d7c922016-05-25 14:40:44 -0700508__attribute__ ((visibility ("default")))
509int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
510 int table_size) {
511 int ret_val = 0;
512 ALOGV("%s: enter ... ", __func__);
513
514 pthread_mutex_lock(&adev_init_lock);
515 if (adev == NULL) {
516 ALOGW("%s: adev is NULL .... ", __func__);
517 goto done;
518 }
519
520 pthread_mutex_lock(&adev->lock);
521 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
522 pthread_mutex_unlock(&adev->lock);
523done:
524 pthread_mutex_unlock(&adev_init_lock);
525 ALOGV("%s: exit ... ", __func__);
526 return ret_val;
527}
528
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700529static bool is_supported_format(audio_format_t format)
530{
Eric Laurent8251ac82014-07-23 11:00:25 -0700531 switch (format) {
532 case AUDIO_FORMAT_MP3:
533 case AUDIO_FORMAT_AAC_LC:
534 case AUDIO_FORMAT_AAC_HE_V1:
535 case AUDIO_FORMAT_AAC_HE_V2:
536 return true;
537 default:
538 break;
539 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700540 return false;
541}
542
Haynes Mathew George03c40102016-01-29 17:57:48 -0800543static inline bool is_mmap_usecase(audio_usecase_t uc_id)
544{
545 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
546 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
547}
548
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700549static int get_snd_codec_id(audio_format_t format)
550{
551 int id = 0;
552
Eric Laurent8251ac82014-07-23 11:00:25 -0700553 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700554 case AUDIO_FORMAT_MP3:
555 id = SND_AUDIOCODEC_MP3;
556 break;
557 case AUDIO_FORMAT_AAC:
558 id = SND_AUDIOCODEC_AAC;
559 break;
560 default:
561 ALOGE("%s: Unsupported audio format", __func__);
562 }
563
564 return id;
565}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800566
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800567static int audio_ssr_status(struct audio_device *adev)
568{
569 int ret = 0;
570 struct mixer_ctl *ctl;
571 const char *mixer_ctl_name = "Audio SSR Status";
572
573 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
574 ret = mixer_ctl_get_value(ctl, 0);
575 ALOGD("%s: value: %d", __func__, ret);
576 return ret;
577}
578
vivek mehta4a824772017-06-08 19:05:49 -0700579static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
580{
581 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
582}
583
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800584static bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
585{
586 return out_snd_device == SND_DEVICE_OUT_BT_SCO ||
587 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
588 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
589 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
590 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
591 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC;
592
593}
594
595static bool is_a2dp_device(snd_device_t out_snd_device)
596{
597 return out_snd_device == SND_DEVICE_OUT_BT_A2DP;
598}
599
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800600int enable_audio_route(struct audio_device *adev,
601 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800602{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700603 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800604 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800605
606 if (usecase == NULL)
607 return -EINVAL;
608
609 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
610
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800611 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700612 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800613 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700614 snd_device = usecase->out_snd_device;
Yamit Mehtae3b99562016-09-16 22:44:00 +0530615 audio_extn_utils_send_app_type_cfg(adev, usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800616 audio_extn_utils_send_audio_calibration(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800617 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500618 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000619 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700620 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700621 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800622
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800623 ALOGV("%s: exit", __func__);
624 return 0;
625}
626
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800627int disable_audio_route(struct audio_device *adev,
628 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800629{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700630 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800631 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800632
633 if (usecase == NULL)
634 return -EINVAL;
635
636 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700637 if (usecase->type == PCM_CAPTURE)
638 snd_device = usecase->in_snd_device;
639 else
640 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800641 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500642 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700643 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700644 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000645 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800646
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800647 ALOGV("%s: exit", __func__);
648 return 0;
649}
650
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800651int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700652 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800653{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700654 int i, num_devices = 0;
655 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800656 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800657 if (snd_device < SND_DEVICE_MIN ||
658 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800659 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800660 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800661 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700662
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700663 platform_send_audio_calibration(adev->platform, snd_device);
664
vivek mehtade4849c2016-03-03 17:23:38 -0800665 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700666 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700667 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800668 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700669 }
670
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700671 /* due to the possibility of calibration overwrite between listen
672 and audio, notify sound trigger hal before audio calibration is sent */
673 audio_extn_sound_trigger_update_device_status(snd_device,
674 ST_EVENT_SND_DEVICE_BUSY);
675
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700676 if (audio_extn_spkr_prot_is_enabled())
677 audio_extn_spkr_prot_calib_cancel(adev);
678
zhaoyang yin4211fad2015-06-04 21:13:25 +0800679 audio_extn_dsm_feedback_enable(adev, snd_device, true);
680
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700681 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800682 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
juyuchen1d05ba32018-03-31 16:03:51 +0800683 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700684 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
685 audio_extn_spkr_prot_is_enabled()) {
Aniket Kumar Lata9d6679a2018-04-11 18:13:23 -0700686 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800687 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700688 }
689 if (audio_extn_spkr_prot_start_processing(snd_device)) {
690 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800691 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700692 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700693 } else if (platform_can_split_snd_device(snd_device,
694 &num_devices,
695 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700696 for (i = 0; i < num_devices; i++) {
697 enable_snd_device(adev, new_snd_devices[i]);
698 }
vivek mehtab6506412015-08-07 16:55:17 -0700699 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700700 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800701 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
702 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
703 ALOGE(" %s: Invalid sound device returned", __func__);
704 goto on_error;
705 }
Ed Tam70b5c142016-03-21 19:14:29 -0700706
Eric Laurent2e140aa2016-06-30 17:14:46 -0700707 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Aniket Kumar Lataa158e862018-05-11 17:28:40 -0700708
709 if (is_a2dp_device(snd_device) &&
710 (audio_extn_a2dp_start_playback() < 0)) {
711 ALOGE("%s: failed to configure A2DP control path", __func__);
712 goto on_error;
713 }
714
vivek mehtade4849c2016-03-03 17:23:38 -0800715 audio_route_apply_and_update_path(adev->audio_route, device_name);
716 }
717on_success:
718 adev->snd_dev_ref_cnt[snd_device]++;
719 ret_val = 0;
720on_error:
721 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800722}
723
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800724int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700725 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800726{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700727 int i, num_devices = 0;
728 snd_device_t new_snd_devices[2];
729
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800730 if (snd_device < SND_DEVICE_MIN ||
731 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800732 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800733 return -EINVAL;
734 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700735 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
736 ALOGE("%s: device ref cnt is already 0", __func__);
737 return -EINVAL;
738 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800739 audio_extn_tfa_98xx_disable_speaker(snd_device);
740
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700741 adev->snd_dev_ref_cnt[snd_device]--;
742 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800743 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800744
745 if (is_a2dp_device(snd_device))
746 audio_extn_a2dp_stop_playback();
747
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700748 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800749 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700750 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700751 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
752 audio_extn_spkr_prot_is_enabled()) {
753 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700754
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700755 // FIXME b/65363602: bullhead is the only Nexus with audio_extn_spkr_prot_is_enabled()
756 // and does not use speaker swap. As this code causes a problem with device enable ref
757 // counting we remove it for now.
vivek mehtae59cfb22017-06-16 15:57:11 -0700758 // when speaker device is disabled, reset swap.
759 // will be renabled on usecase start
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700760 // platform_set_swap_channels(adev, false);
vivek mehtae59cfb22017-06-16 15:57:11 -0700761
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700762 } else if (platform_can_split_snd_device(snd_device,
763 &num_devices,
764 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700765 for (i = 0; i < num_devices; i++) {
766 disable_snd_device(adev, new_snd_devices[i]);
767 }
vivek mehtab6506412015-08-07 16:55:17 -0700768 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700769 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800770 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
771 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
772 ALOGE(" %s: Invalid sound device returned", __func__);
773 return -EINVAL;
774 }
775
Eric Laurent2e140aa2016-06-30 17:14:46 -0700776 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800777 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700778 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700779 audio_extn_sound_trigger_update_device_status(snd_device,
780 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700781 }
vivek mehtab6506412015-08-07 16:55:17 -0700782
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800783 return 0;
784}
785
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700786/*
787 legend:
788 uc - existing usecase
789 new_uc - new usecase
790 d1, d11, d2 - SND_DEVICE enums
791 a1, a2 - corresponding ANDROID device enums
792 B, B1, B2 - backend strings
793
794case 1
795 uc->dev d1 (a1) B1
796 new_uc->dev d1 (a1), d2 (a2) B1, B2
797
798 resolution: disable and enable uc->dev on d1
799
800case 2
801 uc->dev d1 (a1) B1
802 new_uc->dev d11 (a1) B1
803
804 resolution: need to switch uc since d1 and d11 are related
805 (e.g. speaker and voice-speaker)
806 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
807
808case 3
809 uc->dev d1 (a1) B1
810 new_uc->dev d2 (a2) B2
811
812 resolution: no need to switch uc
813
814case 4
815 uc->dev d1 (a1) B
816 new_uc->dev d2 (a2) B
817
818 resolution: disable enable uc-dev on d2 since backends match
819 we cannot enable two streams on two different devices if they
820 share the same backend. e.g. if offload is on speaker device using
821 QUAD_MI2S backend and a low-latency stream is started on voice-handset
822 using the same backend, offload must also be switched to voice-handset.
823
824case 5
825 uc->dev d1 (a1) B
826 new_uc->dev d1 (a1), d2 (a2) B
827
828 resolution: disable enable uc-dev on d2 since backends match
829 we cannot enable two streams on two different devices if they
830 share the same backend.
831
832case 6
833 uc->dev d1 a1 B1
834 new_uc->dev d2 a1 B2
835
836 resolution: no need to switch
837
838case 7
839
840 uc->dev d1 (a1), d2 (a2) B1, B2
841 new_uc->dev d1 B1
842
843 resolution: no need to switch
844
845*/
846static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
847 struct audio_usecase *new_uc,
848 snd_device_t new_snd_device)
849{
850 audio_devices_t a1 = uc->stream.out->devices;
851 audio_devices_t a2 = new_uc->stream.out->devices;
852
853 snd_device_t d1 = uc->out_snd_device;
854 snd_device_t d2 = new_snd_device;
855
856 // Treat as a special case when a1 and a2 are not disjoint
857 if ((a1 != a2) && (a1 & a2)) {
858 snd_device_t d3[2];
859 int num_devices = 0;
860 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
861 &num_devices,
862 d3);
863 if (ret < 0) {
864 if (ret != -ENOSYS) {
865 ALOGW("%s failed to split snd_device %d",
866 __func__,
867 popcount(a1) > 1 ? d1 : d2);
868 }
869 goto end;
870 }
871
872 // NB: case 7 is hypothetical and isn't a practical usecase yet.
873 // But if it does happen, we need to give priority to d2 if
874 // the combo devices active on the existing usecase share a backend.
875 // This is because we cannot have a usecase active on a combo device
876 // and a new usecase requests one device in this combo pair.
877 if (platform_check_backends_match(d3[0], d3[1])) {
878 return d2; // case 5
879 } else {
880 return d1; // case 1
881 }
882 } else {
883 if (platform_check_backends_match(d1, d2)) {
884 return d2; // case 2, 4
885 } else {
886 return d1; // case 6, 3
887 }
888 }
889
890end:
891 return d2; // return whatever was calculated before.
892}
893
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700894static void check_and_route_playback_usecases(struct audio_device *adev,
895 struct audio_usecase *uc_info,
896 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700897{
898 struct listnode *node;
899 struct audio_usecase *usecase;
900 bool switch_device[AUDIO_USECASE_MAX];
901 int i, num_uc_to_switch = 0;
902
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700903 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
904 uc_info,
905 snd_device);
David Linee3fe402017-03-13 10:00:42 -0700906
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800907 /* For a2dp device reconfigure all active sessions
908 * with new AFE encoder format based on a2dp state
909 */
910 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Aniket Kumar Lata9723a962018-05-16 17:41:55 -0700911 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
912 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800913 audio_extn_a2dp_is_force_device_switch()) {
914 force_routing = true;
915 }
916
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700917 /*
918 * This function is to make sure that all the usecases that are active on
919 * the hardware codec backend are always routed to any one device that is
920 * handled by the hardware codec.
921 * For example, if low-latency and deep-buffer usecases are currently active
922 * on speaker and out_set_parameters(headset) is received on low-latency
923 * output, then we have to make sure deep-buffer is also switched to headset,
924 * because of the limitation that both the devices cannot be enabled
925 * at the same time as they share the same backend.
926 */
927 /* Disable all the usecases on the shared backend other than the
928 specified usecase */
929 for (i = 0; i < AUDIO_USECASE_MAX; i++)
930 switch_device[i] = false;
931
932 list_for_each(node, &adev->usecase_list) {
933 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700934 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
935 continue;
936
937 if (force_routing ||
938 (usecase->out_snd_device != snd_device &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -0700939 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
940 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700941 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700942 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
943 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700944 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700945 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700946 switch_device[usecase->id] = true;
947 num_uc_to_switch++;
948 }
949 }
950
951 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700952 list_for_each(node, &adev->usecase_list) {
953 usecase = node_to_item(node, struct audio_usecase, list);
954 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700955 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900956 }
957 }
958
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700959 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900960 list_for_each(node, &adev->usecase_list) {
961 usecase = node_to_item(node, struct audio_usecase, list);
962 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700963 d_device = derive_playback_snd_device(usecase, uc_info,
964 snd_device);
965 enable_snd_device(adev, d_device);
966 /* Update the out_snd_device before enabling the audio route */
967 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700968 }
969 }
970
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700971 /* Re-route all the usecases on the shared backend other than the
972 specified usecase to new snd devices */
973 list_for_each(node, &adev->usecase_list) {
974 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700975 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700976 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700977 }
978 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700979 }
980}
981
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700982static void check_and_route_capture_usecases(struct audio_device *adev,
983 struct audio_usecase *uc_info,
984 snd_device_t snd_device)
985{
986 struct listnode *node;
987 struct audio_usecase *usecase;
988 bool switch_device[AUDIO_USECASE_MAX];
989 int i, num_uc_to_switch = 0;
990
vivek mehta4ed66e62016-04-15 23:33:34 -0700991 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
992
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700993 /*
994 * This function is to make sure that all the active capture usecases
995 * are always routed to the same input sound device.
996 * For example, if audio-record and voice-call usecases are currently
997 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
998 * is received for voice call then we have to make sure that audio-record
999 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1000 * because of the limitation that two devices cannot be enabled
1001 * at the same time if they share the same backend.
1002 */
1003 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1004 switch_device[i] = false;
1005
1006 list_for_each(node, &adev->usecase_list) {
1007 usecase = node_to_item(node, struct audio_usecase, list);
1008 if (usecase->type != PCM_PLAYBACK &&
1009 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -07001010 usecase->in_snd_device != snd_device &&
1011 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001012 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1013 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001014 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001015 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001016 switch_device[usecase->id] = true;
1017 num_uc_to_switch++;
1018 }
1019 }
1020
1021 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001022 list_for_each(node, &adev->usecase_list) {
1023 usecase = node_to_item(node, struct audio_usecase, list);
1024 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001025 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001026 }
1027 }
1028
1029 list_for_each(node, &adev->usecase_list) {
1030 usecase = node_to_item(node, struct audio_usecase, list);
1031 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001032 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001033 }
1034 }
1035
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001036 /* Re-route all the usecases on the shared backend other than the
1037 specified usecase to new snd devices */
1038 list_for_each(node, &adev->usecase_list) {
1039 usecase = node_to_item(node, struct audio_usecase, list);
1040 /* Update the in_snd_device only before enabling the audio route */
1041 if (switch_device[usecase->id] ) {
1042 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001043 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001044 }
1045 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001046 }
1047}
1048
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001049/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001050static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001051{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001052 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001053 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001054
1055 switch (channels) {
1056 /*
1057 * Do not handle stereo output in Multi-channel cases
1058 * Stereo case is handled in normal playback path
1059 */
1060 case 6:
1061 ALOGV("%s: HDMI supports 5.1", __func__);
1062 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1063 break;
1064 case 8:
1065 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
1066 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1067 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
1068 break;
1069 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001070 ALOGE("HDMI does not support multi channel playback");
1071 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001072 break;
1073 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001074 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001075}
1076
Andy Hung18859412017-08-09 11:47:21 -07001077static ssize_t read_usb_sup_sample_rates(bool is_playback,
1078 uint32_t *supported_sample_rates,
1079 uint32_t max_rates)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001080{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001081 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1082 supported_sample_rates,
1083 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001084#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001085 for (ssize_t i=0; i<count; i++) {
1086 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1087 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001088 }
1089#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001090 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001091}
1092
Haynes Mathew George569b7482017-05-08 14:44:27 -07001093static int read_usb_sup_channel_masks(bool is_playback,
1094 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001095 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001096{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001097 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001098 int channel_count;
1099 uint32_t num_masks = 0;
1100 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1101 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001102 }
Eric Laurent74b55762017-07-09 17:04:53 -07001103 if (is_playback) {
Andy Hung6c1afb12017-12-22 11:34:41 -08001104 // start from 2 channels as framework currently doesn't support mono.
1105 // TODO: consider only supporting channel index masks beyond stereo here.
1106 for (channel_count = FCC_2;
1107 channel_count <= channels && num_masks < max_masks;
1108 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001109 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1110 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001111 for (channel_count = FCC_2;
1112 channel_count <= channels && num_masks < max_masks;
1113 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001114 supported_channel_masks[num_masks++] =
1115 audio_channel_mask_for_index_assignment_from_count(channel_count);
1116 }
1117 } else {
1118 // For capture we report all supported channel masks from 1 channel up.
1119 channel_count = MIN_CHANNEL_COUNT;
1120 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1121 // indexed mask
1122 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1123 supported_channel_masks[num_masks++] =
1124 audio_channel_in_mask_from_count(channel_count);
1125 }
1126 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001127#ifdef NDEBUG
1128 for (size_t i = 0; i < num_masks; ++i) {
1129 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1130 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
1131 }
1132#endif
Eric Laurent74b55762017-07-09 17:04:53 -07001133 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001134}
1135
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001136static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001137 audio_format_t *supported_formats,
1138 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001139{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001140 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001141 switch (bitwidth) {
1142 case 24:
1143 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001144 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001145 break;
1146 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001147 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001148 break;
1149 case 16:
1150 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001151 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001152 break;
1153 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001154 ALOGV("%s: %s supported format %d", __func__,
1155 is_playback ? "P" : "C", bitwidth);
1156 return 1;
1157}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001158
Haynes Mathew George569b7482017-05-08 14:44:27 -07001159static int read_usb_sup_params_and_compare(bool is_playback,
1160 audio_format_t *format,
1161 audio_format_t *supported_formats,
1162 uint32_t max_formats,
1163 audio_channel_mask_t *mask,
1164 audio_channel_mask_t *supported_channel_masks,
1165 uint32_t max_masks,
1166 uint32_t *rate,
1167 uint32_t *supported_sample_rates,
1168 uint32_t max_rates) {
1169 int ret = 0;
1170 int num_formats;
1171 int num_masks;
1172 int num_rates;
1173 int i;
1174
1175 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1176 max_formats);
1177 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1178 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001179
Haynes Mathew George569b7482017-05-08 14:44:27 -07001180 num_rates = read_usb_sup_sample_rates(is_playback,
1181 supported_sample_rates, max_rates);
1182
1183#define LUT(table, len, what, dflt) \
1184 for (i=0; i<len && (table[i] != what); i++); \
1185 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1186
1187 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1188 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1189 LUT(supported_sample_rates, num_rates, *rate, 0);
1190
1191#undef LUT
1192 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001193}
1194
Andy Hungd9653bd2017-08-01 19:31:39 -07001195static bool is_usb_ready(struct audio_device *adev, bool is_playback)
1196{
1197 // Check if usb is ready.
1198 // The usb device may have been removed quickly after insertion and hence
1199 // no longer available. This will show up as empty channel masks, or rates.
1200
1201 pthread_mutex_lock(&adev->lock);
1202 uint32_t supported_sample_rate;
1203
1204 // we consider usb ready if we can fetch at least one sample rate.
1205 const bool ready = read_usb_sup_sample_rates(
1206 is_playback, &supported_sample_rate, 1 /* max_rates */) > 0;
1207 pthread_mutex_unlock(&adev->lock);
1208 return ready;
1209}
1210
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001211static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1212{
1213 struct audio_usecase *usecase;
1214 struct listnode *node;
1215
1216 list_for_each(node, &adev->usecase_list) {
1217 usecase = node_to_item(node, struct audio_usecase, list);
1218 if (usecase->type == VOICE_CALL) {
1219 ALOGV("%s: usecase id %d", __func__, usecase->id);
1220 return usecase->id;
1221 }
1222 }
1223 return USECASE_INVALID;
1224}
1225
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001226struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1227 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001228{
1229 struct audio_usecase *usecase;
1230 struct listnode *node;
1231
1232 list_for_each(node, &adev->usecase_list) {
1233 usecase = node_to_item(node, struct audio_usecase, list);
1234 if (usecase->id == uc_id)
1235 return usecase;
1236 }
1237 return NULL;
1238}
1239
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001240static bool force_device_switch(struct audio_usecase *usecase)
1241{
1242 if (usecase->stream.out == NULL) {
1243 ALOGE("%s: stream.out is NULL", __func__);
1244 return false;
1245 }
1246
1247 // Force all A2DP output devices to reconfigure for proper AFE encode format
1248 // Also handle a case where in earlier A2DP start failed as A2DP stream was
1249 // in suspended state, hence try to trigger a retry when we again get a routing request.
1250 if ((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
1251 audio_extn_a2dp_is_force_device_switch()) {
1252 ALOGD("%s: Force A2DP device switch to update new encoder config", __func__);
1253 return true;
1254 }
1255
1256 return false;
1257}
1258
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001259int select_devices(struct audio_device *adev,
1260 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001261{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001262 snd_device_t out_snd_device = SND_DEVICE_NONE;
1263 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001264 struct audio_usecase *usecase = NULL;
1265 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001266 struct audio_usecase *hfp_usecase = NULL;
1267 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001268 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001269 int status = 0;
Eric Laurentf4520b02017-09-20 18:31:58 -07001270 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1271 USECASE_AUDIO_PLAYBACK_VOIP);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001272
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001273 usecase = get_usecase_from_list(adev, uc_id);
1274 if (usecase == NULL) {
1275 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1276 return -EINVAL;
1277 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001278
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001279 if ((usecase->type == VOICE_CALL) ||
1280 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001281 out_snd_device = platform_get_output_snd_device(adev->platform,
1282 usecase->stream.out->devices);
1283 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001284 usecase->devices = usecase->stream.out->devices;
1285 } else {
1286 /*
1287 * If the voice call is active, use the sound devices of voice call usecase
1288 * so that it would not result any device switch. All the usecases will
1289 * be switched to new device when select_devices() is called for voice call
1290 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001291 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001292 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001293 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001294 vc_usecase = get_usecase_from_list(adev,
1295 get_voice_usecase_id_from_list(adev));
1296 if ((vc_usecase != NULL) &&
1297 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1298 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001299 in_snd_device = vc_usecase->in_snd_device;
1300 out_snd_device = vc_usecase->out_snd_device;
1301 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001302 } else if (audio_extn_hfp_is_active(adev)) {
1303 hfp_ucid = audio_extn_hfp_get_usecase();
1304 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1305 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1306 in_snd_device = hfp_usecase->in_snd_device;
1307 out_snd_device = hfp_usecase->out_snd_device;
1308 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001309 }
1310 if (usecase->type == PCM_PLAYBACK) {
1311 usecase->devices = usecase->stream.out->devices;
1312 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001313 if (out_snd_device == SND_DEVICE_NONE) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001314 struct stream_out *voip_out = adev->primary_output;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001315
Eric Laurentb23d5282013-05-14 15:27:20 -07001316 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001317 usecase->stream.out->devices);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001318
1319 if (voip_usecase)
1320 voip_out = voip_usecase->stream.out;
1321
1322 if (usecase->stream.out == voip_out &&
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001323 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001324 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001325 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001326 select_devices(adev, adev->active_input->usecase);
1327 }
1328 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001329 } else if (usecase->type == PCM_CAPTURE) {
1330 usecase->devices = usecase->stream.in->device;
1331 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001332 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001333 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001334 if (adev->active_input &&
1335 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1336 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001337
1338 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1339 USECASE_AUDIO_PLAYBACK_VOIP);
1340
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001341 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001342 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1343 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001344 } else if (voip_usecase) {
1345 out_device = voip_usecase->stream.out->devices;
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001346 } else if (adev->primary_output) {
1347 out_device = adev->primary_output->devices;
1348 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001349 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001350 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001351 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001352 }
1353 }
1354
1355 if (out_snd_device == usecase->out_snd_device &&
1356 in_snd_device == usecase->in_snd_device) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001357 if (!force_device_switch(usecase))
1358 return 0;
1359 }
1360
1361 if (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready()) {
1362 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1363 return 0;
1364 }
1365
Aniket Kumar Lata9723a962018-05-16 17:41:55 -07001366 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
1367 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001368 (!audio_extn_a2dp_is_ready())) {
1369 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
1370 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001371 }
1372
Eric Laurent2bafff12016-03-17 12:17:23 -07001373 if (out_snd_device != SND_DEVICE_NONE &&
1374 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1375 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1376 __func__,
1377 use_case_table[uc_id],
1378 adev->last_logged_snd_device[uc_id][0],
1379 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1380 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1381 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1382 -1,
1383 out_snd_device,
1384 platform_get_snd_device_name(out_snd_device),
1385 platform_get_snd_device_acdb_id(out_snd_device));
1386 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1387 }
1388 if (in_snd_device != SND_DEVICE_NONE &&
1389 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1390 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1391 __func__,
1392 use_case_table[uc_id],
1393 adev->last_logged_snd_device[uc_id][1],
1394 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1395 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1396 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1397 -1,
1398 in_snd_device,
1399 platform_get_snd_device_name(in_snd_device),
1400 platform_get_snd_device_acdb_id(in_snd_device));
1401 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1402 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001403
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001404 /*
1405 * Limitation: While in call, to do a device switch we need to disable
1406 * and enable both RX and TX devices though one of them is same as current
1407 * device.
1408 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001409 if ((usecase->type == VOICE_CALL) &&
1410 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1411 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001412 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001413 /* Disable sidetone only if voice call already exists */
1414 if (voice_is_call_state_active(adev))
1415 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001416 }
1417
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001418 /* Disable current sound devices */
1419 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001420 disable_audio_route(adev, usecase);
1421 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001422 }
1423
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001424 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001425 disable_audio_route(adev, usecase);
1426 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001427 }
1428
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001429 /* Applicable only on the targets that has external modem.
1430 * New device information should be sent to modem before enabling
1431 * the devices to reduce in-call device switch time.
1432 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001433 if ((usecase->type == VOICE_CALL) &&
1434 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1435 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001436 status = platform_switch_voice_call_enable_device_config(adev->platform,
1437 out_snd_device,
1438 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001439 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001440
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001441 /* Enable new sound devices */
1442 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001443 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001444 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) ||
1445 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001446 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001447 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001448 }
1449
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001450 if (in_snd_device != SND_DEVICE_NONE) {
1451 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001452 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001453 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001454
Eric Laurentb23d5282013-05-14 15:27:20 -07001455 if (usecase->type == VOICE_CALL)
1456 status = platform_switch_voice_call_device_post(adev->platform,
1457 out_snd_device,
1458 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001459
sangwoo170731f2013-06-08 15:36:36 +09001460 usecase->in_snd_device = in_snd_device;
1461 usecase->out_snd_device = out_snd_device;
1462
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001463 audio_extn_tfa_98xx_set_mode();
1464
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001465 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001466
Jasmine Cha70771b62018-05-15 15:02:43 +08001467 audio_extn_ma_set_device(usecase);
jasmine cha270b7762018-03-30 15:41:33 +08001468
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001469 /* Applicable only on the targets that has external modem.
1470 * Enable device command should be sent to modem only after
1471 * enabling voice call mixer controls
1472 */
vivek mehta765eb642015-08-07 19:46:06 -07001473 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001474 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1475 out_snd_device,
1476 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001477 /* Enable sidetone only if voice call already exists */
1478 if (voice_is_call_state_active(adev))
1479 voice_set_sidetone(adev, out_snd_device, true);
1480 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001481
Eric Laurentf4520b02017-09-20 18:31:58 -07001482 if (usecase == voip_usecase) {
1483 struct stream_out *voip_out = voip_usecase->stream.out;
1484 audio_extn_utils_send_app_type_gain(adev,
1485 voip_out->app_type_cfg.app_type,
1486 &voip_out->app_type_cfg.gain[0]);
1487 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001488 return status;
1489}
1490
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001491static int stop_input_stream(struct stream_in *in)
1492{
1493 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001494 struct audio_usecase *uc_info;
1495 struct audio_device *adev = in->dev;
1496
Eric Laurent994a6932013-07-17 11:51:42 -07001497 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001498 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001499
1500 if (adev->active_input) {
1501 if (adev->active_input->usecase == in->usecase) {
1502 adev->active_input = NULL;
1503 } else {
1504 ALOGW("%s adev->active_input->usecase %s, v/s in->usecase %s",
1505 __func__,
1506 use_case_table[adev->active_input->usecase],
1507 use_case_table[in->usecase]);
1508 }
1509 }
1510
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001511 uc_info = get_usecase_from_list(adev, in->usecase);
1512 if (uc_info == NULL) {
1513 ALOGE("%s: Could not find the usecase (%d) in the list",
1514 __func__, in->usecase);
1515 return -EINVAL;
1516 }
1517
vivek mehta781065c2017-04-04 12:55:01 -07001518 /* Close in-call recording streams */
1519 voice_check_and_stop_incall_rec_usecase(adev, in);
1520
Eric Laurent150dbfe2013-02-27 14:31:02 -08001521 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001522 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001523
1524 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001525 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001526
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001527 list_remove(&uc_info->list);
1528 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001529
Eric Laurent994a6932013-07-17 11:51:42 -07001530 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001531 return ret;
1532}
1533
1534int start_input_stream(struct stream_in *in)
1535{
1536 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001537 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001538 struct audio_usecase *uc_info;
1539 struct audio_device *adev = in->dev;
1540
Eric Laurent994a6932013-07-17 11:51:42 -07001541 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001542
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001543 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1544 return -EIO;
1545
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001546 if (in->card_status == CARD_STATUS_OFFLINE ||
1547 adev->card_status == CARD_STATUS_OFFLINE) {
1548 ALOGW("in->card_status or adev->card_status offline, try again");
1549 ret = -EAGAIN;
1550 goto error_config;
1551 }
1552
vivek mehta781065c2017-04-04 12:55:01 -07001553 /* Check if source matches incall recording usecase criteria */
1554 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1555 if (ret)
1556 goto error_config;
1557 else
1558 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1559
Eric Laurentb23d5282013-05-14 15:27:20 -07001560 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001561 if (in->pcm_device_id < 0) {
1562 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1563 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001564 ret = -EINVAL;
1565 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001566 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001567
1568 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001569 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1570 uc_info->id = in->usecase;
1571 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001572 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001573 uc_info->devices = in->device;
1574 uc_info->in_snd_device = SND_DEVICE_NONE;
1575 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001576
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001577 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001578
Wei Wangf4837d52017-11-21 14:51:20 -08001579 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001580 audio_extn_perf_lock_acquire();
1581
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001582 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001583
Eric Laurent0e46adf2016-12-16 12:49:24 -08001584 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001585 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001586 ALOGE("%s: pcm stream not ready", __func__);
1587 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001588 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001589 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001590 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001591 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1592 goto error_open;
1593 }
1594 } else {
1595 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1596 unsigned int pcm_open_retry_count = 0;
1597
1598 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1599 flags |= PCM_MMAP | PCM_NOIRQ;
1600 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1601 } else if (in->realtime) {
1602 flags |= PCM_MMAP | PCM_NOIRQ;
1603 }
1604
1605 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1606 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1607
1608 while (1) {
1609 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1610 flags, &in->config);
1611 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1612 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1613 if (in->pcm != NULL) {
1614 pcm_close(in->pcm);
1615 in->pcm = NULL;
1616 }
1617 if (pcm_open_retry_count-- == 0) {
1618 ret = -EIO;
1619 goto error_open;
1620 }
1621 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1622 continue;
1623 }
1624 break;
1625 }
1626
1627 ALOGV("%s: pcm_prepare", __func__);
1628 ret = pcm_prepare(in->pcm);
1629 if (ret < 0) {
1630 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001631 pcm_close(in->pcm);
1632 in->pcm = NULL;
1633 goto error_open;
1634 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001635 if (in->realtime) {
1636 ret = pcm_start(in->pcm);
1637 if (ret < 0) {
1638 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1639 pcm_close(in->pcm);
1640 in->pcm = NULL;
1641 goto error_open;
1642 }
1643 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001644 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001645 register_in_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001646 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001647 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001648 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001649
Eric Laurent0e46adf2016-12-16 12:49:24 -08001650 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001651
1652error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001653 stop_input_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001654 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001655 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001656
1657error_config:
1658 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001659 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001660 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001661}
1662
Eric Laurenta1478072015-09-21 17:21:52 -07001663void lock_input_stream(struct stream_in *in)
1664{
1665 pthread_mutex_lock(&in->pre_lock);
1666 pthread_mutex_lock(&in->lock);
1667 pthread_mutex_unlock(&in->pre_lock);
1668}
1669
1670void lock_output_stream(struct stream_out *out)
1671{
1672 pthread_mutex_lock(&out->pre_lock);
1673 pthread_mutex_lock(&out->lock);
1674 pthread_mutex_unlock(&out->pre_lock);
1675}
1676
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001677/* must be called with out->lock locked */
1678static int send_offload_cmd_l(struct stream_out* out, int command)
1679{
1680 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1681
1682 ALOGVV("%s %d", __func__, command);
1683
1684 cmd->cmd = command;
1685 list_add_tail(&out->offload_cmd_list, &cmd->node);
1686 pthread_cond_signal(&out->offload_cond);
1687 return 0;
1688}
1689
1690/* must be called iwth out->lock locked */
1691static void stop_compressed_output_l(struct stream_out *out)
1692{
1693 out->offload_state = OFFLOAD_STATE_IDLE;
1694 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001695 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001696 if (out->compr != NULL) {
1697 compress_stop(out->compr);
1698 while (out->offload_thread_blocked) {
1699 pthread_cond_wait(&out->cond, &out->lock);
1700 }
1701 }
1702}
1703
1704static void *offload_thread_loop(void *context)
1705{
1706 struct stream_out *out = (struct stream_out *) context;
1707 struct listnode *item;
1708
1709 out->offload_state = OFFLOAD_STATE_IDLE;
1710 out->playback_started = 0;
1711
1712 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1713 set_sched_policy(0, SP_FOREGROUND);
1714 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1715
1716 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001717 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001718 for (;;) {
1719 struct offload_cmd *cmd = NULL;
1720 stream_callback_event_t event;
1721 bool send_callback = false;
1722
1723 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1724 __func__, list_empty(&out->offload_cmd_list),
1725 out->offload_state);
1726 if (list_empty(&out->offload_cmd_list)) {
1727 ALOGV("%s SLEEPING", __func__);
1728 pthread_cond_wait(&out->offload_cond, &out->lock);
1729 ALOGV("%s RUNNING", __func__);
1730 continue;
1731 }
1732
1733 item = list_head(&out->offload_cmd_list);
1734 cmd = node_to_item(item, struct offload_cmd, node);
1735 list_remove(item);
1736
1737 ALOGVV("%s STATE %d CMD %d out->compr %p",
1738 __func__, out->offload_state, cmd->cmd, out->compr);
1739
1740 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1741 free(cmd);
1742 break;
1743 }
1744
1745 if (out->compr == NULL) {
1746 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001747 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001748 pthread_cond_signal(&out->cond);
1749 continue;
1750 }
1751 out->offload_thread_blocked = true;
1752 pthread_mutex_unlock(&out->lock);
1753 send_callback = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001754 switch (cmd->cmd) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001755 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1756 compress_wait(out->compr, -1);
1757 send_callback = true;
1758 event = STREAM_CBK_EVENT_WRITE_READY;
1759 break;
1760 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001761 compress_next_track(out->compr);
1762 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001763 send_callback = true;
1764 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001765 /* Resend the metadata for next iteration */
1766 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001767 break;
1768 case OFFLOAD_CMD_DRAIN:
1769 compress_drain(out->compr);
1770 send_callback = true;
1771 event = STREAM_CBK_EVENT_DRAIN_READY;
1772 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001773 case OFFLOAD_CMD_ERROR:
1774 send_callback = true;
1775 event = STREAM_CBK_EVENT_ERROR;
1776 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001777 default:
1778 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1779 break;
1780 }
Eric Laurenta1478072015-09-21 17:21:52 -07001781 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001782 out->offload_thread_blocked = false;
1783 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001784 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001785 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001786 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001787 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001788 free(cmd);
1789 }
1790
1791 pthread_cond_signal(&out->cond);
1792 while (!list_empty(&out->offload_cmd_list)) {
1793 item = list_head(&out->offload_cmd_list);
1794 list_remove(item);
1795 free(node_to_item(item, struct offload_cmd, node));
1796 }
1797 pthread_mutex_unlock(&out->lock);
1798
1799 return NULL;
1800}
1801
1802static int create_offload_callback_thread(struct stream_out *out)
1803{
1804 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1805 list_init(&out->offload_cmd_list);
1806 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1807 offload_thread_loop, out);
1808 return 0;
1809}
1810
1811static int destroy_offload_callback_thread(struct stream_out *out)
1812{
Eric Laurenta1478072015-09-21 17:21:52 -07001813 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001814 stop_compressed_output_l(out);
1815 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1816
1817 pthread_mutex_unlock(&out->lock);
1818 pthread_join(out->offload_thread, (void **) NULL);
1819 pthread_cond_destroy(&out->offload_cond);
1820
1821 return 0;
1822}
1823
Eric Laurent07eeafd2013-10-06 12:52:49 -07001824static bool allow_hdmi_channel_config(struct audio_device *adev)
1825{
1826 struct listnode *node;
1827 struct audio_usecase *usecase;
1828 bool ret = true;
1829
1830 list_for_each(node, &adev->usecase_list) {
1831 usecase = node_to_item(node, struct audio_usecase, list);
1832 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1833 /*
1834 * If voice call is already existing, do not proceed further to avoid
1835 * disabling/enabling both RX and TX devices, CSD calls, etc.
1836 * Once the voice call done, the HDMI channels can be configured to
1837 * max channels of remaining use cases.
1838 */
1839 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001840 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001841 __func__);
1842 ret = false;
1843 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001844 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1845 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001846 "no change in HDMI channels", __func__);
1847 ret = false;
1848 break;
1849 }
1850 }
1851 }
1852 return ret;
1853}
1854
1855static int check_and_set_hdmi_channels(struct audio_device *adev,
1856 unsigned int channels)
1857{
1858 struct listnode *node;
1859 struct audio_usecase *usecase;
1860
1861 /* Check if change in HDMI channel config is allowed */
1862 if (!allow_hdmi_channel_config(adev))
1863 return 0;
1864
1865 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001866 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001867 return 0;
1868 }
1869
1870 platform_set_hdmi_channels(adev->platform, channels);
1871 adev->cur_hdmi_channels = channels;
1872
1873 /*
1874 * Deroute all the playback streams routed to HDMI so that
1875 * the back end is deactivated. Note that backend will not
1876 * be deactivated if any one stream is connected to it.
1877 */
1878 list_for_each(node, &adev->usecase_list) {
1879 usecase = node_to_item(node, struct audio_usecase, list);
1880 if (usecase->type == PCM_PLAYBACK &&
1881 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001882 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001883 }
1884 }
1885
1886 /*
1887 * Enable all the streams disabled above. Now the HDMI backend
1888 * will be activated with new channel configuration
1889 */
1890 list_for_each(node, &adev->usecase_list) {
1891 usecase = node_to_item(node, struct audio_usecase, list);
1892 if (usecase->type == PCM_PLAYBACK &&
1893 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001894 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001895 }
1896 }
1897
1898 return 0;
1899}
1900
Haynes Mathew George65f6b432018-02-27 17:44:55 -08001901static int check_and_set_usb_service_interval(struct audio_device *adev,
1902 struct audio_usecase *uc_info,
1903 bool min)
1904{
1905 struct listnode *node;
1906 struct audio_usecase *usecase;
1907 bool switch_usecases = false;
1908 bool reconfig = false;
1909
1910 if ((uc_info->id != USECASE_AUDIO_PLAYBACK_MMAP) &&
1911 (uc_info->id != USECASE_AUDIO_PLAYBACK_ULL))
1912 return -1;
1913
1914 /* set if the valid usecase do not already exist */
1915 list_for_each(node, &adev->usecase_list) {
1916 usecase = node_to_item(node, struct audio_usecase, list);
1917 if (usecase->type == PCM_PLAYBACK &&
1918 (audio_is_usb_out_device(usecase->devices & AUDIO_DEVICE_OUT_ALL_USB))) {
1919 switch (usecase->id) {
1920 case USECASE_AUDIO_PLAYBACK_MMAP:
1921 case USECASE_AUDIO_PLAYBACK_ULL:
1922 // cannot reconfig while mmap/ull is present.
1923 return -1;
1924 default:
1925 switch_usecases = true;
1926 break;
1927 }
1928 }
1929 if (switch_usecases)
1930 break;
1931 }
1932 /*
1933 * client can try to set service interval in start_output_stream
1934 * to min or to 0 (i.e reset) in stop_output_stream .
1935 */
1936 unsigned long service_interval =
1937 audio_extn_usb_find_service_interval(min, true /*playback*/);
1938 int ret = platform_set_usb_service_interval(adev->platform,
1939 true /*playback*/,
1940 service_interval,
1941 &reconfig);
1942 /* no change or not supported or no active usecases */
1943 if (ret || !reconfig || !switch_usecases)
1944 return -1;
1945 return 0;
1946#undef VALID_USECASE
1947}
1948
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001949static int stop_output_stream(struct stream_out *out)
1950{
1951 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001952 struct audio_usecase *uc_info;
1953 struct audio_device *adev = out->dev;
1954
Eric Laurent994a6932013-07-17 11:51:42 -07001955 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001956 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001957 uc_info = get_usecase_from_list(adev, out->usecase);
1958 if (uc_info == NULL) {
1959 ALOGE("%s: Could not find the usecase (%d) in the list",
1960 __func__, out->usecase);
1961 return -EINVAL;
1962 }
1963
Haynes Mathew George41f86652014-06-17 14:22:15 -07001964 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1965 if (adev->visualizer_stop_output != NULL)
1966 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1967 if (adev->offload_effects_stop_output != NULL)
1968 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08001969 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
1970 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
1971 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07001972 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001973
Eric Laurent150dbfe2013-02-27 14:31:02 -08001974 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001975 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001976
1977 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001978 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001979
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001980 list_remove(&uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001981
Eric Laurent0499d4f2014-08-25 22:39:29 -05001982 audio_extn_extspk_update(adev->extspk);
1983
Eric Laurent07eeafd2013-10-06 12:52:49 -07001984 /* Must be called after removing the usecase from list */
1985 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1986 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07001987 else if (out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
1988 struct listnode *node;
1989 struct audio_usecase *usecase;
1990 list_for_each(node, &adev->usecase_list) {
1991 usecase = node_to_item(node, struct audio_usecase, list);
1992 if (usecase->devices & AUDIO_DEVICE_OUT_SPEAKER)
1993 select_devices(adev, usecase->id);
1994 }
Haynes Mathew George65f6b432018-02-27 17:44:55 -08001995 } else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
1996 ret = check_and_set_usb_service_interval(adev, uc_info, false /*min*/);
1997 if (ret == 0) {
1998 /* default service interval was successfully updated,
1999 reopen USB backend with new service interval */
2000 check_and_route_playback_usecases(adev, uc_info, uc_info->out_snd_device);
2001 }
2002 ret = 0;
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07002003 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002004
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002005 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07002006 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002007 return ret;
2008}
2009
2010int start_output_stream(struct stream_out *out)
2011{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002012 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002013 struct audio_usecase *uc_info;
2014 struct audio_device *adev = out->dev;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002015 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002016
Eric Laurent994a6932013-07-17 11:51:42 -07002017 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002018 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002019
2020 if (out->card_status == CARD_STATUS_OFFLINE ||
2021 adev->card_status == CARD_STATUS_OFFLINE) {
2022 ALOGW("out->card_status or adev->card_status offline, try again");
2023 ret = -EAGAIN;
2024 goto error_config;
2025 }
2026
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002027 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2028 if (!audio_extn_a2dp_is_ready()) {
2029 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2030 a2dp_combo = true;
2031 } else {
2032 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2033 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2034 ret = -EAGAIN;
2035 goto error_config;
2036 }
2037 }
2038 }
2039 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002040 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002041 if (out->pcm_device_id < 0) {
2042 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2043 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002044 ret = -EINVAL;
2045 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002046 }
2047
2048 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
2049 uc_info->id = out->usecase;
2050 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002051 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002052 uc_info->devices = out->devices;
2053 uc_info->in_snd_device = SND_DEVICE_NONE;
2054 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002055
Eric Laurent07eeafd2013-10-06 12:52:49 -07002056 /* This must be called before adding this usecase to the list */
2057 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2058 check_and_set_hdmi_channels(adev, out->config.channels);
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002059 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
2060 check_and_set_usb_service_interval(adev, uc_info, true /*min*/);
2061 /* USB backend is not reopened immediately.
2062 This is eventually done as part of select_devices */
2063 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002064
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002065 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002066
Wei Wangf4837d52017-11-21 14:51:20 -08002067 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002068 audio_extn_perf_lock_acquire();
2069
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002070 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2071 (!audio_extn_a2dp_is_ready())) {
2072 if (!a2dp_combo) {
2073 check_a2dp_restore_l(adev, out, false);
2074 } else {
2075 audio_devices_t dev = out->devices;
2076 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2077 select_devices(adev, out->usecase);
2078 out->devices = dev;
2079 }
2080 } else {
2081 select_devices(adev, out->usecase);
2082 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002083
Eric Laurent0499d4f2014-08-25 22:39:29 -05002084 audio_extn_extspk_update(adev->extspk);
2085
Andy Hung31aca912014-03-20 17:14:59 -07002086 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002087 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002088 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2089 out->pcm = NULL;
2090 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
2091 COMPRESS_IN, &out->compr_config);
2092 if (out->compr && !is_compress_ready(out->compr)) {
2093 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2094 compress_close(out->compr);
2095 out->compr = NULL;
2096 ret = -EIO;
2097 goto error_open;
2098 }
2099 if (out->offload_callback)
2100 compress_nonblock(out->compr, out->non_blocking);
2101
2102 if (adev->visualizer_start_output != NULL)
2103 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2104 if (adev->offload_effects_start_output != NULL)
2105 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
2106 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002107 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002108 ALOGE("%s: pcm stream not ready", __func__);
2109 goto error_open;
2110 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002111 ret = pcm_start(out->pcm);
2112 if (ret < 0) {
2113 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2114 goto error_open;
2115 }
2116 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07002117 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002118 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002119
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002120 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2121 flags |= PCM_MMAP | PCM_NOIRQ;
2122 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002123 } else if (out->realtime) {
2124 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07002125 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002126
2127 while (1) {
2128 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2129 flags, &out->config);
2130 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2131 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2132 if (out->pcm != NULL) {
2133 pcm_close(out->pcm);
2134 out->pcm = NULL;
2135 }
2136 if (pcm_open_retry_count-- == 0) {
2137 ret = -EIO;
2138 goto error_open;
2139 }
2140 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2141 continue;
2142 }
2143 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002144 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002145 ALOGV("%s: pcm_prepare", __func__);
2146 if (pcm_is_ready(out->pcm)) {
2147 ret = pcm_prepare(out->pcm);
2148 if (ret < 0) {
2149 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2150 pcm_close(out->pcm);
2151 out->pcm = NULL;
2152 goto error_open;
2153 }
2154 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002155 if (out->realtime) {
2156 ret = pcm_start(out->pcm);
2157 if (ret < 0) {
2158 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
2159 pcm_close(out->pcm);
2160 out->pcm = NULL;
2161 goto error_open;
2162 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002163 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002164 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002165 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08002166 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002167 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002168 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07002169
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002170 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2171 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2172 audio_low_latency_hint_start();
2173 }
2174
vivek mehtae59cfb22017-06-16 15:57:11 -07002175 // consider a scenario where on pause lower layers are tear down.
2176 // so on resume, swap mixer control need to be sent only when
2177 // backend is active, hence rather than sending from enable device
2178 // sending it from start of streamtream
2179
2180 platform_set_swap_channels(adev, true);
2181
Eric Laurent994a6932013-07-17 11:51:42 -07002182 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002183 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002184error_open:
Wei Wangf4837d52017-11-21 14:51:20 -08002185 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002186 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002187 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002188error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002189 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002190}
2191
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002192static int check_input_parameters(uint32_t sample_rate,
2193 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07002194 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002195{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002196 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2197 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002198 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2199 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002200 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2201 return -EINVAL;
2202 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002203
Eric Laurent74b55762017-07-09 17:04:53 -07002204 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2205 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002206 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002207 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002208 return -EINVAL;
2209 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002210
2211 switch (sample_rate) {
2212 case 8000:
2213 case 11025:
2214 case 12000:
2215 case 16000:
2216 case 22050:
2217 case 24000:
2218 case 32000:
2219 case 44100:
2220 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002221 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002222 break;
2223 default:
vivek mehtadae44712015-07-27 14:13:18 -07002224 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002225 return -EINVAL;
2226 }
2227
2228 return 0;
2229}
2230
Kevin Rocarda325aa22018-04-03 09:15:52 -07002231/** Add a value in a list if not already present.
2232 * @return true if value was successfully inserted or already present,
2233 * false if the list is full and does not contain the value.
2234 */
2235static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
2236 for (size_t i = 0; i < list_length; i++) {
2237 if (list[i] == value) return true; // value is already present
2238 if (list[i] == 0) { // no values in this slot
2239 list[i] = value;
2240 return true; // value inserted
2241 }
2242 }
2243 return false; // could not insert value
2244}
2245
2246/** Add channel_mask in supported_channel_masks if not already present.
2247 * @return true if channel_mask was successfully inserted or already present,
2248 * false if supported_channel_masks is full and does not contain channel_mask.
2249 */
2250static void register_channel_mask(audio_channel_mask_t channel_mask,
2251 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
2252 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
2253 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
2254}
2255
2256/** Add format in supported_formats if not already present.
2257 * @return true if format was successfully inserted or already present,
2258 * false if supported_formats is full and does not contain format.
2259 */
2260static void register_format(audio_format_t format,
2261 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
2262 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
2263 "%s: stream can not declare supporting its format %x", __func__, format);
2264}
2265/** Add sample_rate in supported_sample_rates if not already present.
2266 * @return true if sample_rate was successfully inserted or already present,
2267 * false if supported_sample_rates is full and does not contain sample_rate.
2268 */
2269static void register_sample_rate(uint32_t sample_rate,
2270 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
2271 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
2272 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
2273}
2274
vivek mehtaa68fea62017-06-08 19:04:02 -07002275static size_t get_stream_buffer_size(size_t duration_ms,
2276 uint32_t sample_rate,
2277 audio_format_t format,
2278 int channel_count,
2279 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002280{
2281 size_t size = 0;
2282
vivek mehtaa68fea62017-06-08 19:04:02 -07002283 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002284 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002285 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002286
2287 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002288
Glenn Kasten4f993392014-05-14 07:30:48 -07002289 /* make sure the size is multiple of 32 bytes
2290 * At 48 kHz mono 16-bit PCM:
2291 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2292 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2293 */
2294 size += 0x1f;
2295 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002296
2297 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002298}
2299
2300static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2301{
2302 struct stream_out *out = (struct stream_out *)stream;
2303
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002304 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002305}
2306
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002307static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002308{
2309 return -ENOSYS;
2310}
2311
2312static size_t out_get_buffer_size(const struct audio_stream *stream)
2313{
2314 struct stream_out *out = (struct stream_out *)stream;
2315
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002316 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2317 return out->compr_config.fragment_size;
2318 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002319 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002320 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002321}
2322
2323static uint32_t out_get_channels(const struct audio_stream *stream)
2324{
2325 struct stream_out *out = (struct stream_out *)stream;
2326
2327 return out->channel_mask;
2328}
2329
2330static audio_format_t out_get_format(const struct audio_stream *stream)
2331{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002332 struct stream_out *out = (struct stream_out *)stream;
2333
2334 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002335}
2336
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002337static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002338{
2339 return -ENOSYS;
2340}
2341
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002342/* must be called with out->lock locked */
2343static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002344{
2345 struct stream_out *out = (struct stream_out *)stream;
2346 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002347 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002348
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002349 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002350 if (adev->adm_deregister_stream)
2351 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002352 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002353 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002354 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2355 if (out->pcm) {
2356 pcm_close(out->pcm);
2357 out->pcm = NULL;
2358 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002359 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002360 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002361 out->playback_started = false;
2362 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002363 } else {
2364 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002365 out->gapless_mdata.encoder_delay = 0;
2366 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002367 if (out->compr != NULL) {
2368 compress_close(out->compr);
2369 out->compr = NULL;
2370 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002371 }
Phil Burkbc991042017-02-24 08:06:44 -08002372 if (do_stop) {
2373 stop_output_stream(out);
2374 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002375 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002376 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002377 return 0;
2378}
2379
2380static int out_standby(struct audio_stream *stream)
2381{
2382 struct stream_out *out = (struct stream_out *)stream;
2383
2384 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2385 out->usecase, use_case_table[out->usecase]);
2386
2387 lock_output_stream(out);
2388 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002389 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002390 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002391 return 0;
2392}
2393
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002394static int out_on_error(struct audio_stream *stream)
2395{
2396 struct stream_out *out = (struct stream_out *)stream;
2397 struct audio_device *adev = out->dev;
2398 bool do_standby = false;
2399
2400 lock_output_stream(out);
2401 if (!out->standby) {
2402 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2403 stop_compressed_output_l(out);
2404 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2405 } else
2406 do_standby = true;
2407 }
2408 pthread_mutex_unlock(&out->lock);
2409
2410 if (do_standby)
2411 return out_standby(&out->stream.common);
2412
2413 return 0;
2414}
2415
Andy Hung7401c7c2016-09-21 12:41:21 -07002416static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002417{
Andy Hung7401c7c2016-09-21 12:41:21 -07002418 struct stream_out *out = (struct stream_out *)stream;
2419
2420 // We try to get the lock for consistency,
2421 // but it isn't necessary for these variables.
2422 // If we're not in standby, we may be blocked on a write.
2423 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2424 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2425 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2426
2427 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002428 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002429 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002430
2431 // dump error info
2432 (void)error_log_dump(
2433 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002434
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002435 return 0;
2436}
2437
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002438static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2439{
2440 int ret = 0;
2441 char value[32];
2442 struct compr_gapless_mdata tmp_mdata;
2443
2444 if (!out || !parms) {
2445 return -EINVAL;
2446 }
2447
2448 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2449 if (ret >= 0) {
2450 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2451 } else {
2452 return -EINVAL;
2453 }
2454
2455 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2456 if (ret >= 0) {
2457 tmp_mdata.encoder_padding = atoi(value);
2458 } else {
2459 return -EINVAL;
2460 }
2461
2462 out->gapless_mdata = tmp_mdata;
2463 out->send_new_metadata = 1;
2464 ALOGV("%s new encoder delay %u and padding %u", __func__,
2465 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2466
2467 return 0;
2468}
2469
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002470static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2471{
2472 return out == adev->primary_output || out == adev->voice_tx_output;
2473}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002474
Kevin Rocard1e02c882017-08-09 15:26:07 -07002475static int get_alive_usb_card(struct str_parms* parms) {
2476 int card;
2477 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2478 !audio_extn_usb_alive(card)) {
2479 return card;
2480 }
2481 return -ENODEV;
2482}
2483
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002484static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2485{
2486 struct stream_out *out = (struct stream_out *)stream;
2487 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002488 struct audio_usecase *usecase;
2489 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002490 struct str_parms *parms;
2491 char value[32];
2492 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002493 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002494 int status = 0;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002495 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002496
Eric Laurent2e140aa2016-06-30 17:14:46 -07002497 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002498 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002499 parms = str_parms_create_str(kvpairs);
2500 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2501 if (ret >= 0) {
2502 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002503
Eric Laurenta1478072015-09-21 17:21:52 -07002504 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002505
2506 // The usb driver needs to be closed after usb device disconnection
2507 // otherwise audio is no longer played on the new usb devices.
2508 // By forcing the stream in standby, the usb stack refcount drops to 0
2509 // and the driver is closed.
2510 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD && val == AUDIO_DEVICE_NONE &&
2511 audio_is_usb_out_device(out->devices)) {
2512 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2513 out_standby_l(&out->stream.common);
2514 }
2515
Eric Laurent150dbfe2013-02-27 14:31:02 -08002516 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002517
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002518 /*
2519 * When HDMI cable is unplugged the music playback is paused and
2520 * the policy manager sends routing=0. But the audioflinger
2521 * continues to write data until standby time (3sec).
2522 * As the HDMI core is turned off, the write gets blocked.
2523 * Avoid this by routing audio to speaker until standby.
2524 */
2525 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2526 val == AUDIO_DEVICE_NONE) {
2527 val = AUDIO_DEVICE_OUT_SPEAKER;
2528 }
2529
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002530 /*
2531 * When A2DP is disconnected the
2532 * music playback is paused and the policy manager sends routing=0
2533 * But the audioflingercontinues to write data until standby time
2534 * (3sec). As BT is turned off, the write gets blocked.
2535 * Avoid this by routing audio to speaker until standby.
2536 */
2537 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2538 (val == AUDIO_DEVICE_NONE) &&
2539 !audio_extn_a2dp_is_ready()) {
2540 val = AUDIO_DEVICE_OUT_SPEAKER;
2541 }
2542
2543 /* To avoid a2dp to sco overlapping / BT device improper state
2544 * check with BT lib about a2dp streaming support before routing
2545 */
2546 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2547 if (!audio_extn_a2dp_is_ready()) {
2548 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
2549 //combo usecase just by pass a2dp
2550 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2551 bypass_a2dp = true;
2552 } else {
2553 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2554 /* update device to a2dp and don't route as BT returned error
2555 * However it is still possible a2dp routing called because
2556 * of current active device disconnection (like wired headset)
2557 */
2558 out->devices = val;
2559 pthread_mutex_unlock(&out->lock);
2560 pthread_mutex_unlock(&adev->lock);
2561 status = -ENOSYS;
2562 goto routing_fail;
2563 }
2564 }
2565 }
2566
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002567 audio_devices_t new_dev = val;
2568
2569 // Workaround: If routing to an non existing usb device, fail gracefully
2570 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002571 int card;
2572 if (audio_is_usb_out_device(new_dev) &&
2573 (card = get_alive_usb_card(parms)) >= 0) {
2574
2575 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002576 pthread_mutex_unlock(&adev->lock);
2577 pthread_mutex_unlock(&out->lock);
2578 status = -ENOSYS;
2579 goto routing_fail;
2580 }
2581
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002582 /*
2583 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002584 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002585 * the select_devices(). But how do we undo this?
2586 *
2587 * For example, music playback is active on headset (deep-buffer usecase)
2588 * and if we go to ringtones and select a ringtone, low-latency usecase
2589 * will be started on headset+speaker. As we can't enable headset+speaker
2590 * and headset devices at the same time, select_devices() switches the music
2591 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2592 * So when the ringtone playback is completed, how do we undo the same?
2593 *
2594 * We are relying on the out_set_parameters() call on deep-buffer output,
2595 * once the ringtone playback is ended.
2596 * NOTE: We should not check if the current devices are same as new devices.
2597 * Because select_devices() must be called to switch back the music
2598 * playback to headset.
2599 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002600 if (new_dev != AUDIO_DEVICE_NONE) {
2601 bool same_dev = out->devices == new_dev;
2602 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002603
Eric Laurenta7657192014-10-09 21:09:33 -07002604 if (output_drives_call(adev, out)) {
Vignesh Kulothungana5c9da12017-11-10 11:41:24 -08002605 if (!voice_is_call_state_active(adev)) {
Eric Laurenta7657192014-10-09 21:09:33 -07002606 if (adev->mode == AUDIO_MODE_IN_CALL) {
2607 adev->current_call_output = out;
2608 ret = voice_start_call(adev);
2609 }
2610 } else {
2611 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002612 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002613 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002614 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002615
2616 if (!out->standby) {
2617 if (!same_dev) {
2618 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002619 // inform adm before actual routing to prevent glitches.
2620 if (adev->adm_on_routing_change) {
2621 adev->adm_on_routing_change(adev->adm_data,
2622 out->handle);
2623 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002624 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002625 if (!bypass_a2dp) {
2626 select_devices(adev, out->usecase);
2627 } else {
2628 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2629 select_devices(adev, out->usecase);
2630 out->devices = new_dev;
2631 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002632 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002633
2634 // on device switch force swap, lower functions will make sure
2635 // to check if swap is allowed or not.
2636
2637 if (!same_dev)
2638 platform_set_swap_channels(adev, true);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002639
2640 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2641 out->a2dp_compress_mute &&
2642 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
2643 pthread_mutex_lock(&out->compr_mute_lock);
2644 out->a2dp_compress_mute = false;
2645 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
2646 pthread_mutex_unlock(&out->compr_mute_lock);
2647 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002648 }
2649
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002650 }
2651
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002652 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002653 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002654
2655 /*handles device and call state changes*/
2656 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002657 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002658 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002659
2660 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2661 parse_compress_metadata(out, parms);
2662 }
2663
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002664 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002665 ALOGV("%s: exit: code(%d)", __func__, status);
2666 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002667}
2668
Haynes Mathew George569b7482017-05-08 14:44:27 -07002669static bool stream_get_parameter_channels(struct str_parms *query,
2670 struct str_parms *reply,
2671 audio_channel_mask_t *supported_channel_masks) {
2672 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002673 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002674 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002675 size_t i, j;
2676
2677 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2678 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002679 value[0] = '\0';
2680 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002681 while (supported_channel_masks[i] != 0) {
2682 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2683 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002684 if (!first) {
2685 strcat(value, "|");
2686 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002687 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002688 first = false;
2689 break;
2690 }
2691 }
2692 i++;
2693 }
2694 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002695 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002696 return ret >= 0;
2697}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002698
Haynes Mathew George569b7482017-05-08 14:44:27 -07002699static bool stream_get_parameter_formats(struct str_parms *query,
2700 struct str_parms *reply,
2701 audio_format_t *supported_formats) {
2702 int ret = -1;
2703 char value[256];
2704 int i;
2705
2706 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2707 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002708 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002709 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002710 case AUDIO_FORMAT_PCM_16_BIT:
2711 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2712 break;
2713 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2714 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2715 break;
2716 case AUDIO_FORMAT_PCM_32_BIT:
2717 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2718 break;
2719 default:
2720 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002721 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002722 break;
2723 }
2724 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002725 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002726 return ret >= 0;
2727}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002728
Haynes Mathew George569b7482017-05-08 14:44:27 -07002729static bool stream_get_parameter_rates(struct str_parms *query,
2730 struct str_parms *reply,
2731 uint32_t *supported_sample_rates) {
2732
2733 int i;
2734 char value[256];
2735 int ret = -1;
2736 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2737 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002738 value[0] = '\0';
2739 i=0;
2740 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002741 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002742 int avail = sizeof(value) - cursor;
2743 ret = snprintf(value + cursor, avail, "%s%d",
2744 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002745 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002746 if (ret < 0 || ret >= avail) {
2747 // if cursor is at the last element of the array
2748 // overwrite with \0 is duplicate work as
2749 // snprintf already put a \0 in place.
2750 // else
2751 // we had space to write the '|' at value[cursor]
2752 // (which will be overwritten) or no space to fill
2753 // the first element (=> cursor == 0)
2754 value[cursor] = '\0';
2755 break;
2756 }
2757 cursor += ret;
2758 ++i;
2759 }
2760 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2761 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002762 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002763 return ret >= 0;
2764}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002765
Haynes Mathew George569b7482017-05-08 14:44:27 -07002766static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2767{
2768 struct stream_out *out = (struct stream_out *)stream;
2769 struct str_parms *query = str_parms_create_str(keys);
2770 char *str;
2771 struct str_parms *reply = str_parms_create();
2772 bool replied = false;
2773 ALOGV("%s: enter: keys - %s", __func__, keys);
2774
2775 replied |= stream_get_parameter_channels(query, reply,
2776 &out->supported_channel_masks[0]);
2777 replied |= stream_get_parameter_formats(query, reply,
2778 &out->supported_formats[0]);
2779 replied |= stream_get_parameter_rates(query, reply,
2780 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002781 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002782 str = str_parms_to_str(reply);
2783 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002784 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002785 }
2786 str_parms_destroy(query);
2787 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002788 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002789 return str;
2790}
2791
2792static uint32_t out_get_latency(const struct audio_stream_out *stream)
2793{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002794 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002795 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002796 uint32_t latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002797
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002798 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2799 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002800 else if ((out->realtime) ||
2801 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002802 // since the buffer won't be filled up faster than realtime,
2803 // return a smaller number
2804 period_ms = (out->af_period_multiplier * out->config.period_size *
2805 1000) / (out->config.rate);
2806 hw_delay = platform_render_latency(out->usecase)/1000;
2807 return period_ms + hw_delay;
2808 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002809
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002810 latency = (out->config.period_count * out->config.period_size * 1000) /
2811 (out->config.rate);
2812
2813 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
2814 latency += audio_extn_a2dp_get_encoder_latency();
2815
2816 return latency;
2817}
2818
2819static int set_compr_volume(struct audio_stream_out *stream, float left,
2820 float right)
2821{
2822 struct stream_out *out = (struct stream_out *)stream;
2823 int volume[2];
2824 char mixer_ctl_name[128];
2825 struct audio_device *adev = out->dev;
2826 struct mixer_ctl *ctl;
2827 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2828 PCM_PLAYBACK);
2829
2830 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2831 "Compress Playback %d Volume", pcm_device_id);
2832 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2833 if (!ctl) {
2834 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2835 __func__, mixer_ctl_name);
2836 return -EINVAL;
2837 }
2838 ALOGV("%s: ctl for mixer cmd - %s, left %f, right %f",
2839 __func__, mixer_ctl_name, left, right);
2840 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2841 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2842 mixer_ctl_set_array(ctl, volume, sizeof(volume) / sizeof(volume[0]));
2843
2844 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002845}
2846
2847static int out_set_volume(struct audio_stream_out *stream, float left,
2848 float right)
2849{
Eric Laurenta9024de2013-04-04 09:19:12 -07002850 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002851 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002852
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002853 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002854 /* only take left channel into account: the API is for stereo anyway */
2855 out->muted = (left == 0.0f);
2856 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002857 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002858 pthread_mutex_lock(&out->compr_mute_lock);
2859 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
2860 if (!out->a2dp_compress_mute)
2861 ret = set_compr_volume(stream, left, right);
2862 out->volume_l = left;
2863 out->volume_r = right;
2864 pthread_mutex_unlock(&out->compr_mute_lock);
2865 return ret;
vivek mehtaa68fea62017-06-08 19:04:02 -07002866 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002867 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2868 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2869 if (!out->standby) {
2870 // if in standby, cached volume will be sent after stream is opened
2871 audio_extn_utils_send_app_type_gain(out->dev,
2872 out->app_type_cfg.app_type,
2873 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002874 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002875 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002876 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002877
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002878 return -ENOSYS;
2879}
2880
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002881// note: this call is safe only if the stream_cb is
2882// removed first in close_output_stream (as is done now).
2883static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2884{
2885 if (!stream || !parms)
2886 return;
2887
2888 struct stream_out *out = (struct stream_out *)stream;
2889 struct audio_device *adev = out->dev;
2890
2891 card_status_t status;
2892 int card;
2893 if (parse_snd_card_status(parms, &card, &status) < 0)
2894 return;
2895
2896 pthread_mutex_lock(&adev->lock);
2897 bool valid_cb = (card == adev->snd_card);
2898 pthread_mutex_unlock(&adev->lock);
2899
2900 if (!valid_cb)
2901 return;
2902
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002903 lock_output_stream(out);
2904 if (out->card_status != status)
2905 out->card_status = status;
2906 pthread_mutex_unlock(&out->lock);
2907
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002908 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2909 use_case_table[out->usecase],
2910 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2911
2912 if (status == CARD_STATUS_OFFLINE)
2913 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002914
2915 return;
2916}
2917
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002918#ifdef NO_AUDIO_OUT
2919static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002920 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002921{
2922 struct stream_out *out = (struct stream_out *)stream;
2923
2924 /* No Output device supported other than BT for playback.
2925 * Sleep for the amount of buffer duration
2926 */
Eric Laurenta1478072015-09-21 17:21:52 -07002927 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002928 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2929 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002930 out_get_sample_rate(&out->stream.common));
2931 pthread_mutex_unlock(&out->lock);
2932 return bytes;
2933}
2934#endif
2935
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002936static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2937 size_t bytes)
2938{
2939 struct stream_out *out = (struct stream_out *)stream;
2940 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002941 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002942 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002943
Eric Laurenta1478072015-09-21 17:21:52 -07002944 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002945 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07002946 const size_t frame_size = audio_stream_out_frame_size(stream);
2947 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002948
Eric Laurent0e46adf2016-12-16 12:49:24 -08002949 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2950 error_code = ERROR_CODE_WRITE;
2951 goto exit;
2952 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002953
2954 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2955 (audio_extn_a2dp_is_suspended())) {
2956 if (!(out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2957 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2958 ret = -EIO;
2959 goto exit;
2960 }
2961 }
2962 }
2963
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002964 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002965 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002966 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002967 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07002968
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002969 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002970 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002971 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07002972 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002973 goto exit;
2974 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002975
vivek mehta40125092017-08-21 18:48:51 -07002976 // after standby always force set last known cal step
2977 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
2978 ALOGD("%s: retry previous failed cal level set", __func__);
2979 send_gain_dep_calibration_l();
2980 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002981 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002982
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002983 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002984 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002985 if (out->send_new_metadata) {
2986 ALOGVV("send new gapless metadata");
2987 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2988 out->send_new_metadata = 0;
2989 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002990 unsigned int avail;
2991 struct timespec tstamp;
2992 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2993 /* Do not limit write size if the available frames count is unknown */
2994 if (ret != 0) {
2995 avail = bytes;
2996 }
2997 if (avail == 0) {
2998 ret = 0;
2999 } else {
3000 if (avail > bytes) {
3001 avail = bytes;
3002 }
3003 ret = compress_write(out->compr, buffer, avail);
3004 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
3005 __func__, avail, ret);
3006 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003007
Eric Laurent6e895242013-09-05 16:10:57 -07003008 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003009 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
3010 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003011 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003012 compress_start(out->compr);
3013 out->playback_started = 1;
3014 out->offload_state = OFFLOAD_STATE_PLAYING;
3015 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003016 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07003017 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07003018 } else {
3019 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07003020 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003021 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07003022 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003023 return ret;
3024 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07003025 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003026 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003027 size_t bytes_to_write = bytes;
3028
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003029 if (out->muted)
3030 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07003031 // FIXME: this can be removed once audio flinger mixer supports mono output
Nadav Bar3d72cfc2018-01-07 12:19:24 +02003032 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP || out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003033 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3034 int16_t *src = (int16_t *)buffer;
3035 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003036
Eric Laurentad2dde92017-09-20 18:27:31 -07003037 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
3038 out->format != AUDIO_FORMAT_PCM_16_BIT,
3039 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003040
Eric Laurentad2dde92017-09-20 18:27:31 -07003041 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
3042 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
3043 }
3044 bytes_to_write /= 2;
3045 }
3046 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes_to_write);
3047
Glenn Kasten5a59dff2018-02-22 08:05:35 -08003048 long ns = (frames * (int64_t) NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003049 request_out_focus(out, ns);
3050
3051 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3052 if (use_mmap)
Eric Laurentad2dde92017-09-20 18:27:31 -07003053 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003054 else
Eric Laurentad2dde92017-09-20 18:27:31 -07003055 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003056
Haynes Mathew George03c40102016-01-29 17:57:48 -08003057 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07003058 } else {
3059 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003060 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003061 }
3062
3063exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07003064 // For PCM we always consume the buffer and return #bytes regardless of ret.
3065 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003066 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07003067 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003068 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07003069
Andy Hung7401c7c2016-09-21 12:41:21 -07003070 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07003071 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07003072 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3073 ALOGE_IF(out->pcm != NULL,
3074 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07003075 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003076 // usleep not guaranteed for values over 1 second but we don't limit here.
3077 }
3078 }
Andy Hungda9b56b2016-09-16 20:06:35 -07003079
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003080 pthread_mutex_unlock(&out->lock);
3081
3082 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07003083 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003084 if (sleeptime_us != 0)
3085 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003086 }
3087 return bytes;
3088}
3089
3090static int out_get_render_position(const struct audio_stream_out *stream,
3091 uint32_t *dsp_frames)
3092{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003093 struct stream_out *out = (struct stream_out *)stream;
3094 *dsp_frames = 0;
3095 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07003096 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003097 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003098 unsigned long frames = 0;
3099 // TODO: check return value
3100 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
3101 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003102 ALOGVV("%s rendered frames %d sample_rate %d",
3103 __func__, *dsp_frames, out->sample_rate);
3104 }
3105 pthread_mutex_unlock(&out->lock);
3106 return 0;
3107 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003108 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003109}
3110
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003111static int out_add_audio_effect(const struct audio_stream *stream __unused,
3112 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003113{
3114 return 0;
3115}
3116
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003117static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3118 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003119{
3120 return 0;
3121}
3122
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003123static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3124 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003125{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003126 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003127}
3128
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003129static int out_get_presentation_position(const struct audio_stream_out *stream,
3130 uint64_t *frames, struct timespec *timestamp)
3131{
3132 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003133 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07003134 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003135
Eric Laurenta1478072015-09-21 17:21:52 -07003136 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003137
Eric Laurent949a0892013-09-20 09:20:13 -07003138 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3139 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003140 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07003141 compress_get_tstamp(out->compr, &dsp_frames,
3142 &out->sample_rate);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003143 // Adjustment accounts for A2DP encoder latency with offload usecases
3144 // Note: Encoder latency is returned in ms.
3145 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3146 unsigned long offset =
3147 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3148 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
3149 }
Eric Laurent949a0892013-09-20 09:20:13 -07003150 ALOGVV("%s rendered frames %ld sample_rate %d",
3151 __func__, dsp_frames, out->sample_rate);
3152 *frames = dsp_frames;
3153 ret = 0;
3154 /* this is the best we can do */
3155 clock_gettime(CLOCK_MONOTONIC, timestamp);
3156 }
3157 } else {
3158 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07003159 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003160 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3161 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003162 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003163 // This adjustment accounts for buffering after app processor.
3164 // It is based on estimated DSP latency per use case, rather than exact.
3165 signed_frames -=
3166 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3167
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003168 // Adjustment accounts for A2DP encoder latency with non-offload usecases
3169 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3170 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3171 signed_frames -=
3172 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3173 }
3174
Eric Laurent949a0892013-09-20 09:20:13 -07003175 // It would be unusual for this value to be negative, but check just in case ...
3176 if (signed_frames >= 0) {
3177 *frames = signed_frames;
3178 ret = 0;
3179 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003180 }
3181 }
3182 }
3183
3184 pthread_mutex_unlock(&out->lock);
3185
3186 return ret;
3187}
3188
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003189static int out_set_callback(struct audio_stream_out *stream,
3190 stream_callback_t callback, void *cookie)
3191{
3192 struct stream_out *out = (struct stream_out *)stream;
3193
3194 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003195 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003196 out->offload_callback = callback;
3197 out->offload_cookie = cookie;
3198 pthread_mutex_unlock(&out->lock);
3199 return 0;
3200}
3201
3202static int out_pause(struct audio_stream_out* stream)
3203{
3204 struct stream_out *out = (struct stream_out *)stream;
3205 int status = -ENOSYS;
3206 ALOGV("%s", __func__);
3207 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003208 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003209 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
3210 status = compress_pause(out->compr);
3211 out->offload_state = OFFLOAD_STATE_PAUSED;
3212 }
3213 pthread_mutex_unlock(&out->lock);
3214 }
3215 return status;
3216}
3217
3218static int out_resume(struct audio_stream_out* stream)
3219{
3220 struct stream_out *out = (struct stream_out *)stream;
3221 int status = -ENOSYS;
3222 ALOGV("%s", __func__);
3223 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3224 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07003225 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003226 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
3227 status = compress_resume(out->compr);
3228 out->offload_state = OFFLOAD_STATE_PLAYING;
3229 }
3230 pthread_mutex_unlock(&out->lock);
3231 }
3232 return status;
3233}
3234
3235static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3236{
3237 struct stream_out *out = (struct stream_out *)stream;
3238 int status = -ENOSYS;
3239 ALOGV("%s", __func__);
3240 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003241 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003242 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3243 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3244 else
3245 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3246 pthread_mutex_unlock(&out->lock);
3247 }
3248 return status;
3249}
3250
3251static int out_flush(struct audio_stream_out* stream)
3252{
3253 struct stream_out *out = (struct stream_out *)stream;
3254 ALOGV("%s", __func__);
3255 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003256 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003257 stop_compressed_output_l(out);
3258 pthread_mutex_unlock(&out->lock);
3259 return 0;
3260 }
3261 return -ENOSYS;
3262}
3263
Eric Laurent0e46adf2016-12-16 12:49:24 -08003264static int out_stop(const struct audio_stream_out* stream)
3265{
3266 struct stream_out *out = (struct stream_out *)stream;
3267 struct audio_device *adev = out->dev;
3268 int ret = -ENOSYS;
3269
3270 ALOGV("%s", __func__);
3271 pthread_mutex_lock(&adev->lock);
3272 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3273 out->playback_started && out->pcm != NULL) {
3274 pcm_stop(out->pcm);
3275 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08003276 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003277 }
3278 pthread_mutex_unlock(&adev->lock);
3279 return ret;
3280}
3281
3282static int out_start(const struct audio_stream_out* stream)
3283{
3284 struct stream_out *out = (struct stream_out *)stream;
3285 struct audio_device *adev = out->dev;
3286 int ret = -ENOSYS;
3287
3288 ALOGV("%s", __func__);
3289 pthread_mutex_lock(&adev->lock);
3290 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3291 !out->playback_started && out->pcm != NULL) {
3292 ret = start_output_stream(out);
3293 if (ret == 0) {
3294 out->playback_started = true;
3295 }
3296 }
3297 pthread_mutex_unlock(&adev->lock);
3298 return ret;
3299}
3300
Phil Burkbc991042017-02-24 08:06:44 -08003301/*
3302 * Modify config->period_count based on min_size_frames
3303 */
3304static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
3305{
3306 int periodCountRequested = (min_size_frames + config->period_size - 1)
3307 / config->period_size;
3308 int periodCount = MMAP_PERIOD_COUNT_MIN;
3309
3310 ALOGV("%s original config.period_size = %d config.period_count = %d",
3311 __func__, config->period_size, config->period_count);
3312
3313 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
3314 periodCount *= 2;
3315 }
3316 config->period_count = periodCount;
3317
3318 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
3319}
3320
Eric Laurent0e46adf2016-12-16 12:49:24 -08003321static int out_create_mmap_buffer(const struct audio_stream_out *stream,
3322 int32_t min_size_frames,
3323 struct audio_mmap_buffer_info *info)
3324{
3325 struct stream_out *out = (struct stream_out *)stream;
3326 struct audio_device *adev = out->dev;
3327 int ret = 0;
3328 unsigned int offset1;
3329 unsigned int frames1;
3330 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003331 uint32_t mmap_size;
3332 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003333
3334 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003335 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003336 pthread_mutex_lock(&adev->lock);
3337
3338 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003339 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003340 ret = -EINVAL;
3341 goto exit;
3342 }
3343 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003344 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003345 ret = -ENOSYS;
3346 goto exit;
3347 }
3348 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3349 if (out->pcm_device_id < 0) {
3350 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3351 __func__, out->pcm_device_id, out->usecase);
3352 ret = -EINVAL;
3353 goto exit;
3354 }
Phil Burkbc991042017-02-24 08:06:44 -08003355
3356 adjust_mmap_period_count(&out->config, min_size_frames);
3357
Eric Laurent0e46adf2016-12-16 12:49:24 -08003358 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3359 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3360 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3361 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3362 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3363 step = "open";
3364 ret = -ENODEV;
3365 goto exit;
3366 }
3367 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3368 if (ret < 0) {
3369 step = "begin";
3370 goto exit;
3371 }
3372 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003373 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003374 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003375 ret = platform_get_mmap_data_fd(adev->platform,
3376 out->pcm_device_id, 0 /*playback*/,
3377 &info->shared_memory_fd,
3378 &mmap_size);
3379 if (ret < 0) {
3380 // Fall back to non exclusive mode
3381 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3382 } else {
3383 if (mmap_size < buffer_size) {
3384 step = "mmap";
3385 goto exit;
3386 }
3387 // FIXME: indicate exclusive mode support by returning a negative buffer size
3388 info->buffer_size_frames *= -1;
3389 }
3390 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003391
3392 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3393 if (ret < 0) {
3394 step = "commit";
3395 goto exit;
3396 }
Phil Burkbc991042017-02-24 08:06:44 -08003397
3398 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003399 ret = 0;
3400
3401 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3402 __func__, info->shared_memory_address, info->buffer_size_frames);
3403
3404exit:
3405 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003406 if (out->pcm == NULL) {
3407 ALOGE("%s: %s - %d", __func__, step, ret);
3408 } else {
3409 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003410 pcm_close(out->pcm);
3411 out->pcm = NULL;
3412 }
3413 }
3414 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003415 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003416 return ret;
3417}
3418
3419static int out_get_mmap_position(const struct audio_stream_out *stream,
3420 struct audio_mmap_position *position)
3421{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003422 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003423 struct stream_out *out = (struct stream_out *)stream;
3424 ALOGVV("%s", __func__);
3425 if (position == NULL) {
3426 return -EINVAL;
3427 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003428 lock_output_stream(out);
3429 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3430 out->pcm == NULL) {
3431 ret = -ENOSYS;
3432 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003433 }
3434
3435 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003436 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003437 if (ret < 0) {
3438 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003439 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003440 }
Andy Hungfc044e12017-03-20 09:24:22 -07003441 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003442exit:
3443 pthread_mutex_unlock(&out->lock);
3444 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003445}
3446
3447
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003448/** audio_stream_in implementation **/
3449static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3450{
3451 struct stream_in *in = (struct stream_in *)stream;
3452
3453 return in->config.rate;
3454}
3455
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003456static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003457{
3458 return -ENOSYS;
3459}
3460
3461static size_t in_get_buffer_size(const struct audio_stream *stream)
3462{
3463 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003464 return in->config.period_size * in->af_period_multiplier *
3465 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003466}
3467
3468static uint32_t in_get_channels(const struct audio_stream *stream)
3469{
3470 struct stream_in *in = (struct stream_in *)stream;
3471
3472 return in->channel_mask;
3473}
3474
vivek mehta4ed66e62016-04-15 23:33:34 -07003475static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003476{
vivek mehta4ed66e62016-04-15 23:33:34 -07003477 struct stream_in *in = (struct stream_in *)stream;
3478 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003479}
3480
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003481static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003482{
3483 return -ENOSYS;
3484}
3485
3486static int in_standby(struct audio_stream *stream)
3487{
3488 struct stream_in *in = (struct stream_in *)stream;
3489 struct audio_device *adev = in->dev;
3490 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003491 bool do_stop = true;
3492
Eric Laurent994a6932013-07-17 11:51:42 -07003493 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003494
3495 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003496
3497 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003498 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003499 audio_extn_sound_trigger_stop_lab(in);
3500 in->standby = true;
3501 }
3502
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003503 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003504 if (adev->adm_deregister_stream)
3505 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3506
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003507 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003508 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003509 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003510 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003511 in->capture_started = false;
3512 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003513 if (in->pcm) {
3514 pcm_close(in->pcm);
3515 in->pcm = NULL;
3516 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003517 adev->enable_voicerx = false;
3518 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003519 if (do_stop) {
3520 status = stop_input_stream(in);
3521 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003522 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003523 }
3524 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003525 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003526 return status;
3527}
3528
Andy Hungd13f0d32017-06-12 13:58:37 -07003529static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003530{
Andy Hungd13f0d32017-06-12 13:58:37 -07003531 struct stream_in *in = (struct stream_in *)stream;
3532
3533 // We try to get the lock for consistency,
3534 // but it isn't necessary for these variables.
3535 // If we're not in standby, we may be blocked on a read.
3536 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3537 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3538 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3539 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3540
3541 if (locked) {
3542 pthread_mutex_unlock(&in->lock);
3543 }
3544
3545 // dump error info
3546 (void)error_log_dump(
3547 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003548 return 0;
3549}
3550
3551static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3552{
3553 struct stream_in *in = (struct stream_in *)stream;
3554 struct audio_device *adev = in->dev;
3555 struct str_parms *parms;
3556 char *str;
3557 char value[32];
3558 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003559 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003560
Eric Laurent994a6932013-07-17 11:51:42 -07003561 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003562 parms = str_parms_create_str(kvpairs);
3563
3564 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3565
Eric Laurenta1478072015-09-21 17:21:52 -07003566 lock_input_stream(in);
3567
Eric Laurent150dbfe2013-02-27 14:31:02 -08003568 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003569 if (ret >= 0) {
3570 val = atoi(value);
3571 /* no audio source uses val == 0 */
3572 if ((in->source != val) && (val != 0)) {
3573 in->source = val;
3574 }
3575 }
3576
3577 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003578
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003579 if (ret >= 0) {
3580 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003581 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003582
3583 // Workaround: If routing to an non existing usb device, fail gracefully
3584 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003585 int card;
3586 if (audio_is_usb_in_device(val) &&
3587 (card = get_alive_usb_card(parms)) >= 0) {
3588
3589 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003590 status = -ENOSYS;
3591 } else {
3592
3593 in->device = val;
3594 /* If recording is in progress, change the tx device to new device */
3595 if (!in->standby) {
3596 ALOGV("update input routing change");
3597 // inform adm before actual routing to prevent glitches.
3598 if (adev->adm_on_routing_change) {
3599 adev->adm_on_routing_change(adev->adm_data,
3600 in->capture_handle);
3601 }
3602 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003603 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003604 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003605 }
3606 }
3607
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003608 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003609 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003610
3611 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003612 ALOGV("%s: exit: status(%d)", __func__, status);
3613 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003614}
3615
Haynes Mathew George569b7482017-05-08 14:44:27 -07003616static char* in_get_parameters(const struct audio_stream *stream,
3617 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003618{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003619 struct stream_in *in = (struct stream_in *)stream;
3620 struct str_parms *query = str_parms_create_str(keys);
3621 char *str;
3622 struct str_parms *reply = str_parms_create();
3623 bool replied = false;
3624
3625 ALOGV("%s: enter: keys - %s", __func__, keys);
3626 replied |= stream_get_parameter_channels(query, reply,
3627 &in->supported_channel_masks[0]);
3628 replied |= stream_get_parameter_formats(query, reply,
3629 &in->supported_formats[0]);
3630 replied |= stream_get_parameter_rates(query, reply,
3631 &in->supported_sample_rates[0]);
3632 if (replied) {
3633 str = str_parms_to_str(reply);
3634 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003635 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003636 }
3637 str_parms_destroy(query);
3638 str_parms_destroy(reply);
3639 ALOGV("%s: exit: returns - %s", __func__, str);
3640 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003641}
3642
Eric Laurent51f3c662018-04-10 18:21:34 -07003643static int in_set_gain(struct audio_stream_in *stream, float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003644{
Eric Laurent51f3c662018-04-10 18:21:34 -07003645 struct stream_in *in = (struct stream_in *)stream;
3646 char mixer_ctl_name[128];
3647 struct mixer_ctl *ctl;
3648 int ctl_value;
3649
3650 ALOGV("%s: gain %f", __func__, gain);
3651
3652 if (stream == NULL)
3653 return -EINVAL;
3654
3655 /* in_set_gain() only used to silence MMAP capture for now */
3656 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
3657 return -ENOSYS;
3658
3659 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
3660
3661 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
3662 if (!ctl) {
3663 ALOGW("%s: Could not get ctl for mixer cmd - %s",
3664 __func__, mixer_ctl_name);
3665 return -ENOSYS;
3666 }
3667
3668 if (gain < RECORD_GAIN_MIN)
3669 gain = RECORD_GAIN_MIN;
3670 else if (gain > RECORD_GAIN_MAX)
3671 gain = RECORD_GAIN_MAX;
3672 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
3673
3674 mixer_ctl_set_value(ctl, 0, ctl_value);
3675 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003676}
3677
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003678static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3679{
3680 if (!stream || !parms)
3681 return;
3682
3683 struct stream_in *in = (struct stream_in *)stream;
3684 struct audio_device *adev = in->dev;
3685
3686 card_status_t status;
3687 int card;
3688 if (parse_snd_card_status(parms, &card, &status) < 0)
3689 return;
3690
3691 pthread_mutex_lock(&adev->lock);
3692 bool valid_cb = (card == adev->snd_card);
3693 pthread_mutex_unlock(&adev->lock);
3694
3695 if (!valid_cb)
3696 return;
3697
3698 lock_input_stream(in);
3699 if (in->card_status != status)
3700 in->card_status = status;
3701 pthread_mutex_unlock(&in->lock);
3702
3703 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3704 use_case_table[in->usecase],
3705 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3706
3707 // a better solution would be to report error back to AF and let
3708 // it put the stream to standby
3709 if (status == CARD_STATUS_OFFLINE)
3710 in_standby(&in->stream.common);
3711
3712 return;
3713}
3714
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003715static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3716 size_t bytes)
3717{
3718 struct stream_in *in = (struct stream_in *)stream;
3719 struct audio_device *adev = in->dev;
3720 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003721 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003722 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003723
Eric Laurenta1478072015-09-21 17:21:52 -07003724 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003725 const size_t frame_size = audio_stream_in_frame_size(stream);
3726 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003727
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003728 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003729 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003730 /* Read from sound trigger HAL */
3731 audio_extn_sound_trigger_read(in, buffer, bytes);
3732 pthread_mutex_unlock(&in->lock);
3733 return bytes;
3734 }
3735
Eric Laurent0e46adf2016-12-16 12:49:24 -08003736 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3737 ret = -ENOSYS;
3738 goto exit;
3739 }
3740
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003741 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003742 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003743 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003744 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003745 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003746 goto exit;
3747 }
3748 in->standby = 0;
3749 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003750
Andy Hungd13f0d32017-06-12 13:58:37 -07003751 // errors that occur here are read errors.
3752 error_code = ERROR_CODE_READ;
3753
Haynes Mathew George03c40102016-01-29 17:57:48 -08003754 //what's the duration requested by the client?
3755 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3756 in->config.rate;
3757 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003758
Haynes Mathew George03c40102016-01-29 17:57:48 -08003759 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003760 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003761 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003762 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003763 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003764 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003765 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003766 if (ret < 0) {
3767 ALOGE("Failed to read w/err %s", strerror(errno));
3768 ret = -errno;
3769 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003770 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3771 if (bytes % 4 == 0) {
3772 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3773 int_buf_stream = buffer;
3774 for (size_t itt=0; itt < bytes/4 ; itt++) {
3775 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003776 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003777 } else {
3778 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3779 ret = -EINVAL;
3780 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003781 }
3782 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003783 }
3784
Haynes Mathew George03c40102016-01-29 17:57:48 -08003785 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003786
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003787 /*
3788 * Instead of writing zeroes here, we could trust the hardware
3789 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003790 * 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 -08003791 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08003792 if (ret == 0 && adev->mic_muted &&
3793 !voice_is_in_call_rec_stream(in) &&
3794 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003795 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07003796 in->frames_muted += frames;
3797 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003798
3799exit:
3800 pthread_mutex_unlock(&in->lock);
3801
3802 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07003803 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003804 in_standby(&in->stream.common);
3805 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003806 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003807 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07003808 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08003809 }
3810 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003811 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003812 }
3813 return bytes;
3814}
3815
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003816static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003817{
3818 return 0;
3819}
3820
Andy Hung6ebe5962016-01-15 17:46:57 -08003821static int in_get_capture_position(const struct audio_stream_in *stream,
3822 int64_t *frames, int64_t *time)
3823{
3824 if (stream == NULL || frames == NULL || time == NULL) {
3825 return -EINVAL;
3826 }
3827 struct stream_in *in = (struct stream_in *)stream;
3828 int ret = -ENOSYS;
3829
3830 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003831 // note: ST sessions do not close the alsa pcm driver synchronously
3832 // on standby. Therefore, we may return an error even though the
3833 // pcm stream is still opened.
3834 if (in->standby) {
3835 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
3836 "%s stream in standby but pcm not NULL for non ST session", __func__);
3837 goto exit;
3838 }
Andy Hung6ebe5962016-01-15 17:46:57 -08003839 if (in->pcm) {
3840 struct timespec timestamp;
3841 unsigned int avail;
3842 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3843 *frames = in->frames_read + avail;
3844 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3845 ret = 0;
3846 }
3847 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003848exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08003849 pthread_mutex_unlock(&in->lock);
3850 return ret;
3851}
3852
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003853static int add_remove_audio_effect(const struct audio_stream *stream,
3854 effect_handle_t effect,
3855 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003856{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003857 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003858 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003859 int status = 0;
3860 effect_descriptor_t desc;
3861
3862 status = (*effect)->get_descriptor(effect, &desc);
3863 if (status != 0)
3864 return status;
3865
Eric Laurenta1478072015-09-21 17:21:52 -07003866 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003867 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003868 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003869 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003870 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003871 in->enable_aec != enable &&
3872 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3873 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003874 if (!enable)
3875 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003876 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3877 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3878 adev->enable_voicerx = enable;
3879 struct audio_usecase *usecase;
3880 struct listnode *node;
3881 list_for_each(node, &adev->usecase_list) {
3882 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07003883 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07003884 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05003885 }
3886 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003887 if (!in->standby)
3888 select_devices(in->dev, in->usecase);
3889 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003890 if (in->enable_ns != enable &&
3891 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3892 in->enable_ns = enable;
3893 if (!in->standby)
3894 select_devices(in->dev, in->usecase);
3895 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003896 pthread_mutex_unlock(&in->dev->lock);
3897 pthread_mutex_unlock(&in->lock);
3898
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003899 return 0;
3900}
3901
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003902static int in_add_audio_effect(const struct audio_stream *stream,
3903 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003904{
Eric Laurent994a6932013-07-17 11:51:42 -07003905 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003906 return add_remove_audio_effect(stream, effect, true);
3907}
3908
3909static int in_remove_audio_effect(const struct audio_stream *stream,
3910 effect_handle_t effect)
3911{
Eric Laurent994a6932013-07-17 11:51:42 -07003912 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003913 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003914}
3915
Eric Laurent0e46adf2016-12-16 12:49:24 -08003916static int in_stop(const struct audio_stream_in* stream)
3917{
3918 struct stream_in *in = (struct stream_in *)stream;
3919 struct audio_device *adev = in->dev;
3920
3921 int ret = -ENOSYS;
3922 ALOGV("%s", __func__);
3923 pthread_mutex_lock(&adev->lock);
3924 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3925 in->capture_started && in->pcm != NULL) {
3926 pcm_stop(in->pcm);
3927 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003928 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003929 }
3930 pthread_mutex_unlock(&adev->lock);
3931 return ret;
3932}
3933
3934static int in_start(const struct audio_stream_in* stream)
3935{
3936 struct stream_in *in = (struct stream_in *)stream;
3937 struct audio_device *adev = in->dev;
3938 int ret = -ENOSYS;
3939
3940 ALOGV("%s in %p", __func__, in);
3941 pthread_mutex_lock(&adev->lock);
3942 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3943 !in->capture_started && in->pcm != NULL) {
3944 if (!in->capture_started) {
3945 ret = start_input_stream(in);
3946 if (ret == 0) {
3947 in->capture_started = true;
3948 }
3949 }
3950 }
3951 pthread_mutex_unlock(&adev->lock);
3952 return ret;
3953}
3954
3955static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3956 int32_t min_size_frames,
3957 struct audio_mmap_buffer_info *info)
3958{
3959 struct stream_in *in = (struct stream_in *)stream;
3960 struct audio_device *adev = in->dev;
3961 int ret = 0;
3962 unsigned int offset1;
3963 unsigned int frames1;
3964 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003965 uint32_t mmap_size;
3966 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003967
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003968 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003969 pthread_mutex_lock(&adev->lock);
3970 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003971
Eric Laurent0e46adf2016-12-16 12:49:24 -08003972 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003973 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003974 ret = -EINVAL;
3975 goto exit;
3976 }
3977 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003978 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003979 ALOGV("%s in %p", __func__, in);
3980 ret = -ENOSYS;
3981 goto exit;
3982 }
3983 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3984 if (in->pcm_device_id < 0) {
3985 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3986 __func__, in->pcm_device_id, in->usecase);
3987 ret = -EINVAL;
3988 goto exit;
3989 }
Phil Burkbc991042017-02-24 08:06:44 -08003990
3991 adjust_mmap_period_count(&in->config, min_size_frames);
3992
Eric Laurent0e46adf2016-12-16 12:49:24 -08003993 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3994 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3995 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3996 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3997 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3998 step = "open";
3999 ret = -ENODEV;
4000 goto exit;
4001 }
4002
4003 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
4004 if (ret < 0) {
4005 step = "begin";
4006 goto exit;
4007 }
4008 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07004009 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004010 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07004011 ret = platform_get_mmap_data_fd(adev->platform,
4012 in->pcm_device_id, 1 /*capture*/,
4013 &info->shared_memory_fd,
4014 &mmap_size);
4015 if (ret < 0) {
4016 // Fall back to non exclusive mode
4017 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
4018 } else {
4019 if (mmap_size < buffer_size) {
4020 step = "mmap";
4021 goto exit;
4022 }
4023 // FIXME: indicate exclusive mode support by returning a negative buffer size
4024 info->buffer_size_frames *= -1;
4025 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08004026
Haynes Mathew George96483a22017-03-28 14:52:47 -07004027 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004028
4029 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4030 if (ret < 0) {
4031 step = "commit";
4032 goto exit;
4033 }
4034
Phil Burkbc991042017-02-24 08:06:44 -08004035 in->standby = false;
4036 ret = 0;
4037
Eric Laurent0e46adf2016-12-16 12:49:24 -08004038 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4039 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004040
4041exit:
4042 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004043 if (in->pcm == NULL) {
4044 ALOGE("%s: %s - %d", __func__, step, ret);
4045 } else {
4046 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08004047 pcm_close(in->pcm);
4048 in->pcm = NULL;
4049 }
4050 }
4051 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004052 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004053 return ret;
4054}
4055
4056static int in_get_mmap_position(const struct audio_stream_in *stream,
4057 struct audio_mmap_position *position)
4058{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004059 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004060 struct stream_in *in = (struct stream_in *)stream;
4061 ALOGVV("%s", __func__);
4062 if (position == NULL) {
4063 return -EINVAL;
4064 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004065 lock_input_stream(in);
4066 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
4067 in->pcm == NULL) {
4068 ret = -ENOSYS;
4069 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004070 }
4071 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004072 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004073 if (ret < 0) {
4074 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004075 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004076 }
Andy Hungfc044e12017-03-20 09:24:22 -07004077 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004078exit:
4079 pthread_mutex_unlock(&in->lock);
4080 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004081}
4082
jiabin8962a4d2018-03-19 18:21:24 -07004083static int in_get_active_microphones(const struct audio_stream_in *stream,
4084 struct audio_microphone_characteristic_t *mic_array,
4085 size_t *mic_count) {
4086 struct stream_in *in = (struct stream_in *)stream;
4087 struct audio_device *adev = in->dev;
4088 ALOGVV("%s", __func__);
4089
4090 lock_input_stream(in);
4091 pthread_mutex_lock(&adev->lock);
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004092 int ret = platform_get_active_microphones(adev->platform,
jiabin8962a4d2018-03-19 18:21:24 -07004093 audio_channel_count_from_in_mask(in->channel_mask),
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004094 in->usecase, mic_array, mic_count);
jiabin8962a4d2018-03-19 18:21:24 -07004095 pthread_mutex_unlock(&adev->lock);
4096 pthread_mutex_unlock(&in->lock);
4097
4098 return ret;
4099}
4100
4101static int adev_get_microphones(const struct audio_hw_device *dev,
4102 struct audio_microphone_characteristic_t *mic_array,
4103 size_t *mic_count) {
4104 struct audio_device *adev = (struct audio_device *)dev;
4105 ALOGVV("%s", __func__);
4106
4107 pthread_mutex_lock(&adev->lock);
4108 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
4109 pthread_mutex_unlock(&adev->lock);
4110
4111 return ret;
4112}
Eric Laurent0e46adf2016-12-16 12:49:24 -08004113
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004114static int adev_open_output_stream(struct audio_hw_device *dev,
4115 audio_io_handle_t handle,
4116 audio_devices_t devices,
4117 audio_output_flags_t flags,
4118 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07004119 struct audio_stream_out **stream_out,
4120 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004121{
4122 struct audio_device *adev = (struct audio_device *)dev;
4123 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004124 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004125 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
4126 bool is_usb_dev = audio_is_usb_out_device(devices) &&
4127 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004128
Andy Hungd9653bd2017-08-01 19:31:39 -07004129 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
4130 return -ENOSYS;
4131 }
4132
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004133 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
4134 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004135 *stream_out = NULL;
4136 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4137
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004138 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
4139
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004140 if (devices == AUDIO_DEVICE_NONE)
4141 devices = AUDIO_DEVICE_OUT_SPEAKER;
4142
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004143 out->flags = flags;
4144 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004145 out->dev = adev;
Eric Laurentc4aef752013-09-12 17:45:53 -07004146 out->handle = handle;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004147 out->a2dp_compress_mute = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004148
4149 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004150 if ((is_hdmi || is_usb_dev) &&
4151 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
4152 (flags == AUDIO_OUTPUT_FLAG_NONE ||
4153 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Eric Laurentab805ee2018-03-30 12:20:38 -07004154 audio_format_t req_format = config->format;
4155 audio_channel_mask_t req_channel_mask = config->channel_mask;
4156 uint32_t req_sample_rate = config->sample_rate;
4157
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004158 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004159 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004160 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004161 if (config->sample_rate == 0)
4162 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Eric Laurentab805ee2018-03-30 12:20:38 -07004163 if (config->channel_mask == AUDIO_CHANNEL_NONE)
Haynes Mathew George569b7482017-05-08 14:44:27 -07004164 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
4165 if (config->format == AUDIO_FORMAT_DEFAULT)
4166 config->format = AUDIO_FORMAT_PCM_16_BIT;
4167 } else if (is_usb_dev) {
4168 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
4169 &config->format,
4170 &out->supported_formats[0],
4171 MAX_SUPPORTED_FORMATS,
4172 &config->channel_mask,
4173 &out->supported_channel_masks[0],
4174 MAX_SUPPORTED_CHANNEL_MASKS,
4175 &config->sample_rate,
4176 &out->supported_sample_rates[0],
4177 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004178 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004179 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004180 pthread_mutex_unlock(&adev->lock);
Eric Laurentab805ee2018-03-30 12:20:38 -07004181 if (ret != 0) {
4182 // For MMAP NO IRQ, allow conversions in ADSP
4183 if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
4184 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004185
Eric Laurentab805ee2018-03-30 12:20:38 -07004186 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
4187 config->sample_rate = req_sample_rate;
4188 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
4189 config->channel_mask = req_channel_mask;
4190 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
4191 config->format = req_format;
4192 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004193
Haynes Mathew George569b7482017-05-08 14:44:27 -07004194 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004195 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004196 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004197 if (is_hdmi) {
4198 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4199 out->config = pcm_config_hdmi_multi;
4200 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
4201 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4202 out->config = pcm_config_mmap_playback;
4203 out->stream.start = out_start;
4204 out->stream.stop = out_stop;
4205 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4206 out->stream.get_mmap_position = out_get_mmap_position;
4207 } else {
4208 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4209 out->config = pcm_config_hifi;
4210 }
4211
4212 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004213 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004214 if (is_hdmi) {
4215 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
4216 audio_bytes_per_sample(out->format));
4217 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004218 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004219 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07004220 pthread_mutex_lock(&adev->lock);
4221 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4222 pthread_mutex_unlock(&adev->lock);
4223
4224 // reject offload during card offline to allow
4225 // fallback to s/w paths
4226 if (offline) {
4227 ret = -ENODEV;
4228 goto error_open;
4229 }
4230
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004231 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4232 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4233 ALOGE("%s: Unsupported Offload information", __func__);
4234 ret = -EINVAL;
4235 goto error_open;
4236 }
4237 if (!is_supported_format(config->offload_info.format)) {
4238 ALOGE("%s: Unsupported audio format", __func__);
4239 ret = -EINVAL;
4240 goto error_open;
4241 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004242 out->sample_rate = config->offload_info.sample_rate;
4243 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
4244 out->channel_mask = config->offload_info.channel_mask;
4245 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
4246 out->channel_mask = config->channel_mask;
4247 else
4248 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4249
4250 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004251
4252 out->compr_config.codec = (struct snd_codec *)
4253 calloc(1, sizeof(struct snd_codec));
4254
4255 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004256
4257 out->stream.set_callback = out_set_callback;
4258 out->stream.pause = out_pause;
4259 out->stream.resume = out_resume;
4260 out->stream.drain = out_drain;
4261 out->stream.flush = out_flush;
4262
4263 out->compr_config.codec->id =
4264 get_snd_codec_id(config->offload_info.format);
4265 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
4266 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004267 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004268 out->compr_config.codec->bit_rate =
4269 config->offload_info.bit_rate;
4270 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004271 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004272 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
4273
4274 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4275 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004276
4277 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004278 create_offload_callback_thread(out);
4279 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4280 __func__, config->offload_info.version,
4281 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02004282 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4283 switch (config->sample_rate) {
4284 case 0:
4285 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4286 break;
4287 case 8000:
4288 case 16000:
4289 case 48000:
4290 out->sample_rate = config->sample_rate;
4291 break;
4292 default:
4293 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
4294 config->sample_rate);
4295 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4296 ret = -EINVAL;
4297 goto error_open;
4298 }
4299 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4300 switch (config->channel_mask) {
4301 case AUDIO_CHANNEL_NONE:
4302 case AUDIO_CHANNEL_OUT_STEREO:
4303 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4304 break;
4305 default:
4306 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
4307 config->channel_mask);
4308 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4309 ret = -EINVAL;
4310 goto error_open;
4311 }
4312 switch (config->format) {
4313 case AUDIO_FORMAT_DEFAULT:
4314 case AUDIO_FORMAT_PCM_16_BIT:
4315 out->format = AUDIO_FORMAT_PCM_16_BIT;
4316 break;
4317 default:
4318 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
4319 config->format);
4320 config->format = AUDIO_FORMAT_PCM_16_BIT;
4321 ret = -EINVAL;
4322 goto error_open;
4323 }
4324
4325 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004326 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004327 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004328 case 0:
4329 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
4330 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07004331 case 8000:
4332 case 16000:
4333 case 48000:
4334 out->sample_rate = config->sample_rate;
4335 break;
4336 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004337 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
4338 config->sample_rate);
4339 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4340 ret = -EINVAL;
4341 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004342 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004343 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4344 switch (config->channel_mask) {
4345 case AUDIO_CHANNEL_NONE:
4346 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4347 break;
4348 case AUDIO_CHANNEL_OUT_STEREO:
4349 out->channel_mask = config->channel_mask;
4350 break;
4351 default:
4352 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
4353 config->channel_mask);
4354 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4355 ret = -EINVAL;
4356 break;
4357 }
4358 switch (config->format) {
4359 case AUDIO_FORMAT_DEFAULT:
4360 out->format = AUDIO_FORMAT_PCM_16_BIT;
4361 break;
4362 case AUDIO_FORMAT_PCM_16_BIT:
4363 out->format = config->format;
4364 break;
4365 default:
4366 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
4367 config->format);
4368 config->format = AUDIO_FORMAT_PCM_16_BIT;
4369 ret = -EINVAL;
4370 break;
4371 }
4372 if (ret != 0)
4373 goto error_open;
4374
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004375 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4376 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004377 out->config.rate = out->sample_rate;
4378 out->config.channels =
4379 audio_channel_count_from_out_mask(out->channel_mask);
4380 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004381 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004382 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
4383 switch (config->sample_rate) {
4384 case 0:
4385 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4386 break;
4387 case 8000:
4388 case 16000:
4389 case 32000:
4390 case 48000:
4391 out->sample_rate = config->sample_rate;
4392 break;
4393 default:
4394 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
4395 config->sample_rate);
4396 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4397 ret = -EINVAL;
4398 break;
4399 }
Eric Laurentad2dde92017-09-20 18:27:31 -07004400 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004401 switch (config->channel_mask) {
4402 case AUDIO_CHANNEL_NONE:
4403 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4404 break;
4405 case AUDIO_CHANNEL_OUT_STEREO:
4406 out->channel_mask = config->channel_mask;
4407 break;
4408 default:
4409 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
4410 config->channel_mask);
4411 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4412 ret = -EINVAL;
4413 break;
4414 }
4415 switch (config->format) {
4416 case AUDIO_FORMAT_DEFAULT:
4417 out->format = AUDIO_FORMAT_PCM_16_BIT;
4418 break;
4419 case AUDIO_FORMAT_PCM_16_BIT:
4420 out->format = config->format;
4421 break;
4422 default:
4423 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
4424 config->format);
4425 config->format = AUDIO_FORMAT_PCM_16_BIT;
4426 ret = -EINVAL;
4427 break;
4428 }
4429 if (ret != 0)
4430 goto error_open;
4431
vivek mehtaa68fea62017-06-08 19:04:02 -07004432 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07004433 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4434 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004435 out->config.rate = out->sample_rate;
4436 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07004437 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004438 out->sample_rate,
4439 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07004440 out->config.channels,
4441 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004442 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07004443 out->config.period_size = buffer_size / frame_size;
4444 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
4445 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004446 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004447 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07004448 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4449 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004450 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07004451 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
4452 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004453 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07004454 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004455 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004456 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004457 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004458 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4459 out->config = pcm_config_mmap_playback;
4460 out->stream.start = out_start;
4461 out->stream.stop = out_stop;
4462 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4463 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004464 } else {
4465 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4466 out->config = pcm_config_low_latency;
4467 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004468
4469 if (config->sample_rate == 0) {
4470 out->sample_rate = out->config.rate;
4471 } else {
4472 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004473 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004474 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
4475 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
4476 } else {
4477 out->channel_mask = config->channel_mask;
4478 }
4479 if (config->format == AUDIO_FORMAT_DEFAULT)
4480 out->format = audio_format_from_pcm_format(out->config.format);
4481 else if (!audio_is_linear_pcm(config->format)) {
4482 config->format = AUDIO_FORMAT_PCM_16_BIT;
4483 ret = -EINVAL;
4484 goto error_open;
4485 } else {
4486 out->format = config->format;
4487 }
4488
4489 out->config.rate = out->sample_rate;
4490 out->config.channels =
4491 audio_channel_count_from_out_mask(out->channel_mask);
4492 if (out->format != audio_format_from_pcm_format(out->config.format)) {
4493 out->config.format = pcm_format_from_audio_format(out->format);
4494 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004495 }
Kevin Rocard50eff892017-05-02 16:52:05 -07004496
4497 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
4498 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004499 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004500 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
4501 __func__, config->sample_rate, config->format, config->channel_mask);
4502 config->sample_rate = out->sample_rate;
4503 config->format = out->format;
4504 config->channel_mask = out->channel_mask;
4505 ret = -EINVAL;
4506 goto error_open;
4507 }
4508
Andy Hung6fcba9c2014-03-18 11:53:32 -07004509 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
4510 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004511
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004512 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004513 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004514 adev->primary_output = out;
4515 else {
4516 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004517 ret = -EEXIST;
4518 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004519 }
4520 }
4521
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004522 /* Check if this usecase is already existing */
4523 pthread_mutex_lock(&adev->lock);
4524 if (get_usecase_from_list(adev, out->usecase) != NULL) {
4525 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004526 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004527 ret = -EEXIST;
4528 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004529 }
4530 pthread_mutex_unlock(&adev->lock);
4531
4532 out->stream.common.get_sample_rate = out_get_sample_rate;
4533 out->stream.common.set_sample_rate = out_set_sample_rate;
4534 out->stream.common.get_buffer_size = out_get_buffer_size;
4535 out->stream.common.get_channels = out_get_channels;
4536 out->stream.common.get_format = out_get_format;
4537 out->stream.common.set_format = out_set_format;
4538 out->stream.common.standby = out_standby;
4539 out->stream.common.dump = out_dump;
4540 out->stream.common.set_parameters = out_set_parameters;
4541 out->stream.common.get_parameters = out_get_parameters;
4542 out->stream.common.add_audio_effect = out_add_audio_effect;
4543 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4544 out->stream.get_latency = out_get_latency;
4545 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004546#ifdef NO_AUDIO_OUT
4547 out->stream.write = out_write_for_no_output;
4548#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004549 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004550#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004551 out->stream.get_render_position = out_get_render_position;
4552 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004553 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004554
Eric Laurent0e46adf2016-12-16 12:49:24 -08004555 if (out->realtime)
4556 out->af_period_multiplier = af_period_multiplier;
4557 else
4558 out->af_period_multiplier = 1;
4559
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004560 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004561 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004562 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004563
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004564 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004565 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004566 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4567
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004568 config->format = out->stream.common.get_format(&out->stream.common);
4569 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4570 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4571
Kevin Rocarda325aa22018-04-03 09:15:52 -07004572 register_format(out->format, out->supported_formats);
4573 register_channel_mask(out->channel_mask, out->supported_channel_masks);
4574 register_sample_rate(out->sample_rate, out->supported_sample_rates);
4575
Andy Hunga452b0a2017-03-15 14:51:15 -07004576 out->error_log = error_log_create(
4577 ERROR_LOG_ENTRIES,
4578 1000000000 /* aggregate consecutive identical errors within one second in ns */);
4579
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004580 /*
4581 By locking output stream before registering, we allow the callback
4582 to update stream's state only after stream's initial state is set to
4583 adev state.
4584 */
4585 lock_output_stream(out);
4586 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4587 pthread_mutex_lock(&adev->lock);
4588 out->card_status = adev->card_status;
4589 pthread_mutex_unlock(&adev->lock);
4590 pthread_mutex_unlock(&out->lock);
4591
vivek mehta4a824772017-06-08 19:05:49 -07004592 stream_app_type_cfg_init(&out->app_type_cfg);
4593
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004594 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004595
Eric Laurent994a6932013-07-17 11:51:42 -07004596 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004597 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004598
4599error_open:
4600 free(out);
4601 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07004602 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004603 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004604}
4605
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004606static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004607 struct audio_stream_out *stream)
4608{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004609 struct stream_out *out = (struct stream_out *)stream;
4610 struct audio_device *adev = out->dev;
4611
Eric Laurent994a6932013-07-17 11:51:42 -07004612 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004613
4614 // must deregister from sndmonitor first to prevent races
4615 // between the callback and close_stream
4616 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004617 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004618 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
4619 destroy_offload_callback_thread(out);
4620
4621 if (out->compr_config.codec != NULL)
4622 free(out->compr_config.codec);
4623 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004624
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004625 out->a2dp_compress_mute = false;
4626
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004627 if (adev->voice_tx_output == out)
4628 adev->voice_tx_output = NULL;
4629
Andy Hunga452b0a2017-03-15 14:51:15 -07004630 error_log_destroy(out->error_log);
4631 out->error_log = NULL;
4632
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004633 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004634 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004635 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004636 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004637 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004638}
4639
4640static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4641{
4642 struct audio_device *adev = (struct audio_device *)dev;
4643 struct str_parms *parms;
4644 char *str;
4645 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004646 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004647 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07004648 int status = 0;
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004649 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004650
Joe Onorato188b6222016-03-01 11:02:27 -08004651 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004652
4653 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004654
4655 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004656 status = voice_set_parameters(adev, parms);
4657 if (status != 0) {
4658 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004659 }
4660
4661 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4662 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07004663 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004664 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4665 adev->bluetooth_nrec = true;
4666 else
4667 adev->bluetooth_nrec = false;
4668 }
4669
4670 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4671 if (ret >= 0) {
4672 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4673 adev->screen_off = false;
4674 else
4675 adev->screen_off = true;
4676 }
4677
jasmine cha270b7762018-03-30 15:41:33 +08004678#ifndef MAXXAUDIO_QDSP_ENABLED
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004679 ret = str_parms_get_int(parms, "rotation", &val);
4680 if (ret >= 0) {
4681 bool reverse_speakers = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004682 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004683 // FIXME: note that the code below assumes that the speakers are in the correct placement
4684 // relative to the user when the device is rotated 90deg from its default rotation. This
4685 // assumption is device-specific, not platform-specific like this code.
4686 case 270:
4687 reverse_speakers = true;
4688 break;
4689 case 0:
4690 case 90:
4691 case 180:
4692 break;
4693 default:
4694 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07004695 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004696 }
Eric Laurent03f09432014-03-25 18:09:11 -07004697 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004698 // check and set swap
4699 // - check if orientation changed and speaker active
4700 // - set rotation and cache the rotation value
4701 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004702 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004703 }
jasmine cha270b7762018-03-30 15:41:33 +08004704#endif
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004705
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004706 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4707 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004708 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004709 }
4710
David Linee3fe402017-03-13 10:00:42 -07004711 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4712 if (ret >= 0) {
4713 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004714 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004715 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4716 if (ret >= 0) {
4717 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004718 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004719 }
Eric Laurent99dab492017-06-17 15:19:08 -07004720 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004721 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4722 if (ret >= 0) {
4723 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004724 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004725 }
4726 }
4727 }
4728
4729 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4730 if (ret >= 0) {
4731 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004732 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004733 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4734 if (ret >= 0) {
4735 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004736 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004737 }
Eric Laurent99dab492017-06-17 15:19:08 -07004738 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004739 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4740 if (ret >= 0) {
4741 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004742 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004743 }
4744 }
4745 }
4746
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004747 audio_extn_hfp_set_parameters(adev, parms);
jasmine cha270b7762018-03-30 15:41:33 +08004748 audio_extn_ma_set_parameters(adev, parms);
4749
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004750 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
4751 if (status >= 0 && a2dp_reconfig) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004752 struct audio_usecase *usecase;
4753 struct listnode *node;
4754 list_for_each(node, &adev->usecase_list) {
4755 usecase = node_to_item(node, struct audio_usecase, list);
4756 if ((usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004757 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004758 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
4759
4760 pthread_mutex_unlock(&adev->lock);
4761 lock_output_stream(usecase->stream.out);
4762 pthread_mutex_lock(&adev->lock);
4763 audio_extn_a2dp_set_handoff_mode(true);
4764 // force device switch to reconfigure encoder
4765 select_devices(adev, usecase->id);
4766 audio_extn_a2dp_set_handoff_mode(false);
4767 pthread_mutex_unlock(&usecase->stream.out->lock);
4768 break;
4769 }
4770 }
4771 }
4772
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004773done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004774 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004775 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004776 ALOGV("%s: exit with code(%d)", __func__, status);
4777 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004778}
4779
4780static char* adev_get_parameters(const struct audio_hw_device *dev,
4781 const char *keys)
4782{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004783 struct audio_device *adev = (struct audio_device *)dev;
4784 struct str_parms *reply = str_parms_create();
4785 struct str_parms *query = str_parms_create_str(keys);
4786 char *str;
4787
4788 pthread_mutex_lock(&adev->lock);
4789
4790 voice_get_parameters(adev, query, reply);
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004791 audio_extn_a2dp_get_parameters(query, reply);
4792
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004793 str = str_parms_to_str(reply);
4794 str_parms_destroy(query);
4795 str_parms_destroy(reply);
4796
4797 pthread_mutex_unlock(&adev->lock);
4798 ALOGV("%s: exit: returns - %s", __func__, str);
4799 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004800}
4801
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004802static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004803{
4804 return 0;
4805}
4806
Haynes Mathew George5191a852013-09-11 14:19:36 -07004807static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4808{
4809 int ret;
4810 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004811
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004812 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4813
Haynes Mathew George5191a852013-09-11 14:19:36 -07004814 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004815 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004816 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004817
Haynes Mathew George5191a852013-09-11 14:19:36 -07004818 return ret;
4819}
4820
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004821static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004822{
4823 return -ENOSYS;
4824}
4825
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004826static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4827 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004828{
4829 return -ENOSYS;
4830}
4831
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004832static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004833{
4834 return -ENOSYS;
4835}
4836
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004837static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004838{
4839 return -ENOSYS;
4840}
4841
4842static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4843{
4844 struct audio_device *adev = (struct audio_device *)dev;
4845
4846 pthread_mutex_lock(&adev->lock);
4847 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004848 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004849 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004850 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4851 voice_is_in_call(adev)) {
4852 voice_stop_call(adev);
4853 adev->current_call_output = NULL;
4854 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004855 }
4856 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004857
4858 audio_extn_extspk_set_mode(adev->extspk, mode);
4859
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004860 return 0;
4861}
4862
4863static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4864{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004865 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004866 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004867
Eric Laurent2bafff12016-03-17 12:17:23 -07004868 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004869 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004870 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4871 ret = audio_extn_hfp_set_mic_mute(adev, state);
4872 } else {
4873 ret = voice_set_mic_mute(adev, state);
4874 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004875 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004876 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004877
4878 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004879}
4880
4881static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4882{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004883 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004884 return 0;
4885}
4886
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004887static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004888 const struct audio_config *config)
4889{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004890 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004891
Eric Laurent74b55762017-07-09 17:04:53 -07004892 /* Don't know if USB HIFI in this context so use true to be conservative */
4893 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4894 true /*is_usb_hifi */) != 0)
4895 return 0;
4896
vivek mehtaa68fea62017-06-08 19:04:02 -07004897 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4898 config->sample_rate, config->format,
4899 channel_count,
4900 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004901}
4902
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004903static bool adev_input_allow_hifi_record(struct audio_device *adev,
4904 audio_devices_t devices,
4905 audio_input_flags_t flags,
4906 audio_source_t source) {
4907 const bool allowed = true;
4908
4909 if (!audio_is_usb_in_device(devices))
4910 return !allowed;
4911
4912 switch (flags) {
4913 case AUDIO_INPUT_FLAG_NONE:
4914 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4915 break;
4916 default:
4917 return !allowed;
4918 }
4919
4920 switch (source) {
4921 case AUDIO_SOURCE_DEFAULT:
4922 case AUDIO_SOURCE_MIC:
4923 case AUDIO_SOURCE_UNPROCESSED:
4924 break;
4925 default:
4926 return !allowed;
4927 }
4928
4929 switch (adev->mode) {
4930 case 0:
4931 break;
4932 default:
4933 return !allowed;
4934 }
4935
4936 return allowed;
4937}
4938
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004939static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004940 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004941 audio_devices_t devices,
4942 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004943 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004944 audio_input_flags_t flags,
4945 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004946 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004947{
4948 struct audio_device *adev = (struct audio_device *)dev;
4949 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004950 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004951 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004952 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004953 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004954 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4955 devices,
4956 flags,
4957 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004958 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004959 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004960
Andy Hungd9653bd2017-08-01 19:31:39 -07004961 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
4962 return -ENOSYS;
4963 }
4964
Eric Laurent74b55762017-07-09 17:04:53 -07004965 if (!(is_usb_dev && may_use_hifi_record)) {
4966 if (config->sample_rate == 0)
4967 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4968 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4969 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4970 if (config->format == AUDIO_FORMAT_DEFAULT)
4971 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004972
Eric Laurent74b55762017-07-09 17:04:53 -07004973 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
4974
4975 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
4976 return -EINVAL;
4977 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004978
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004979 if (audio_extn_tfa_98xx_is_supported() &&
4980 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004981 return -EINVAL;
4982
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004983 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4984
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004985 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004986 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004987
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004988 in->stream.common.get_sample_rate = in_get_sample_rate;
4989 in->stream.common.set_sample_rate = in_set_sample_rate;
4990 in->stream.common.get_buffer_size = in_get_buffer_size;
4991 in->stream.common.get_channels = in_get_channels;
4992 in->stream.common.get_format = in_get_format;
4993 in->stream.common.set_format = in_set_format;
4994 in->stream.common.standby = in_standby;
4995 in->stream.common.dump = in_dump;
4996 in->stream.common.set_parameters = in_set_parameters;
4997 in->stream.common.get_parameters = in_get_parameters;
4998 in->stream.common.add_audio_effect = in_add_audio_effect;
4999 in->stream.common.remove_audio_effect = in_remove_audio_effect;
5000 in->stream.set_gain = in_set_gain;
5001 in->stream.read = in_read;
5002 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08005003 in->stream.get_capture_position = in_get_capture_position;
jiabin8962a4d2018-03-19 18:21:24 -07005004 in->stream.get_active_microphones = in_get_active_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005005
5006 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005007 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005008 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005009 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005010 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005011 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005012
Arun Mirpuriba2749a2018-04-17 14:32:24 -07005013 ALOGV("%s: source = %d, config->channel_mask = %d", __func__, source, config->channel_mask);
5014 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
5015 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
5016 /* Force channel config requested to mono if incall
5017 record is being requested for only uplink/downlink */
5018 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
5019 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5020 ret = -EINVAL;
5021 goto err_open;
5022 }
5023 }
5024
Haynes Mathew George569b7482017-05-08 14:44:27 -07005025 if (is_usb_dev && may_use_hifi_record) {
5026 /* HiFi record selects an appropriate format, channel, rate combo
5027 depending on sink capabilities*/
5028 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
5029 &config->format,
5030 &in->supported_formats[0],
5031 MAX_SUPPORTED_FORMATS,
5032 &config->channel_mask,
5033 &in->supported_channel_masks[0],
5034 MAX_SUPPORTED_CHANNEL_MASKS,
5035 &config->sample_rate,
5036 &in->supported_sample_rates[0],
5037 MAX_SUPPORTED_SAMPLE_RATES);
5038 if (ret != 0) {
5039 ret = -EINVAL;
5040 goto err_open;
5041 }
Eric Laurent74b55762017-07-09 17:04:53 -07005042 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005043 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07005044 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07005045 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
5046 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
5047 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5048 bool ret_error = false;
5049 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5050 from HAL is 8_24
5051 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5052 8_24 return error indicating supported format is 8_24
5053 *> In case of any other source requesting 24 bit or float return error
5054 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07005055
vivek mehta57ff9b52016-04-28 14:13:08 -07005056 on error flinger will retry with supported format passed
5057 */
5058 if (source != AUDIO_SOURCE_UNPROCESSED) {
5059 config->format = AUDIO_FORMAT_PCM_16_BIT;
5060 ret_error = true;
5061 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
5062 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
5063 ret_error = true;
5064 }
5065
5066 if (ret_error) {
5067 ret = -EINVAL;
5068 goto err_open;
5069 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005070 }
5071
vivek mehta57ff9b52016-04-28 14:13:08 -07005072 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07005073 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07005074
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005075 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005076 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
5077 if (config->sample_rate == 0)
5078 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5079 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5080 config->sample_rate != 8000) {
5081 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5082 ret = -EINVAL;
5083 goto err_open;
5084 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005085
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005086 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5087 config->format = AUDIO_FORMAT_PCM_16_BIT;
5088 ret = -EINVAL;
5089 goto err_open;
5090 }
5091
5092 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5093 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07005094 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005095 } else if (is_usb_dev && may_use_hifi_record) {
5096 in->usecase = USECASE_AUDIO_RECORD_HIFI;
5097 in->config = pcm_config_audio_capture;
5098 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005099 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5100 config->sample_rate,
5101 config->format,
5102 channel_count,
5103 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005104 in->config.period_size = buffer_size / frame_size;
5105 in->config.rate = config->sample_rate;
5106 in->af_period_multiplier = 1;
5107 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005108 } else {
5109 in->usecase = USECASE_AUDIO_RECORD;
5110 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08005111 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005112 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07005113#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005114 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07005115#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08005116 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005117 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08005118 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005119 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005120 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5121 config->sample_rate,
5122 config->format,
5123 channel_count,
5124 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005125 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005126 in->config.rate = config->sample_rate;
5127 in->af_period_multiplier = 1;
5128 } else {
5129 // period size is left untouched for rt mode playback
5130 in->config = pcm_config_audio_capture_rt;
5131 in->af_period_multiplier = af_period_multiplier;
5132 }
5133 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
5134 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005135 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08005136 in->usecase = USECASE_AUDIO_RECORD_MMAP;
5137 in->config = pcm_config_mmap_capture;
5138 in->stream.start = in_start;
5139 in->stream.stop = in_stop;
5140 in->stream.create_mmap_buffer = in_create_mmap_buffer;
5141 in->stream.get_mmap_position = in_get_mmap_position;
5142 in->af_period_multiplier = 1;
5143 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07005144 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07005145 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07005146 (config->sample_rate == 8000 ||
5147 config->sample_rate == 16000 ||
5148 config->sample_rate == 32000 ||
5149 config->sample_rate == 48000) &&
5150 channel_count == 1) {
5151 in->usecase = USECASE_AUDIO_RECORD_VOIP;
5152 in->config = pcm_config_audio_capture;
5153 frame_size = audio_stream_in_frame_size(&in->stream);
5154 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
5155 config->sample_rate,
5156 config->format,
5157 channel_count, false /*is_low_latency*/);
5158 in->config.period_size = buffer_size / frame_size;
5159 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
5160 in->config.rate = config->sample_rate;
5161 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005162 } else {
5163 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005164 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005165 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5166 config->sample_rate,
5167 config->format,
5168 channel_count,
5169 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005170 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005171 in->config.rate = config->sample_rate;
5172 in->af_period_multiplier = 1;
5173 }
5174 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
5175 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005176 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08005177
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005178 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07005179 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005180
Kevin Rocarda325aa22018-04-03 09:15:52 -07005181
5182 register_format(in->format, in->supported_formats);
5183 register_channel_mask(in->channel_mask, in->supported_channel_masks);
5184 register_sample_rate(in->sample_rate, in->supported_sample_rates);
5185
Andy Hungd13f0d32017-06-12 13:58:37 -07005186 in->error_log = error_log_create(
5187 ERROR_LOG_ENTRIES,
5188 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
5189
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005190 /* This stream could be for sound trigger lab,
5191 get sound trigger pcm if present */
5192 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005193
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005194 lock_input_stream(in);
5195 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5196 pthread_mutex_lock(&adev->lock);
5197 in->card_status = adev->card_status;
5198 pthread_mutex_unlock(&adev->lock);
5199 pthread_mutex_unlock(&in->lock);
5200
vivek mehta4a824772017-06-08 19:05:49 -07005201 stream_app_type_cfg_init(&in->app_type_cfg);
5202
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005203 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005204 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005205 return 0;
5206
5207err_open:
5208 free(in);
5209 *stream_in = NULL;
5210 return ret;
5211}
5212
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005213static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005214 struct audio_stream_in *stream)
5215{
Andy Hungd13f0d32017-06-12 13:58:37 -07005216 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005217 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005218
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005219 // must deregister from sndmonitor first to prevent races
5220 // between the callback and close_stream
5221 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005222 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07005223
5224 error_log_destroy(in->error_log);
5225 in->error_log = NULL;
5226
Andy Hung0dbb52b2017-08-09 13:51:38 -07005227 pthread_mutex_destroy(&in->pre_lock);
5228 pthread_mutex_destroy(&in->lock);
5229
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005230 free(stream);
5231
5232 return;
5233}
5234
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005235static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005236{
5237 return 0;
5238}
5239
Andy Hung31aca912014-03-20 17:14:59 -07005240/* verifies input and output devices and their capabilities.
5241 *
5242 * This verification is required when enabling extended bit-depth or
5243 * sampling rates, as not all qcom products support it.
5244 *
5245 * Suitable for calling only on initialization such as adev_open().
5246 * It fills the audio_device use_case_table[] array.
5247 *
5248 * Has a side-effect that it needs to configure audio routing / devices
5249 * in order to power up the devices and read the device parameters.
5250 * It does not acquire any hw device lock. Should restore the devices
5251 * back to "normal state" upon completion.
5252 */
5253static int adev_verify_devices(struct audio_device *adev)
5254{
5255 /* enumeration is a bit difficult because one really wants to pull
5256 * the use_case, device id, etc from the hidden pcm_device_table[].
5257 * In this case there are the following use cases and device ids.
5258 *
5259 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
5260 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005261 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07005262 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
5263 * [USECASE_AUDIO_RECORD] = {0, 0},
5264 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
5265 * [USECASE_VOICE_CALL] = {2, 2},
5266 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005267 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07005268 * USECASE_VOICE_CALL omitted, but possible for either input or output.
5269 */
5270
5271 /* should be the usecases enabled in adev_open_input_stream() */
5272 static const int test_in_usecases[] = {
5273 USECASE_AUDIO_RECORD,
5274 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
5275 };
5276 /* should be the usecases enabled in adev_open_output_stream()*/
5277 static const int test_out_usecases[] = {
5278 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
5279 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
5280 };
5281 static const usecase_type_t usecase_type_by_dir[] = {
5282 PCM_PLAYBACK,
5283 PCM_CAPTURE,
5284 };
5285 static const unsigned flags_by_dir[] = {
5286 PCM_OUT,
5287 PCM_IN,
5288 };
5289
5290 size_t i;
5291 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005292 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07005293 char info[512]; /* for possible debug info */
5294
5295 for (dir = 0; dir < 2; ++dir) {
5296 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
5297 const unsigned flags_dir = flags_by_dir[dir];
5298 const size_t testsize =
5299 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
5300 const int *testcases =
5301 dir ? test_in_usecases : test_out_usecases;
5302 const audio_devices_t audio_device =
5303 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
5304
5305 for (i = 0; i < testsize; ++i) {
5306 const audio_usecase_t audio_usecase = testcases[i];
5307 int device_id;
5308 snd_device_t snd_device;
5309 struct pcm_params **pparams;
5310 struct stream_out out;
5311 struct stream_in in;
5312 struct audio_usecase uc_info;
5313 int retval;
5314
5315 pparams = &adev->use_case_table[audio_usecase];
5316 pcm_params_free(*pparams); /* can accept null input */
5317 *pparams = NULL;
5318
5319 /* find the device ID for the use case (signed, for error) */
5320 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
5321 if (device_id < 0)
5322 continue;
5323
5324 /* prepare structures for device probing */
5325 memset(&uc_info, 0, sizeof(uc_info));
5326 uc_info.id = audio_usecase;
5327 uc_info.type = usecase_type;
5328 if (dir) {
5329 adev->active_input = &in;
5330 memset(&in, 0, sizeof(in));
5331 in.device = audio_device;
5332 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
5333 uc_info.stream.in = &in;
5334 } else {
5335 adev->active_input = NULL;
5336 }
5337 memset(&out, 0, sizeof(out));
5338 out.devices = audio_device; /* only field needed in select_devices */
5339 uc_info.stream.out = &out;
5340 uc_info.devices = audio_device;
5341 uc_info.in_snd_device = SND_DEVICE_NONE;
5342 uc_info.out_snd_device = SND_DEVICE_NONE;
5343 list_add_tail(&adev->usecase_list, &uc_info.list);
5344
5345 /* select device - similar to start_(in/out)put_stream() */
5346 retval = select_devices(adev, audio_usecase);
5347 if (retval >= 0) {
5348 *pparams = pcm_params_get(card_id, device_id, flags_dir);
5349#if LOG_NDEBUG == 0
5350 if (*pparams) {
5351 ALOGV("%s: (%s) card %d device %d", __func__,
5352 dir ? "input" : "output", card_id, device_id);
5353 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07005354 } else {
5355 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
5356 }
5357#endif
5358 }
5359
5360 /* deselect device - similar to stop_(in/out)put_stream() */
5361 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07005362 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07005363 /* 2. Disable the rx device */
5364 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07005365 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07005366 list_remove(&uc_info.list);
5367 }
5368 }
5369 adev->active_input = NULL; /* restore adev state */
5370 return 0;
5371}
5372
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005373static int adev_close(hw_device_t *device)
5374{
Andy Hung31aca912014-03-20 17:14:59 -07005375 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005376 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005377
5378 if (!adev)
5379 return 0;
5380
5381 pthread_mutex_lock(&adev_init_lock);
5382
5383 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005384 audio_extn_snd_mon_unregister_listener(adev);
5385 audio_extn_tfa_98xx_deinit();
jasmine cha270b7762018-03-30 15:41:33 +08005386 audio_extn_ma_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005387 audio_route_free(adev->audio_route);
5388 free(adev->snd_dev_ref_cnt);
5389 platform_deinit(adev->platform);
5390 audio_extn_extspk_deinit(adev->extspk);
5391 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005392 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005393 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
5394 pcm_params_free(adev->use_case_table[i]);
5395 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005396 if (adev->adm_deinit)
5397 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005398 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005399 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07005400 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07005401
5402 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005403
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005404 return 0;
5405}
5406
Glenn Kasten4f993392014-05-14 07:30:48 -07005407/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5408 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5409 * just that it _might_ work.
5410 */
5411static int period_size_is_plausible_for_low_latency(int period_size)
5412{
5413 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005414 case 48:
5415 case 96:
5416 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07005417 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005418 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07005419 case 240:
5420 case 320:
5421 case 480:
5422 return 1;
5423 default:
5424 return 0;
5425 }
5426}
5427
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005428static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
5429{
5430 int card;
5431 card_status_t status;
5432
5433 if (!parms)
5434 return;
5435
5436 if (parse_snd_card_status(parms, &card, &status) < 0)
5437 return;
5438
5439 pthread_mutex_lock(&adev->lock);
5440 bool valid_cb = (card == adev->snd_card);
5441 if (valid_cb) {
5442 if (adev->card_status != status) {
5443 adev->card_status = status;
5444 platform_snd_card_update(adev->platform, status);
5445 }
5446 }
5447 pthread_mutex_unlock(&adev->lock);
5448 return;
5449}
5450
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005451/* out and adev lock held */
5452static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
5453{
5454 struct audio_usecase *uc_info;
5455 float left_p;
5456 float right_p;
5457 audio_devices_t devices;
5458
5459 uc_info = get_usecase_from_list(adev, out->usecase);
5460 if (uc_info == NULL) {
5461 ALOGE("%s: Could not find the usecase (%d) in the list",
5462 __func__, out->usecase);
5463 return -EINVAL;
5464 }
5465
5466 ALOGD("%s: enter: usecase(%d: %s)", __func__,
5467 out->usecase, use_case_table[out->usecase]);
5468
5469 if (restore) {
5470 // restore A2DP device for active usecases and unmute if required
5471 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
5472 !is_a2dp_device(uc_info->out_snd_device)) {
5473 ALOGD("%s: restoring A2DP and unmuting stream", __func__);
5474 select_devices(adev, uc_info->id);
5475 pthread_mutex_lock(&out->compr_mute_lock);
5476 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5477 (out->a2dp_compress_mute)) {
5478 out->a2dp_compress_mute = false;
5479 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5480 }
5481 pthread_mutex_unlock(&out->compr_mute_lock);
5482 }
5483 } else {
5484 // mute compress stream if suspended
5485 pthread_mutex_lock(&out->compr_mute_lock);
5486 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5487 (!out->a2dp_compress_mute)) {
5488 if (!out->standby) {
5489 ALOGD("%s: selecting speaker and muting stream", __func__);
5490 devices = out->devices;
5491 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
5492 left_p = out->volume_l;
5493 right_p = out->volume_r;
5494 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5495 compress_pause(out->compr);
5496 set_compr_volume(&out->stream, 0.0f, 0.0f);
5497 out->a2dp_compress_mute = true;
5498 select_devices(adev, out->usecase);
5499 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5500 compress_resume(out->compr);
5501 out->devices = devices;
5502 out->volume_l = left_p;
5503 out->volume_r = right_p;
5504 }
5505 }
5506 pthread_mutex_unlock(&out->compr_mute_lock);
5507 }
5508 ALOGV("%s: exit", __func__);
5509 return 0;
5510}
5511
5512int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
5513{
5514 int ret = 0;
5515
5516 lock_output_stream(out);
5517 pthread_mutex_lock(&adev->lock);
5518
5519 ret = check_a2dp_restore_l(adev, out, restore);
5520
5521 pthread_mutex_unlock(&adev->lock);
5522 pthread_mutex_unlock(&out->lock);
5523 return ret;
5524}
5525
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005526static int adev_open(const hw_module_t *module, const char *name,
5527 hw_device_t **device)
5528{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005529 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005530
Eric Laurent2bafff12016-03-17 12:17:23 -07005531 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005532 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005533 pthread_mutex_lock(&adev_init_lock);
5534 if (audio_device_ref_count != 0) {
5535 *device = &adev->device.common;
5536 audio_device_ref_count++;
5537 ALOGV("%s: returning existing instance of adev", __func__);
5538 ALOGV("%s: exit", __func__);
5539 pthread_mutex_unlock(&adev_init_lock);
5540 return 0;
5541 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005542 adev = calloc(1, sizeof(struct audio_device));
5543
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005544 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5545
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005546 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5547 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5548 adev->device.common.module = (struct hw_module_t *)module;
5549 adev->device.common.close = adev_close;
5550
5551 adev->device.init_check = adev_init_check;
5552 adev->device.set_voice_volume = adev_set_voice_volume;
5553 adev->device.set_master_volume = adev_set_master_volume;
5554 adev->device.get_master_volume = adev_get_master_volume;
5555 adev->device.set_master_mute = adev_set_master_mute;
5556 adev->device.get_master_mute = adev_get_master_mute;
5557 adev->device.set_mode = adev_set_mode;
5558 adev->device.set_mic_mute = adev_set_mic_mute;
5559 adev->device.get_mic_mute = adev_get_mic_mute;
5560 adev->device.set_parameters = adev_set_parameters;
5561 adev->device.get_parameters = adev_get_parameters;
5562 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5563 adev->device.open_output_stream = adev_open_output_stream;
5564 adev->device.close_output_stream = adev_close_output_stream;
5565 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005566
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005567 adev->device.close_input_stream = adev_close_input_stream;
5568 adev->device.dump = adev_dump;
jiabin8962a4d2018-03-19 18:21:24 -07005569 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005570
5571 /* Set the default route before the PCM stream is opened */
5572 pthread_mutex_lock(&adev->lock);
5573 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005574 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005575 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005576 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005577 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005578 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005579 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005580 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005581 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005582 pthread_mutex_unlock(&adev->lock);
5583
5584 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005585 adev->platform = platform_init(adev);
5586 if (!adev->platform) {
5587 free(adev->snd_dev_ref_cnt);
5588 free(adev);
5589 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5590 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005591 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005592 return -EINVAL;
5593 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05005594 adev->extspk = audio_extn_extspk_init(adev);
5595
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005596 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5597 if (adev->visualizer_lib == NULL) {
5598 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5599 } else {
5600 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5601 adev->visualizer_start_output =
5602 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5603 "visualizer_hal_start_output");
5604 adev->visualizer_stop_output =
5605 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5606 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07005607 }
5608
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005609 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5610 if (adev->offload_effects_lib == NULL) {
5611 ALOGW("%s: DLOPEN failed for %s", __func__,
5612 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5613 } else {
5614 ALOGV("%s: DLOPEN successful for %s", __func__,
5615 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5616 adev->offload_effects_start_output =
5617 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5618 "offload_effects_bundle_hal_start_output");
5619 adev->offload_effects_stop_output =
5620 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5621 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07005622 }
5623
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005624 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5625 if (adev->adm_lib == NULL) {
5626 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5627 } else {
5628 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5629 adev->adm_init = (adm_init_t)
5630 dlsym(adev->adm_lib, "adm_init");
5631 adev->adm_deinit = (adm_deinit_t)
5632 dlsym(adev->adm_lib, "adm_deinit");
5633 adev->adm_register_input_stream = (adm_register_input_stream_t)
5634 dlsym(adev->adm_lib, "adm_register_input_stream");
5635 adev->adm_register_output_stream = (adm_register_output_stream_t)
5636 dlsym(adev->adm_lib, "adm_register_output_stream");
5637 adev->adm_deregister_stream = (adm_deregister_stream_t)
5638 dlsym(adev->adm_lib, "adm_deregister_stream");
5639 adev->adm_request_focus = (adm_request_focus_t)
5640 dlsym(adev->adm_lib, "adm_request_focus");
5641 adev->adm_abandon_focus = (adm_abandon_focus_t)
5642 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08005643 adev->adm_set_config = (adm_set_config_t)
5644 dlsym(adev->adm_lib, "adm_set_config");
5645 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5646 dlsym(adev->adm_lib, "adm_request_focus_v2");
5647 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5648 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5649 adev->adm_on_routing_change = (adm_on_routing_change_t)
5650 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005651 }
5652
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005653 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005654 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005655
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005656 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005657
Andy Hung31aca912014-03-20 17:14:59 -07005658 if (k_enable_extended_precision)
5659 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005660
Glenn Kasten4f993392014-05-14 07:30:48 -07005661 char value[PROPERTY_VALUE_MAX];
5662 int trial;
5663 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5664 trial = atoi(value);
5665 if (period_size_is_plausible_for_low_latency(trial)) {
5666 pcm_config_low_latency.period_size = trial;
5667 pcm_config_low_latency.start_threshold = trial / 4;
5668 pcm_config_low_latency.avail_min = trial / 4;
5669 configured_low_latency_capture_period_size = trial;
5670 }
5671 }
5672 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5673 trial = atoi(value);
5674 if (period_size_is_plausible_for_low_latency(trial)) {
5675 configured_low_latency_capture_period_size = trial;
5676 }
5677 }
5678
Vignesh Kulothunganb6f0a9c2018-03-22 13:50:22 -07005679 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
5680
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005681 // commented as full set of app type cfg is sent from platform
5682 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005683 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005684
5685 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5686 af_period_multiplier = atoi(value);
5687 if (af_period_multiplier < 0) {
5688 af_period_multiplier = 2;
5689 } else if (af_period_multiplier > 4) {
5690 af_period_multiplier = 4;
5691 }
5692 ALOGV("new period_multiplier = %d", af_period_multiplier);
5693 }
5694
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005695 audio_extn_tfa_98xx_init(adev);
jasmine cha270b7762018-03-30 15:41:33 +08005696 audio_extn_ma_init(adev->platform);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005697
vivek mehta1a9b7c02015-06-25 11:49:38 -07005698 pthread_mutex_unlock(&adev_init_lock);
5699
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005700 if (adev->adm_init)
5701 adev->adm_data = adev->adm_init();
5702
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005703 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005704 audio_extn_snd_mon_init();
5705 pthread_mutex_lock(&adev->lock);
5706 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
5707 adev->card_status = CARD_STATUS_ONLINE;
5708 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005709 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005710
Eric Laurent2bafff12016-03-17 12:17:23 -07005711 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005712 return 0;
5713}
5714
5715static struct hw_module_methods_t hal_module_methods = {
5716 .open = adev_open,
5717};
5718
5719struct audio_module HAL_MODULE_INFO_SYM = {
5720 .common = {
5721 .tag = HARDWARE_MODULE_TAG,
5722 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5723 .hal_api_version = HARDWARE_HAL_API_VERSION,
5724 .id = AUDIO_HARDWARE_MODULE_ID,
5725 .name = "QCOM Audio HAL",
5726 .author = "Code Aurora Forum",
5727 .methods = &hal_module_methods,
5728 },
5729};