blob: 99e638b161c7841a488e87c6efd81b68f03c41bc [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"
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070061
Eric Laurent397db572016-05-11 11:31:47 -070062/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
63 * COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
Marco Nelissen32093f52015-04-08 15:14:02 -070064#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070065// 2 buffers causes problems with high bitrate files
66#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070067/* ToDo: Check and update a proper value in msec */
68#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
vivek mehta4a824772017-06-08 19:05:49 -070069/* treat as unsigned Q1.13 */
70#define APP_TYPE_GAIN_DEFAULT 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070071#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
vivek mehta4a824772017-06-08 19:05:49 -070072
73/* treat as unsigned Q1.13 */
vivek mehtaa68fea62017-06-08 19:04:02 -070074#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070075
Eric Laurent51f3c662018-04-10 18:21:34 -070076#define RECORD_GAIN_MIN 0.0f
77#define RECORD_GAIN_MAX 1.0f
78#define RECORD_VOLUME_CTL_MAX 0x2000
79
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070080#define PROXY_OPEN_RETRY_COUNT 100
81#define PROXY_OPEN_WAIT_TIME 20
82
vivek mehtadae44712015-07-27 14:13:18 -070083#define MIN_CHANNEL_COUNT 1
84#define DEFAULT_CHANNEL_COUNT 2
85
Jean-Michel Trivic0750692015-10-12 12:12:32 -070086#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
87#define MAX_CHANNEL_COUNT 1
88#else
vivek mehtadae44712015-07-27 14:13:18 -070089#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
90#define XSTR(x) STR(x)
91#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070092#endif
Eric Laurent74b55762017-07-09 17:04:53 -070093#define MAX_HIFI_CHANNEL_COUNT 8
vivek mehtadae44712015-07-27 14:13:18 -070094
Haynes Mathew George03c40102016-01-29 17:57:48 -080095#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
96
Glenn Kasten4f993392014-05-14 07:30:48 -070097static unsigned int configured_low_latency_capture_period_size =
98 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
99
Eric Laurent0e46adf2016-12-16 12:49:24 -0800100
101#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Phil Burkbc991042017-02-24 08:06:44 -0800102#define MMAP_PERIOD_COUNT_MIN 32
103#define MMAP_PERIOD_COUNT_MAX 512
104#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
Eric Laurent0e46adf2016-12-16 12:49:24 -0800105
Andy Hung31aca912014-03-20 17:14:59 -0700106/* This constant enables extended precision handling.
107 * TODO The flag is off until more testing is done.
108 */
109static const bool k_enable_extended_precision = false;
110
Eric Laurentb23d5282013-05-14 15:27:20 -0700111struct pcm_config pcm_config_deep_buffer = {
vivek mehtadae44712015-07-27 14:13:18 -0700112 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700113 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
114 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
115 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
116 .format = PCM_FORMAT_S16_LE,
117 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
118 .stop_threshold = INT_MAX,
119 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
120};
121
122struct pcm_config pcm_config_low_latency = {
vivek mehtadae44712015-07-27 14:13:18 -0700123 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700124 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
125 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
126 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
127 .format = PCM_FORMAT_S16_LE,
128 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
129 .stop_threshold = INT_MAX,
130 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
131};
132
Haynes Mathew George03c40102016-01-29 17:57:48 -0800133static int af_period_multiplier = 4;
134struct pcm_config pcm_config_rt = {
135 .channels = DEFAULT_CHANNEL_COUNT,
136 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
137 .period_size = ULL_PERIOD_SIZE, //1 ms
138 .period_count = 512, //=> buffer size is 512ms
139 .format = PCM_FORMAT_S16_LE,
140 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
141 .stop_threshold = INT_MAX,
142 .silence_threshold = 0,
143 .silence_size = 0,
144 .avail_min = ULL_PERIOD_SIZE, //1 ms
145};
146
Eric Laurentb23d5282013-05-14 15:27:20 -0700147struct pcm_config pcm_config_hdmi_multi = {
148 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
149 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
150 .period_size = HDMI_MULTI_PERIOD_SIZE,
151 .period_count = HDMI_MULTI_PERIOD_COUNT,
152 .format = PCM_FORMAT_S16_LE,
153 .start_threshold = 0,
154 .stop_threshold = INT_MAX,
155 .avail_min = 0,
156};
157
Eric Laurent0e46adf2016-12-16 12:49:24 -0800158struct pcm_config pcm_config_mmap_playback = {
159 .channels = DEFAULT_CHANNEL_COUNT,
160 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
161 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800162 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800163 .format = PCM_FORMAT_S16_LE,
164 .start_threshold = MMAP_PERIOD_SIZE*8,
165 .stop_threshold = INT32_MAX,
166 .silence_threshold = 0,
167 .silence_size = 0,
168 .avail_min = MMAP_PERIOD_SIZE, //1 ms
169};
170
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800171struct pcm_config pcm_config_hifi = {
172 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
173 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
174 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
175 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
176 .format = PCM_FORMAT_S24_3LE,
177 .start_threshold = 0,
178 .stop_threshold = INT_MAX,
179 .avail_min = 0,
180};
181
Eric Laurentb23d5282013-05-14 15:27:20 -0700182struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700183 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700184 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
185 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700186 .stop_threshold = INT_MAX,
187 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700188};
189
Haynes Mathew George03c40102016-01-29 17:57:48 -0800190struct pcm_config pcm_config_audio_capture_rt = {
191 .channels = DEFAULT_CHANNEL_COUNT,
192 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
193 .period_size = ULL_PERIOD_SIZE,
194 .period_count = 512,
195 .format = PCM_FORMAT_S16_LE,
196 .start_threshold = 0,
197 .stop_threshold = INT_MAX,
198 .silence_threshold = 0,
199 .silence_size = 0,
200 .avail_min = ULL_PERIOD_SIZE, //1 ms
201};
202
Eric Laurent0e46adf2016-12-16 12:49:24 -0800203struct pcm_config pcm_config_mmap_capture = {
204 .channels = DEFAULT_CHANNEL_COUNT,
205 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
206 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800207 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800208 .format = PCM_FORMAT_S16_LE,
209 .start_threshold = 0,
210 .stop_threshold = INT_MAX,
211 .silence_threshold = 0,
212 .silence_size = 0,
213 .avail_min = MMAP_PERIOD_SIZE, //1 ms
214};
215
vivek mehtaa68fea62017-06-08 19:04:02 -0700216struct pcm_config pcm_config_voip = {
217 .channels = 1,
218 .period_count = 2,
219 .format = PCM_FORMAT_S16_LE,
220 .stop_threshold = INT_MAX,
221 .avail_min = 0,
222};
223
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700224#define AFE_PROXY_CHANNEL_COUNT 2
225#define AFE_PROXY_SAMPLING_RATE 48000
226
227#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
228#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
229
230struct pcm_config pcm_config_afe_proxy_playback = {
231 .channels = AFE_PROXY_CHANNEL_COUNT,
232 .rate = AFE_PROXY_SAMPLING_RATE,
233 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
234 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
235 .format = PCM_FORMAT_S16_LE,
236 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
237 .stop_threshold = INT_MAX,
238 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
239};
240
241#define AFE_PROXY_RECORD_PERIOD_SIZE 768
242#define AFE_PROXY_RECORD_PERIOD_COUNT 4
243
244struct pcm_config pcm_config_afe_proxy_record = {
245 .channels = AFE_PROXY_CHANNEL_COUNT,
246 .rate = AFE_PROXY_SAMPLING_RATE,
247 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
248 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
249 .format = PCM_FORMAT_S16_LE,
250 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
251 .stop_threshold = INT_MAX,
252 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
253};
254
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700255const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700256 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
257 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800258 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700259 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700260 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700261 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800262 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700263
Eric Laurentb23d5282013-05-14 15:27:20 -0700264 [USECASE_AUDIO_RECORD] = "audio-record",
265 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800266 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George569b7482017-05-08 14:44:27 -0700267 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700268
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800269 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
270 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700271
Eric Laurentb23d5282013-05-14 15:27:20 -0700272 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700273 [USECASE_VOICE2_CALL] = "voice2-call",
274 [USECASE_VOLTE_CALL] = "volte-call",
275 [USECASE_QCHAT_CALL] = "qchat-call",
276 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800277 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
278 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700279
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700280 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
281 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
282
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700283 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
284 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
vivek mehta781065c2017-04-04 12:55:01 -0700285
286 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
287 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
288 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
289
vivek mehtaa68fea62017-06-08 19:04:02 -0700290 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
291 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Nadav Bar3d72cfc2018-01-07 12:19:24 +0200292
293 [USECASE_INCALL_MUSIC_UPLINK] = "incall-music-uplink",
Aniket Kumar Lata99546312018-03-19 21:38:38 -0700294
295 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700296};
297
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800298
299#define STRING_TO_ENUM(string) { #string, string }
300
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800301struct string_to_enum {
302 const char *name;
303 uint32_t value;
304};
305
Haynes Mathew George569b7482017-05-08 14:44:27 -0700306static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800307 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
308 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
309 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Eric Laurent74b55762017-07-09 17:04:53 -0700310 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
Haynes Mathew George569b7482017-05-08 14:44:27 -0700311 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
Eric Laurent74b55762017-07-09 17:04:53 -0700312 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
313 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
314 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
315 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
316 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
317 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
318 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
319 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
320 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800321};
322
Haynes Mathew George5191a852013-09-11 14:19:36 -0700323static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700324static struct audio_device *adev = NULL;
Andy Hung9e737de2017-05-22 10:51:22 -0700325static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700326static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700327//cache last MBDRC cal step level
328static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700329
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800330static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
331static int set_compr_volume(struct audio_stream_out *stream, float left, float right);
332
Haynes Mathew George03c40102016-01-29 17:57:48 -0800333static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
334 int flags __unused)
335{
336 int dir = 0;
337 switch (uc_id) {
338 case USECASE_AUDIO_RECORD_LOW_LATENCY:
339 dir = 1;
340 case USECASE_AUDIO_PLAYBACK_ULL:
341 break;
342 default:
343 return false;
344 }
345
346 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
347 PCM_PLAYBACK : PCM_CAPTURE);
348 if (adev->adm_is_noirq_avail)
349 return adev->adm_is_noirq_avail(adev->adm_data,
350 adev->snd_card, dev_id, dir);
351 return false;
352}
353
354static void register_out_stream(struct stream_out *out)
355{
356 struct audio_device *adev = out->dev;
357 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
358 return;
359
360 if (!adev->adm_register_output_stream)
361 return;
362
363 adev->adm_register_output_stream(adev->adm_data,
364 out->handle,
365 out->flags);
366
367 if (!adev->adm_set_config)
368 return;
369
370 if (out->realtime) {
371 adev->adm_set_config(adev->adm_data,
372 out->handle,
373 out->pcm, &out->config);
374 }
375}
376
377static void register_in_stream(struct stream_in *in)
378{
379 struct audio_device *adev = in->dev;
380 if (!adev->adm_register_input_stream)
381 return;
382
383 adev->adm_register_input_stream(adev->adm_data,
384 in->capture_handle,
385 in->flags);
386
387 if (!adev->adm_set_config)
388 return;
389
390 if (in->realtime) {
391 adev->adm_set_config(adev->adm_data,
392 in->capture_handle,
393 in->pcm,
394 &in->config);
395 }
396}
397
398static void request_out_focus(struct stream_out *out, long ns)
399{
400 struct audio_device *adev = out->dev;
401
Haynes Mathew George03c40102016-01-29 17:57:48 -0800402 if (adev->adm_request_focus_v2) {
403 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
404 } else if (adev->adm_request_focus) {
405 adev->adm_request_focus(adev->adm_data, out->handle);
406 }
407}
408
409static void request_in_focus(struct stream_in *in, long ns)
410{
411 struct audio_device *adev = in->dev;
412
Haynes Mathew George03c40102016-01-29 17:57:48 -0800413 if (adev->adm_request_focus_v2) {
414 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
415 } else if (adev->adm_request_focus) {
416 adev->adm_request_focus(adev->adm_data, in->capture_handle);
417 }
418}
419
420static void release_out_focus(struct stream_out *out, long ns __unused)
421{
422 struct audio_device *adev = out->dev;
423
424 if (adev->adm_abandon_focus)
425 adev->adm_abandon_focus(adev->adm_data, out->handle);
426}
427
428static void release_in_focus(struct stream_in *in, long ns __unused)
429{
430 struct audio_device *adev = in->dev;
431 if (adev->adm_abandon_focus)
432 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
433}
434
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700435static int parse_snd_card_status(struct str_parms * parms, int * card,
436 card_status_t * status)
437{
438 char value[32]={0};
439 char state[32]={0};
440
441 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
442
443 if (ret < 0)
444 return -1;
445
446 // sscanf should be okay as value is of max length 32.
447 // same as sizeof state.
448 if (sscanf(value, "%d,%s", card, state) < 2)
449 return -1;
450
451 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
452 CARD_STATUS_OFFLINE;
453 return 0;
454}
455
vivek mehta40125092017-08-21 18:48:51 -0700456// always call with adev lock held
457void send_gain_dep_calibration_l() {
458 if (last_known_cal_step >= 0)
459 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
460}
461
vivek mehta1a9b7c02015-06-25 11:49:38 -0700462__attribute__ ((visibility ("default")))
463bool audio_hw_send_gain_dep_calibration(int level) {
464 bool ret_val = false;
465 ALOGV("%s: enter ... ", __func__);
466
467 pthread_mutex_lock(&adev_init_lock);
468
469 if (adev != NULL && adev->platform != NULL) {
470 pthread_mutex_lock(&adev->lock);
vivek mehta40125092017-08-21 18:48:51 -0700471 last_known_cal_step = level;
472 send_gain_dep_calibration_l();
vivek mehta1a9b7c02015-06-25 11:49:38 -0700473 pthread_mutex_unlock(&adev->lock);
474 } else {
475 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
476 }
477
478 pthread_mutex_unlock(&adev_init_lock);
479
480 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
481 return ret_val;
482}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700483
vivek mehtaa8d7c922016-05-25 14:40:44 -0700484__attribute__ ((visibility ("default")))
485int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
486 int table_size) {
487 int ret_val = 0;
488 ALOGV("%s: enter ... ", __func__);
489
490 pthread_mutex_lock(&adev_init_lock);
491 if (adev == NULL) {
492 ALOGW("%s: adev is NULL .... ", __func__);
493 goto done;
494 }
495
496 pthread_mutex_lock(&adev->lock);
497 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
498 pthread_mutex_unlock(&adev->lock);
499done:
500 pthread_mutex_unlock(&adev_init_lock);
501 ALOGV("%s: exit ... ", __func__);
502 return ret_val;
503}
504
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700505static bool is_supported_format(audio_format_t format)
506{
Eric Laurent8251ac82014-07-23 11:00:25 -0700507 switch (format) {
508 case AUDIO_FORMAT_MP3:
509 case AUDIO_FORMAT_AAC_LC:
510 case AUDIO_FORMAT_AAC_HE_V1:
511 case AUDIO_FORMAT_AAC_HE_V2:
512 return true;
513 default:
514 break;
515 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700516 return false;
517}
518
Haynes Mathew George03c40102016-01-29 17:57:48 -0800519static inline bool is_mmap_usecase(audio_usecase_t uc_id)
520{
521 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
522 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
523}
524
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700525static int get_snd_codec_id(audio_format_t format)
526{
527 int id = 0;
528
Eric Laurent8251ac82014-07-23 11:00:25 -0700529 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700530 case AUDIO_FORMAT_MP3:
531 id = SND_AUDIOCODEC_MP3;
532 break;
533 case AUDIO_FORMAT_AAC:
534 id = SND_AUDIOCODEC_AAC;
535 break;
536 default:
537 ALOGE("%s: Unsupported audio format", __func__);
538 }
539
540 return id;
541}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800542
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800543static int audio_ssr_status(struct audio_device *adev)
544{
545 int ret = 0;
546 struct mixer_ctl *ctl;
547 const char *mixer_ctl_name = "Audio SSR Status";
548
549 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
550 ret = mixer_ctl_get_value(ctl, 0);
551 ALOGD("%s: value: %d", __func__, ret);
552 return ret;
553}
554
vivek mehta4a824772017-06-08 19:05:49 -0700555static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
556{
557 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
558}
559
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800560static bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
561{
562 return out_snd_device == SND_DEVICE_OUT_BT_SCO ||
563 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
564 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
565 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
566 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
567 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC;
568
569}
570
571static bool is_a2dp_device(snd_device_t out_snd_device)
572{
573 return out_snd_device == SND_DEVICE_OUT_BT_A2DP;
574}
575
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800576int enable_audio_route(struct audio_device *adev,
577 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800578{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700579 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800580 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800581
582 if (usecase == NULL)
583 return -EINVAL;
584
585 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
586
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800587 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700588 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800589 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700590 snd_device = usecase->out_snd_device;
Yamit Mehtae3b99562016-09-16 22:44:00 +0530591 audio_extn_utils_send_app_type_cfg(adev, usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800592 audio_extn_utils_send_audio_calibration(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800593 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500594 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000595 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700596 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700597 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800598
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800599 ALOGV("%s: exit", __func__);
600 return 0;
601}
602
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800603int disable_audio_route(struct audio_device *adev,
604 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800605{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700606 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800607 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800608
609 if (usecase == NULL)
610 return -EINVAL;
611
612 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700613 if (usecase->type == PCM_CAPTURE)
614 snd_device = usecase->in_snd_device;
615 else
616 snd_device = usecase->out_snd_device;
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);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700619 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700620 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000621 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
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 enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700628 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800629{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700630 int i, num_devices = 0;
631 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800632 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800633 if (snd_device < SND_DEVICE_MIN ||
634 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800635 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800636 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800637 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700638
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700639 platform_send_audio_calibration(adev->platform, snd_device);
640
vivek mehtade4849c2016-03-03 17:23:38 -0800641 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700642 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700643 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800644 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700645 }
646
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700647 /* due to the possibility of calibration overwrite between listen
648 and audio, notify sound trigger hal before audio calibration is sent */
649 audio_extn_sound_trigger_update_device_status(snd_device,
650 ST_EVENT_SND_DEVICE_BUSY);
651
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700652 if (audio_extn_spkr_prot_is_enabled())
653 audio_extn_spkr_prot_calib_cancel(adev);
654
zhaoyang yin4211fad2015-06-04 21:13:25 +0800655 audio_extn_dsm_feedback_enable(adev, snd_device, true);
656
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800657 if (is_a2dp_device(snd_device) &&
658 (audio_extn_a2dp_start_playback() < 0)) {
659 ALOGE("%s: failed to configure A2DP control path", __func__);
660 goto on_error;
661 }
662
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700663 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800664 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700665 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
666 audio_extn_spkr_prot_is_enabled()) {
667 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800668 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700669 }
670 if (audio_extn_spkr_prot_start_processing(snd_device)) {
671 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800672 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700673 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700674 } else if (platform_can_split_snd_device(snd_device,
675 &num_devices,
676 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700677 for (i = 0; i < num_devices; i++) {
678 enable_snd_device(adev, new_snd_devices[i]);
679 }
vivek mehtab6506412015-08-07 16:55:17 -0700680 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700681 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800682 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
683 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
684 ALOGE(" %s: Invalid sound device returned", __func__);
685 goto on_error;
686 }
Ed Tam70b5c142016-03-21 19:14:29 -0700687
Eric Laurent2e140aa2016-06-30 17:14:46 -0700688 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800689 audio_route_apply_and_update_path(adev->audio_route, device_name);
690 }
691on_success:
692 adev->snd_dev_ref_cnt[snd_device]++;
693 ret_val = 0;
694on_error:
695 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800696}
697
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800698int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700699 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800700{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700701 int i, num_devices = 0;
702 snd_device_t new_snd_devices[2];
703
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800704 if (snd_device < SND_DEVICE_MIN ||
705 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800706 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800707 return -EINVAL;
708 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700709 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
710 ALOGE("%s: device ref cnt is already 0", __func__);
711 return -EINVAL;
712 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800713 audio_extn_tfa_98xx_disable_speaker(snd_device);
714
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700715 adev->snd_dev_ref_cnt[snd_device]--;
716 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800717 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800718
719 if (is_a2dp_device(snd_device))
720 audio_extn_a2dp_stop_playback();
721
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700722 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800723 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700724 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700725 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
726 audio_extn_spkr_prot_is_enabled()) {
727 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700728
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700729 // FIXME b/65363602: bullhead is the only Nexus with audio_extn_spkr_prot_is_enabled()
730 // and does not use speaker swap. As this code causes a problem with device enable ref
731 // counting we remove it for now.
vivek mehtae59cfb22017-06-16 15:57:11 -0700732 // when speaker device is disabled, reset swap.
733 // will be renabled on usecase start
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700734 // platform_set_swap_channels(adev, false);
vivek mehtae59cfb22017-06-16 15:57:11 -0700735
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700736 } else if (platform_can_split_snd_device(snd_device,
737 &num_devices,
738 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700739 for (i = 0; i < num_devices; i++) {
740 disable_snd_device(adev, new_snd_devices[i]);
741 }
vivek mehtab6506412015-08-07 16:55:17 -0700742 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700743 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800744 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
745 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
746 ALOGE(" %s: Invalid sound device returned", __func__);
747 return -EINVAL;
748 }
749
Eric Laurent2e140aa2016-06-30 17:14:46 -0700750 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800751 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700752 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700753 audio_extn_sound_trigger_update_device_status(snd_device,
754 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700755 }
vivek mehtab6506412015-08-07 16:55:17 -0700756
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800757 return 0;
758}
759
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700760/*
761 legend:
762 uc - existing usecase
763 new_uc - new usecase
764 d1, d11, d2 - SND_DEVICE enums
765 a1, a2 - corresponding ANDROID device enums
766 B, B1, B2 - backend strings
767
768case 1
769 uc->dev d1 (a1) B1
770 new_uc->dev d1 (a1), d2 (a2) B1, B2
771
772 resolution: disable and enable uc->dev on d1
773
774case 2
775 uc->dev d1 (a1) B1
776 new_uc->dev d11 (a1) B1
777
778 resolution: need to switch uc since d1 and d11 are related
779 (e.g. speaker and voice-speaker)
780 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
781
782case 3
783 uc->dev d1 (a1) B1
784 new_uc->dev d2 (a2) B2
785
786 resolution: no need to switch uc
787
788case 4
789 uc->dev d1 (a1) B
790 new_uc->dev d2 (a2) B
791
792 resolution: disable enable uc-dev on d2 since backends match
793 we cannot enable two streams on two different devices if they
794 share the same backend. e.g. if offload is on speaker device using
795 QUAD_MI2S backend and a low-latency stream is started on voice-handset
796 using the same backend, offload must also be switched to voice-handset.
797
798case 5
799 uc->dev d1 (a1) B
800 new_uc->dev d1 (a1), d2 (a2) B
801
802 resolution: disable enable uc-dev on d2 since backends match
803 we cannot enable two streams on two different devices if they
804 share the same backend.
805
806case 6
807 uc->dev d1 a1 B1
808 new_uc->dev d2 a1 B2
809
810 resolution: no need to switch
811
812case 7
813
814 uc->dev d1 (a1), d2 (a2) B1, B2
815 new_uc->dev d1 B1
816
817 resolution: no need to switch
818
819*/
820static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
821 struct audio_usecase *new_uc,
822 snd_device_t new_snd_device)
823{
824 audio_devices_t a1 = uc->stream.out->devices;
825 audio_devices_t a2 = new_uc->stream.out->devices;
826
827 snd_device_t d1 = uc->out_snd_device;
828 snd_device_t d2 = new_snd_device;
829
830 // Treat as a special case when a1 and a2 are not disjoint
831 if ((a1 != a2) && (a1 & a2)) {
832 snd_device_t d3[2];
833 int num_devices = 0;
834 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
835 &num_devices,
836 d3);
837 if (ret < 0) {
838 if (ret != -ENOSYS) {
839 ALOGW("%s failed to split snd_device %d",
840 __func__,
841 popcount(a1) > 1 ? d1 : d2);
842 }
843 goto end;
844 }
845
846 // NB: case 7 is hypothetical and isn't a practical usecase yet.
847 // But if it does happen, we need to give priority to d2 if
848 // the combo devices active on the existing usecase share a backend.
849 // This is because we cannot have a usecase active on a combo device
850 // and a new usecase requests one device in this combo pair.
851 if (platform_check_backends_match(d3[0], d3[1])) {
852 return d2; // case 5
853 } else {
854 return d1; // case 1
855 }
856 } else {
857 if (platform_check_backends_match(d1, d2)) {
858 return d2; // case 2, 4
859 } else {
860 return d1; // case 6, 3
861 }
862 }
863
864end:
865 return d2; // return whatever was calculated before.
866}
867
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700868static void check_and_route_playback_usecases(struct audio_device *adev,
869 struct audio_usecase *uc_info,
870 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700871{
872 struct listnode *node;
873 struct audio_usecase *usecase;
874 bool switch_device[AUDIO_USECASE_MAX];
875 int i, num_uc_to_switch = 0;
876
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700877 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
878 uc_info,
879 snd_device);
David Linee3fe402017-03-13 10:00:42 -0700880
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800881 /* For a2dp device reconfigure all active sessions
882 * with new AFE encoder format based on a2dp state
883 */
884 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
885 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
886 audio_extn_a2dp_is_force_device_switch()) {
887 force_routing = true;
888 }
889
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700890 /*
891 * This function is to make sure that all the usecases that are active on
892 * the hardware codec backend are always routed to any one device that is
893 * handled by the hardware codec.
894 * For example, if low-latency and deep-buffer usecases are currently active
895 * on speaker and out_set_parameters(headset) is received on low-latency
896 * output, then we have to make sure deep-buffer is also switched to headset,
897 * because of the limitation that both the devices cannot be enabled
898 * at the same time as they share the same backend.
899 */
900 /* Disable all the usecases on the shared backend other than the
901 specified usecase */
902 for (i = 0; i < AUDIO_USECASE_MAX; i++)
903 switch_device[i] = false;
904
905 list_for_each(node, &adev->usecase_list) {
906 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700907 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
908 continue;
909
910 if (force_routing ||
911 (usecase->out_snd_device != snd_device &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -0700912 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
913 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700914 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700915 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
916 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700917 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700918 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700919 switch_device[usecase->id] = true;
920 num_uc_to_switch++;
921 }
922 }
923
924 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700925 list_for_each(node, &adev->usecase_list) {
926 usecase = node_to_item(node, struct audio_usecase, list);
927 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700928 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900929 }
930 }
931
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700932 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900933 list_for_each(node, &adev->usecase_list) {
934 usecase = node_to_item(node, struct audio_usecase, list);
935 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700936 d_device = derive_playback_snd_device(usecase, uc_info,
937 snd_device);
938 enable_snd_device(adev, d_device);
939 /* Update the out_snd_device before enabling the audio route */
940 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700941 }
942 }
943
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700944 /* Re-route all the usecases on the shared backend other than the
945 specified usecase to new snd devices */
946 list_for_each(node, &adev->usecase_list) {
947 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700948 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700949 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700950 }
951 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700952 }
953}
954
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700955static void check_and_route_capture_usecases(struct audio_device *adev,
956 struct audio_usecase *uc_info,
957 snd_device_t snd_device)
958{
959 struct listnode *node;
960 struct audio_usecase *usecase;
961 bool switch_device[AUDIO_USECASE_MAX];
962 int i, num_uc_to_switch = 0;
963
vivek mehta4ed66e62016-04-15 23:33:34 -0700964 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
965
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700966 /*
967 * This function is to make sure that all the active capture usecases
968 * are always routed to the same input sound device.
969 * For example, if audio-record and voice-call usecases are currently
970 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
971 * is received for voice call then we have to make sure that audio-record
972 * usecase is also switched to earpiece i.e. voice-dmic-ef,
973 * because of the limitation that two devices cannot be enabled
974 * at the same time if they share the same backend.
975 */
976 for (i = 0; i < AUDIO_USECASE_MAX; i++)
977 switch_device[i] = false;
978
979 list_for_each(node, &adev->usecase_list) {
980 usecase = node_to_item(node, struct audio_usecase, list);
981 if (usecase->type != PCM_PLAYBACK &&
982 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700983 usecase->in_snd_device != snd_device &&
984 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700985 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
986 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700987 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700988 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700989 switch_device[usecase->id] = true;
990 num_uc_to_switch++;
991 }
992 }
993
994 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700995 list_for_each(node, &adev->usecase_list) {
996 usecase = node_to_item(node, struct audio_usecase, list);
997 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700998 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700999 }
1000 }
1001
1002 list_for_each(node, &adev->usecase_list) {
1003 usecase = node_to_item(node, struct audio_usecase, list);
1004 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001005 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001006 }
1007 }
1008
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001009 /* Re-route all the usecases on the shared backend other than the
1010 specified usecase to new snd devices */
1011 list_for_each(node, &adev->usecase_list) {
1012 usecase = node_to_item(node, struct audio_usecase, list);
1013 /* Update the in_snd_device only before enabling the audio route */
1014 if (switch_device[usecase->id] ) {
1015 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001016 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001017 }
1018 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001019 }
1020}
1021
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001022/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001023static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001024{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001025 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001026 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001027
1028 switch (channels) {
1029 /*
1030 * Do not handle stereo output in Multi-channel cases
1031 * Stereo case is handled in normal playback path
1032 */
1033 case 6:
1034 ALOGV("%s: HDMI supports 5.1", __func__);
1035 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1036 break;
1037 case 8:
1038 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
1039 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1040 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
1041 break;
1042 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001043 ALOGE("HDMI does not support multi channel playback");
1044 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001045 break;
1046 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001047 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001048}
1049
Andy Hung18859412017-08-09 11:47:21 -07001050static ssize_t read_usb_sup_sample_rates(bool is_playback,
1051 uint32_t *supported_sample_rates,
1052 uint32_t max_rates)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001053{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001054 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1055 supported_sample_rates,
1056 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001057#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001058 for (ssize_t i=0; i<count; i++) {
1059 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1060 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001061 }
1062#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001063 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001064}
1065
Haynes Mathew George569b7482017-05-08 14:44:27 -07001066static int read_usb_sup_channel_masks(bool is_playback,
1067 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001068 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001069{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001070 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001071 int channel_count;
1072 uint32_t num_masks = 0;
1073 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1074 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001075 }
Eric Laurent74b55762017-07-09 17:04:53 -07001076 if (is_playback) {
Andy Hung6c1afb12017-12-22 11:34:41 -08001077 // start from 2 channels as framework currently doesn't support mono.
1078 // TODO: consider only supporting channel index masks beyond stereo here.
1079 for (channel_count = FCC_2;
1080 channel_count <= channels && num_masks < max_masks;
1081 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001082 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1083 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001084 for (channel_count = FCC_2;
1085 channel_count <= channels && num_masks < max_masks;
1086 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001087 supported_channel_masks[num_masks++] =
1088 audio_channel_mask_for_index_assignment_from_count(channel_count);
1089 }
1090 } else {
1091 // For capture we report all supported channel masks from 1 channel up.
1092 channel_count = MIN_CHANNEL_COUNT;
1093 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1094 // indexed mask
1095 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1096 supported_channel_masks[num_masks++] =
1097 audio_channel_in_mask_from_count(channel_count);
1098 }
1099 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001100#ifdef NDEBUG
1101 for (size_t i = 0; i < num_masks; ++i) {
1102 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1103 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
1104 }
1105#endif
Eric Laurent74b55762017-07-09 17:04:53 -07001106 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001107}
1108
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001109static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001110 audio_format_t *supported_formats,
1111 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001112{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001113 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001114 switch (bitwidth) {
1115 case 24:
1116 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001117 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001118 break;
1119 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001120 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001121 break;
1122 case 16:
1123 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001124 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001125 break;
1126 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001127 ALOGV("%s: %s supported format %d", __func__,
1128 is_playback ? "P" : "C", bitwidth);
1129 return 1;
1130}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001131
Haynes Mathew George569b7482017-05-08 14:44:27 -07001132static int read_usb_sup_params_and_compare(bool is_playback,
1133 audio_format_t *format,
1134 audio_format_t *supported_formats,
1135 uint32_t max_formats,
1136 audio_channel_mask_t *mask,
1137 audio_channel_mask_t *supported_channel_masks,
1138 uint32_t max_masks,
1139 uint32_t *rate,
1140 uint32_t *supported_sample_rates,
1141 uint32_t max_rates) {
1142 int ret = 0;
1143 int num_formats;
1144 int num_masks;
1145 int num_rates;
1146 int i;
1147
1148 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1149 max_formats);
1150 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1151 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001152
Haynes Mathew George569b7482017-05-08 14:44:27 -07001153 num_rates = read_usb_sup_sample_rates(is_playback,
1154 supported_sample_rates, max_rates);
1155
1156#define LUT(table, len, what, dflt) \
1157 for (i=0; i<len && (table[i] != what); i++); \
1158 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1159
1160 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1161 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1162 LUT(supported_sample_rates, num_rates, *rate, 0);
1163
1164#undef LUT
1165 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001166}
1167
Andy Hungd9653bd2017-08-01 19:31:39 -07001168static bool is_usb_ready(struct audio_device *adev, bool is_playback)
1169{
1170 // Check if usb is ready.
1171 // The usb device may have been removed quickly after insertion and hence
1172 // no longer available. This will show up as empty channel masks, or rates.
1173
1174 pthread_mutex_lock(&adev->lock);
1175 uint32_t supported_sample_rate;
1176
1177 // we consider usb ready if we can fetch at least one sample rate.
1178 const bool ready = read_usb_sup_sample_rates(
1179 is_playback, &supported_sample_rate, 1 /* max_rates */) > 0;
1180 pthread_mutex_unlock(&adev->lock);
1181 return ready;
1182}
1183
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001184static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1185{
1186 struct audio_usecase *usecase;
1187 struct listnode *node;
1188
1189 list_for_each(node, &adev->usecase_list) {
1190 usecase = node_to_item(node, struct audio_usecase, list);
1191 if (usecase->type == VOICE_CALL) {
1192 ALOGV("%s: usecase id %d", __func__, usecase->id);
1193 return usecase->id;
1194 }
1195 }
1196 return USECASE_INVALID;
1197}
1198
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001199struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1200 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001201{
1202 struct audio_usecase *usecase;
1203 struct listnode *node;
1204
1205 list_for_each(node, &adev->usecase_list) {
1206 usecase = node_to_item(node, struct audio_usecase, list);
1207 if (usecase->id == uc_id)
1208 return usecase;
1209 }
1210 return NULL;
1211}
1212
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001213static bool force_device_switch(struct audio_usecase *usecase)
1214{
1215 if (usecase->stream.out == NULL) {
1216 ALOGE("%s: stream.out is NULL", __func__);
1217 return false;
1218 }
1219
1220 // Force all A2DP output devices to reconfigure for proper AFE encode format
1221 // Also handle a case where in earlier A2DP start failed as A2DP stream was
1222 // in suspended state, hence try to trigger a retry when we again get a routing request.
1223 if ((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
1224 audio_extn_a2dp_is_force_device_switch()) {
1225 ALOGD("%s: Force A2DP device switch to update new encoder config", __func__);
1226 return true;
1227 }
1228
1229 return false;
1230}
1231
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001232int select_devices(struct audio_device *adev,
1233 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001234{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001235 snd_device_t out_snd_device = SND_DEVICE_NONE;
1236 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001237 struct audio_usecase *usecase = NULL;
1238 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001239 struct audio_usecase *hfp_usecase = NULL;
1240 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001241 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001242 int status = 0;
Eric Laurentf4520b02017-09-20 18:31:58 -07001243 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1244 USECASE_AUDIO_PLAYBACK_VOIP);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001245
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001246 usecase = get_usecase_from_list(adev, uc_id);
1247 if (usecase == NULL) {
1248 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1249 return -EINVAL;
1250 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001251
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001252 if ((usecase->type == VOICE_CALL) ||
1253 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001254 out_snd_device = platform_get_output_snd_device(adev->platform,
1255 usecase->stream.out->devices);
1256 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001257 usecase->devices = usecase->stream.out->devices;
1258 } else {
1259 /*
1260 * If the voice call is active, use the sound devices of voice call usecase
1261 * so that it would not result any device switch. All the usecases will
1262 * be switched to new device when select_devices() is called for voice call
1263 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001264 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001265 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001266 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001267 vc_usecase = get_usecase_from_list(adev,
1268 get_voice_usecase_id_from_list(adev));
1269 if ((vc_usecase != NULL) &&
1270 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1271 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001272 in_snd_device = vc_usecase->in_snd_device;
1273 out_snd_device = vc_usecase->out_snd_device;
1274 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001275 } else if (audio_extn_hfp_is_active(adev)) {
1276 hfp_ucid = audio_extn_hfp_get_usecase();
1277 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1278 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1279 in_snd_device = hfp_usecase->in_snd_device;
1280 out_snd_device = hfp_usecase->out_snd_device;
1281 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001282 }
1283 if (usecase->type == PCM_PLAYBACK) {
1284 usecase->devices = usecase->stream.out->devices;
1285 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001286 if (out_snd_device == SND_DEVICE_NONE) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001287 struct stream_out *voip_out = adev->primary_output;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001288
Eric Laurentb23d5282013-05-14 15:27:20 -07001289 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001290 usecase->stream.out->devices);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001291
1292 if (voip_usecase)
1293 voip_out = voip_usecase->stream.out;
1294
1295 if (usecase->stream.out == voip_out &&
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001296 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001297 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001298 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001299 select_devices(adev, adev->active_input->usecase);
1300 }
1301 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001302 } else if (usecase->type == PCM_CAPTURE) {
1303 usecase->devices = usecase->stream.in->device;
1304 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001305 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001306 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001307 if (adev->active_input &&
1308 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1309 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001310
1311 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1312 USECASE_AUDIO_PLAYBACK_VOIP);
1313
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001314 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001315 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1316 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001317 } else if (voip_usecase) {
1318 out_device = voip_usecase->stream.out->devices;
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001319 } else if (adev->primary_output) {
1320 out_device = adev->primary_output->devices;
1321 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001322 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001323 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001324 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001325 }
1326 }
1327
1328 if (out_snd_device == usecase->out_snd_device &&
1329 in_snd_device == usecase->in_snd_device) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001330 if (!force_device_switch(usecase))
1331 return 0;
1332 }
1333
1334 if (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready()) {
1335 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1336 return 0;
1337 }
1338
1339 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP) &&
1340 (!audio_extn_a2dp_is_ready())) {
1341 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
1342 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001343 }
1344
Eric Laurent2bafff12016-03-17 12:17:23 -07001345 if (out_snd_device != SND_DEVICE_NONE &&
1346 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1347 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1348 __func__,
1349 use_case_table[uc_id],
1350 adev->last_logged_snd_device[uc_id][0],
1351 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1352 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1353 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1354 -1,
1355 out_snd_device,
1356 platform_get_snd_device_name(out_snd_device),
1357 platform_get_snd_device_acdb_id(out_snd_device));
1358 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1359 }
1360 if (in_snd_device != SND_DEVICE_NONE &&
1361 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1362 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1363 __func__,
1364 use_case_table[uc_id],
1365 adev->last_logged_snd_device[uc_id][1],
1366 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1367 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1368 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1369 -1,
1370 in_snd_device,
1371 platform_get_snd_device_name(in_snd_device),
1372 platform_get_snd_device_acdb_id(in_snd_device));
1373 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1374 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001375
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001376 /*
1377 * Limitation: While in call, to do a device switch we need to disable
1378 * and enable both RX and TX devices though one of them is same as current
1379 * device.
1380 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001381 if ((usecase->type == VOICE_CALL) &&
1382 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1383 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001384 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001385 /* Disable sidetone only if voice call already exists */
1386 if (voice_is_call_state_active(adev))
1387 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001388 }
1389
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001390 /* Disable current sound devices */
1391 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001392 disable_audio_route(adev, usecase);
1393 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001394 }
1395
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001396 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001397 disable_audio_route(adev, usecase);
1398 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001399 }
1400
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001401 /* Applicable only on the targets that has external modem.
1402 * New device information should be sent to modem before enabling
1403 * the devices to reduce in-call device switch time.
1404 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001405 if ((usecase->type == VOICE_CALL) &&
1406 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1407 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001408 status = platform_switch_voice_call_enable_device_config(adev->platform,
1409 out_snd_device,
1410 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001411 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001412
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001413 /* Enable new sound devices */
1414 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001415 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001416 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) ||
1417 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001418 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001419 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001420 }
1421
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001422 if (in_snd_device != SND_DEVICE_NONE) {
1423 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001424 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001425 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001426
Eric Laurentb23d5282013-05-14 15:27:20 -07001427 if (usecase->type == VOICE_CALL)
1428 status = platform_switch_voice_call_device_post(adev->platform,
1429 out_snd_device,
1430 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001431
sangwoo170731f2013-06-08 15:36:36 +09001432 usecase->in_snd_device = in_snd_device;
1433 usecase->out_snd_device = out_snd_device;
1434
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001435 audio_extn_tfa_98xx_set_mode();
1436
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001437 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001438
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001439 /* Applicable only on the targets that has external modem.
1440 * Enable device command should be sent to modem only after
1441 * enabling voice call mixer controls
1442 */
vivek mehta765eb642015-08-07 19:46:06 -07001443 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001444 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1445 out_snd_device,
1446 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001447 /* Enable sidetone only if voice call already exists */
1448 if (voice_is_call_state_active(adev))
1449 voice_set_sidetone(adev, out_snd_device, true);
1450 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001451
Eric Laurentf4520b02017-09-20 18:31:58 -07001452 if (usecase == voip_usecase) {
1453 struct stream_out *voip_out = voip_usecase->stream.out;
1454 audio_extn_utils_send_app_type_gain(adev,
1455 voip_out->app_type_cfg.app_type,
1456 &voip_out->app_type_cfg.gain[0]);
1457 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001458 return status;
1459}
1460
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001461static int stop_input_stream(struct stream_in *in)
1462{
1463 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001464 struct audio_usecase *uc_info;
1465 struct audio_device *adev = in->dev;
1466
Eric Laurent994a6932013-07-17 11:51:42 -07001467 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001468 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001469
1470 if (adev->active_input) {
1471 if (adev->active_input->usecase == in->usecase) {
1472 adev->active_input = NULL;
1473 } else {
1474 ALOGW("%s adev->active_input->usecase %s, v/s in->usecase %s",
1475 __func__,
1476 use_case_table[adev->active_input->usecase],
1477 use_case_table[in->usecase]);
1478 }
1479 }
1480
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001481 uc_info = get_usecase_from_list(adev, in->usecase);
1482 if (uc_info == NULL) {
1483 ALOGE("%s: Could not find the usecase (%d) in the list",
1484 __func__, in->usecase);
1485 return -EINVAL;
1486 }
1487
vivek mehta781065c2017-04-04 12:55:01 -07001488 /* Close in-call recording streams */
1489 voice_check_and_stop_incall_rec_usecase(adev, in);
1490
Eric Laurent150dbfe2013-02-27 14:31:02 -08001491 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001492 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001493
1494 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001495 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001496
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001497 list_remove(&uc_info->list);
1498 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001499
Eric Laurent994a6932013-07-17 11:51:42 -07001500 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001501 return ret;
1502}
1503
1504int start_input_stream(struct stream_in *in)
1505{
1506 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001507 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001508 struct audio_usecase *uc_info;
1509 struct audio_device *adev = in->dev;
1510
Eric Laurent994a6932013-07-17 11:51:42 -07001511 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001512
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001513 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1514 return -EIO;
1515
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001516 if (in->card_status == CARD_STATUS_OFFLINE ||
1517 adev->card_status == CARD_STATUS_OFFLINE) {
1518 ALOGW("in->card_status or adev->card_status offline, try again");
1519 ret = -EAGAIN;
1520 goto error_config;
1521 }
1522
vivek mehta781065c2017-04-04 12:55:01 -07001523 /* Check if source matches incall recording usecase criteria */
1524 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1525 if (ret)
1526 goto error_config;
1527 else
1528 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1529
Eric Laurentb23d5282013-05-14 15:27:20 -07001530 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001531 if (in->pcm_device_id < 0) {
1532 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1533 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001534 ret = -EINVAL;
1535 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001536 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001537
1538 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001539 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1540 uc_info->id = in->usecase;
1541 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001542 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001543 uc_info->devices = in->device;
1544 uc_info->in_snd_device = SND_DEVICE_NONE;
1545 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001546
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001547 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001548
Wei Wangf4837d52017-11-21 14:51:20 -08001549 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001550 audio_extn_perf_lock_acquire();
1551
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001552 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001553
Eric Laurent0e46adf2016-12-16 12:49:24 -08001554 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001555 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001556 ALOGE("%s: pcm stream not ready", __func__);
1557 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001558 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001559 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001560 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001561 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1562 goto error_open;
1563 }
1564 } else {
1565 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1566 unsigned int pcm_open_retry_count = 0;
1567
1568 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1569 flags |= PCM_MMAP | PCM_NOIRQ;
1570 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1571 } else if (in->realtime) {
1572 flags |= PCM_MMAP | PCM_NOIRQ;
1573 }
1574
1575 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1576 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1577
1578 while (1) {
1579 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1580 flags, &in->config);
1581 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1582 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1583 if (in->pcm != NULL) {
1584 pcm_close(in->pcm);
1585 in->pcm = NULL;
1586 }
1587 if (pcm_open_retry_count-- == 0) {
1588 ret = -EIO;
1589 goto error_open;
1590 }
1591 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1592 continue;
1593 }
1594 break;
1595 }
1596
1597 ALOGV("%s: pcm_prepare", __func__);
1598 ret = pcm_prepare(in->pcm);
1599 if (ret < 0) {
1600 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001601 pcm_close(in->pcm);
1602 in->pcm = NULL;
1603 goto error_open;
1604 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001605 if (in->realtime) {
1606 ret = pcm_start(in->pcm);
1607 if (ret < 0) {
1608 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1609 pcm_close(in->pcm);
1610 in->pcm = NULL;
1611 goto error_open;
1612 }
1613 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001614 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001615 register_in_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001616 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001617 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001618 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001619
Eric Laurent0e46adf2016-12-16 12:49:24 -08001620 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001621
1622error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001623 stop_input_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001624 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001625 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001626
1627error_config:
1628 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001629 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001630 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001631}
1632
Eric Laurenta1478072015-09-21 17:21:52 -07001633void lock_input_stream(struct stream_in *in)
1634{
1635 pthread_mutex_lock(&in->pre_lock);
1636 pthread_mutex_lock(&in->lock);
1637 pthread_mutex_unlock(&in->pre_lock);
1638}
1639
1640void lock_output_stream(struct stream_out *out)
1641{
1642 pthread_mutex_lock(&out->pre_lock);
1643 pthread_mutex_lock(&out->lock);
1644 pthread_mutex_unlock(&out->pre_lock);
1645}
1646
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001647/* must be called with out->lock locked */
1648static int send_offload_cmd_l(struct stream_out* out, int command)
1649{
1650 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1651
1652 ALOGVV("%s %d", __func__, command);
1653
1654 cmd->cmd = command;
1655 list_add_tail(&out->offload_cmd_list, &cmd->node);
1656 pthread_cond_signal(&out->offload_cond);
1657 return 0;
1658}
1659
1660/* must be called iwth out->lock locked */
1661static void stop_compressed_output_l(struct stream_out *out)
1662{
1663 out->offload_state = OFFLOAD_STATE_IDLE;
1664 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001665 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001666 if (out->compr != NULL) {
1667 compress_stop(out->compr);
1668 while (out->offload_thread_blocked) {
1669 pthread_cond_wait(&out->cond, &out->lock);
1670 }
1671 }
1672}
1673
1674static void *offload_thread_loop(void *context)
1675{
1676 struct stream_out *out = (struct stream_out *) context;
1677 struct listnode *item;
1678
1679 out->offload_state = OFFLOAD_STATE_IDLE;
1680 out->playback_started = 0;
1681
1682 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1683 set_sched_policy(0, SP_FOREGROUND);
1684 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1685
1686 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001687 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001688 for (;;) {
1689 struct offload_cmd *cmd = NULL;
1690 stream_callback_event_t event;
1691 bool send_callback = false;
1692
1693 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1694 __func__, list_empty(&out->offload_cmd_list),
1695 out->offload_state);
1696 if (list_empty(&out->offload_cmd_list)) {
1697 ALOGV("%s SLEEPING", __func__);
1698 pthread_cond_wait(&out->offload_cond, &out->lock);
1699 ALOGV("%s RUNNING", __func__);
1700 continue;
1701 }
1702
1703 item = list_head(&out->offload_cmd_list);
1704 cmd = node_to_item(item, struct offload_cmd, node);
1705 list_remove(item);
1706
1707 ALOGVV("%s STATE %d CMD %d out->compr %p",
1708 __func__, out->offload_state, cmd->cmd, out->compr);
1709
1710 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1711 free(cmd);
1712 break;
1713 }
1714
1715 if (out->compr == NULL) {
1716 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001717 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001718 pthread_cond_signal(&out->cond);
1719 continue;
1720 }
1721 out->offload_thread_blocked = true;
1722 pthread_mutex_unlock(&out->lock);
1723 send_callback = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001724 switch (cmd->cmd) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001725 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1726 compress_wait(out->compr, -1);
1727 send_callback = true;
1728 event = STREAM_CBK_EVENT_WRITE_READY;
1729 break;
1730 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001731 compress_next_track(out->compr);
1732 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001733 send_callback = true;
1734 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001735 /* Resend the metadata for next iteration */
1736 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001737 break;
1738 case OFFLOAD_CMD_DRAIN:
1739 compress_drain(out->compr);
1740 send_callback = true;
1741 event = STREAM_CBK_EVENT_DRAIN_READY;
1742 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001743 case OFFLOAD_CMD_ERROR:
1744 send_callback = true;
1745 event = STREAM_CBK_EVENT_ERROR;
1746 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001747 default:
1748 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1749 break;
1750 }
Eric Laurenta1478072015-09-21 17:21:52 -07001751 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001752 out->offload_thread_blocked = false;
1753 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001754 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001755 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001756 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001757 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001758 free(cmd);
1759 }
1760
1761 pthread_cond_signal(&out->cond);
1762 while (!list_empty(&out->offload_cmd_list)) {
1763 item = list_head(&out->offload_cmd_list);
1764 list_remove(item);
1765 free(node_to_item(item, struct offload_cmd, node));
1766 }
1767 pthread_mutex_unlock(&out->lock);
1768
1769 return NULL;
1770}
1771
1772static int create_offload_callback_thread(struct stream_out *out)
1773{
1774 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1775 list_init(&out->offload_cmd_list);
1776 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1777 offload_thread_loop, out);
1778 return 0;
1779}
1780
1781static int destroy_offload_callback_thread(struct stream_out *out)
1782{
Eric Laurenta1478072015-09-21 17:21:52 -07001783 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001784 stop_compressed_output_l(out);
1785 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1786
1787 pthread_mutex_unlock(&out->lock);
1788 pthread_join(out->offload_thread, (void **) NULL);
1789 pthread_cond_destroy(&out->offload_cond);
1790
1791 return 0;
1792}
1793
Eric Laurent07eeafd2013-10-06 12:52:49 -07001794static bool allow_hdmi_channel_config(struct audio_device *adev)
1795{
1796 struct listnode *node;
1797 struct audio_usecase *usecase;
1798 bool ret = true;
1799
1800 list_for_each(node, &adev->usecase_list) {
1801 usecase = node_to_item(node, struct audio_usecase, list);
1802 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1803 /*
1804 * If voice call is already existing, do not proceed further to avoid
1805 * disabling/enabling both RX and TX devices, CSD calls, etc.
1806 * Once the voice call done, the HDMI channels can be configured to
1807 * max channels of remaining use cases.
1808 */
1809 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001810 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001811 __func__);
1812 ret = false;
1813 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001814 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1815 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001816 "no change in HDMI channels", __func__);
1817 ret = false;
1818 break;
1819 }
1820 }
1821 }
1822 return ret;
1823}
1824
1825static int check_and_set_hdmi_channels(struct audio_device *adev,
1826 unsigned int channels)
1827{
1828 struct listnode *node;
1829 struct audio_usecase *usecase;
1830
1831 /* Check if change in HDMI channel config is allowed */
1832 if (!allow_hdmi_channel_config(adev))
1833 return 0;
1834
1835 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001836 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001837 return 0;
1838 }
1839
1840 platform_set_hdmi_channels(adev->platform, channels);
1841 adev->cur_hdmi_channels = channels;
1842
1843 /*
1844 * Deroute all the playback streams routed to HDMI so that
1845 * the back end is deactivated. Note that backend will not
1846 * be deactivated if any one stream is connected to it.
1847 */
1848 list_for_each(node, &adev->usecase_list) {
1849 usecase = node_to_item(node, struct audio_usecase, list);
1850 if (usecase->type == PCM_PLAYBACK &&
1851 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001852 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001853 }
1854 }
1855
1856 /*
1857 * Enable all the streams disabled above. Now the HDMI backend
1858 * will be activated with new channel configuration
1859 */
1860 list_for_each(node, &adev->usecase_list) {
1861 usecase = node_to_item(node, struct audio_usecase, list);
1862 if (usecase->type == PCM_PLAYBACK &&
1863 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001864 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001865 }
1866 }
1867
1868 return 0;
1869}
1870
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001871static int stop_output_stream(struct stream_out *out)
1872{
1873 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001874 struct audio_usecase *uc_info;
1875 struct audio_device *adev = out->dev;
1876
Eric Laurent994a6932013-07-17 11:51:42 -07001877 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001878 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001879 uc_info = get_usecase_from_list(adev, out->usecase);
1880 if (uc_info == NULL) {
1881 ALOGE("%s: Could not find the usecase (%d) in the list",
1882 __func__, out->usecase);
1883 return -EINVAL;
1884 }
1885
Haynes Mathew George41f86652014-06-17 14:22:15 -07001886 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1887 if (adev->visualizer_stop_output != NULL)
1888 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1889 if (adev->offload_effects_stop_output != NULL)
1890 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08001891 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
1892 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
1893 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07001894 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001895
Eric Laurent150dbfe2013-02-27 14:31:02 -08001896 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001897 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001898
1899 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001900 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001901
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001902 list_remove(&uc_info->list);
1903 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001904
Eric Laurent0499d4f2014-08-25 22:39:29 -05001905 audio_extn_extspk_update(adev->extspk);
1906
Eric Laurent07eeafd2013-10-06 12:52:49 -07001907 /* Must be called after removing the usecase from list */
1908 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1909 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07001910 else if (out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
1911 struct listnode *node;
1912 struct audio_usecase *usecase;
1913 list_for_each(node, &adev->usecase_list) {
1914 usecase = node_to_item(node, struct audio_usecase, list);
1915 if (usecase->devices & AUDIO_DEVICE_OUT_SPEAKER)
1916 select_devices(adev, usecase->id);
1917 }
1918 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001919
Eric Laurent994a6932013-07-17 11:51:42 -07001920 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001921 return ret;
1922}
1923
1924int start_output_stream(struct stream_out *out)
1925{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001926 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001927 struct audio_usecase *uc_info;
1928 struct audio_device *adev = out->dev;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001929 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001930
Eric Laurent994a6932013-07-17 11:51:42 -07001931 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001932 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001933
1934 if (out->card_status == CARD_STATUS_OFFLINE ||
1935 adev->card_status == CARD_STATUS_OFFLINE) {
1936 ALOGW("out->card_status or adev->card_status offline, try again");
1937 ret = -EAGAIN;
1938 goto error_config;
1939 }
1940
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001941 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
1942 if (!audio_extn_a2dp_is_ready()) {
1943 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
1944 a2dp_combo = true;
1945 } else {
1946 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
1947 ALOGE("%s: A2DP profile is not ready, return error", __func__);
1948 ret = -EAGAIN;
1949 goto error_config;
1950 }
1951 }
1952 }
1953 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001954 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001955 if (out->pcm_device_id < 0) {
1956 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1957 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001958 ret = -EINVAL;
1959 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001960 }
1961
1962 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1963 uc_info->id = out->usecase;
1964 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001965 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001966 uc_info->devices = out->devices;
1967 uc_info->in_snd_device = SND_DEVICE_NONE;
1968 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001969
Eric Laurent07eeafd2013-10-06 12:52:49 -07001970 /* This must be called before adding this usecase to the list */
1971 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1972 check_and_set_hdmi_channels(adev, out->config.channels);
1973
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001974 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001975
Wei Wangf4837d52017-11-21 14:51:20 -08001976 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001977 audio_extn_perf_lock_acquire();
1978
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001979 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
1980 (!audio_extn_a2dp_is_ready())) {
1981 if (!a2dp_combo) {
1982 check_a2dp_restore_l(adev, out, false);
1983 } else {
1984 audio_devices_t dev = out->devices;
1985 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
1986 select_devices(adev, out->usecase);
1987 out->devices = dev;
1988 }
1989 } else {
1990 select_devices(adev, out->usecase);
1991 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001992
Eric Laurent0499d4f2014-08-25 22:39:29 -05001993 audio_extn_extspk_update(adev->extspk);
1994
Andy Hung31aca912014-03-20 17:14:59 -07001995 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001996 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001997 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1998 out->pcm = NULL;
1999 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
2000 COMPRESS_IN, &out->compr_config);
2001 if (out->compr && !is_compress_ready(out->compr)) {
2002 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2003 compress_close(out->compr);
2004 out->compr = NULL;
2005 ret = -EIO;
2006 goto error_open;
2007 }
2008 if (out->offload_callback)
2009 compress_nonblock(out->compr, out->non_blocking);
2010
2011 if (adev->visualizer_start_output != NULL)
2012 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2013 if (adev->offload_effects_start_output != NULL)
2014 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
2015 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002016 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002017 ALOGE("%s: pcm stream not ready", __func__);
2018 goto error_open;
2019 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002020 ret = pcm_start(out->pcm);
2021 if (ret < 0) {
2022 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2023 goto error_open;
2024 }
2025 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07002026 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002027 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002028
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002029 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2030 flags |= PCM_MMAP | PCM_NOIRQ;
2031 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002032 } else if (out->realtime) {
2033 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07002034 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002035
2036 while (1) {
2037 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2038 flags, &out->config);
2039 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2040 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2041 if (out->pcm != NULL) {
2042 pcm_close(out->pcm);
2043 out->pcm = NULL;
2044 }
2045 if (pcm_open_retry_count-- == 0) {
2046 ret = -EIO;
2047 goto error_open;
2048 }
2049 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2050 continue;
2051 }
2052 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002053 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002054 ALOGV("%s: pcm_prepare", __func__);
2055 if (pcm_is_ready(out->pcm)) {
2056 ret = pcm_prepare(out->pcm);
2057 if (ret < 0) {
2058 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2059 pcm_close(out->pcm);
2060 out->pcm = NULL;
2061 goto error_open;
2062 }
2063 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002064 if (out->realtime) {
2065 ret = pcm_start(out->pcm);
2066 if (ret < 0) {
2067 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
2068 pcm_close(out->pcm);
2069 out->pcm = NULL;
2070 goto error_open;
2071 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002072 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002073 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002074 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08002075 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002076 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002077 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07002078
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002079 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2080 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2081 audio_low_latency_hint_start();
2082 }
2083
vivek mehtae59cfb22017-06-16 15:57:11 -07002084 // consider a scenario where on pause lower layers are tear down.
2085 // so on resume, swap mixer control need to be sent only when
2086 // backend is active, hence rather than sending from enable device
2087 // sending it from start of streamtream
2088
2089 platform_set_swap_channels(adev, true);
2090
Eric Laurent994a6932013-07-17 11:51:42 -07002091 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002092 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002093error_open:
Wei Wangf4837d52017-11-21 14:51:20 -08002094 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002095 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002096 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002097error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002098 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002099}
2100
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002101static int check_input_parameters(uint32_t sample_rate,
2102 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07002103 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002104{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002105 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2106 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002107 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2108 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002109 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2110 return -EINVAL;
2111 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002112
Eric Laurent74b55762017-07-09 17:04:53 -07002113 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2114 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002115 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002116 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002117 return -EINVAL;
2118 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002119
2120 switch (sample_rate) {
2121 case 8000:
2122 case 11025:
2123 case 12000:
2124 case 16000:
2125 case 22050:
2126 case 24000:
2127 case 32000:
2128 case 44100:
2129 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002130 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002131 break;
2132 default:
vivek mehtadae44712015-07-27 14:13:18 -07002133 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002134 return -EINVAL;
2135 }
2136
2137 return 0;
2138}
2139
vivek mehtaa68fea62017-06-08 19:04:02 -07002140static size_t get_stream_buffer_size(size_t duration_ms,
2141 uint32_t sample_rate,
2142 audio_format_t format,
2143 int channel_count,
2144 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002145{
2146 size_t size = 0;
2147
vivek mehtaa68fea62017-06-08 19:04:02 -07002148 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002149 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002150 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002151
2152 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002153
Glenn Kasten4f993392014-05-14 07:30:48 -07002154 /* make sure the size is multiple of 32 bytes
2155 * At 48 kHz mono 16-bit PCM:
2156 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2157 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2158 */
2159 size += 0x1f;
2160 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002161
2162 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002163}
2164
2165static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2166{
2167 struct stream_out *out = (struct stream_out *)stream;
2168
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002169 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002170}
2171
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002172static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002173{
2174 return -ENOSYS;
2175}
2176
2177static size_t out_get_buffer_size(const struct audio_stream *stream)
2178{
2179 struct stream_out *out = (struct stream_out *)stream;
2180
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002181 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2182 return out->compr_config.fragment_size;
2183 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002184 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002185 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002186}
2187
2188static uint32_t out_get_channels(const struct audio_stream *stream)
2189{
2190 struct stream_out *out = (struct stream_out *)stream;
2191
2192 return out->channel_mask;
2193}
2194
2195static audio_format_t out_get_format(const struct audio_stream *stream)
2196{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002197 struct stream_out *out = (struct stream_out *)stream;
2198
2199 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002200}
2201
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002202static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002203{
2204 return -ENOSYS;
2205}
2206
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002207/* must be called with out->lock locked */
2208static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002209{
2210 struct stream_out *out = (struct stream_out *)stream;
2211 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002212 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002213
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002214 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002215 if (adev->adm_deregister_stream)
2216 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002217 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002218 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002219 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2220 if (out->pcm) {
2221 pcm_close(out->pcm);
2222 out->pcm = NULL;
2223 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002224 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002225 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002226 out->playback_started = false;
2227 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002228 } else {
2229 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002230 out->gapless_mdata.encoder_delay = 0;
2231 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002232 if (out->compr != NULL) {
2233 compress_close(out->compr);
2234 out->compr = NULL;
2235 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002236 }
Phil Burkbc991042017-02-24 08:06:44 -08002237 if (do_stop) {
2238 stop_output_stream(out);
2239 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002240 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002241 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002242 return 0;
2243}
2244
2245static int out_standby(struct audio_stream *stream)
2246{
2247 struct stream_out *out = (struct stream_out *)stream;
2248
2249 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2250 out->usecase, use_case_table[out->usecase]);
2251
2252 lock_output_stream(out);
2253 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002254 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002255 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002256 return 0;
2257}
2258
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002259static int out_on_error(struct audio_stream *stream)
2260{
2261 struct stream_out *out = (struct stream_out *)stream;
2262 struct audio_device *adev = out->dev;
2263 bool do_standby = false;
2264
2265 lock_output_stream(out);
2266 if (!out->standby) {
2267 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2268 stop_compressed_output_l(out);
2269 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2270 } else
2271 do_standby = true;
2272 }
2273 pthread_mutex_unlock(&out->lock);
2274
2275 if (do_standby)
2276 return out_standby(&out->stream.common);
2277
2278 return 0;
2279}
2280
Andy Hung7401c7c2016-09-21 12:41:21 -07002281static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002282{
Andy Hung7401c7c2016-09-21 12:41:21 -07002283 struct stream_out *out = (struct stream_out *)stream;
2284
2285 // We try to get the lock for consistency,
2286 // but it isn't necessary for these variables.
2287 // If we're not in standby, we may be blocked on a write.
2288 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2289 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2290 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2291
2292 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002293 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002294 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002295
2296 // dump error info
2297 (void)error_log_dump(
2298 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002299
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002300 return 0;
2301}
2302
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002303static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2304{
2305 int ret = 0;
2306 char value[32];
2307 struct compr_gapless_mdata tmp_mdata;
2308
2309 if (!out || !parms) {
2310 return -EINVAL;
2311 }
2312
2313 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2314 if (ret >= 0) {
2315 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2316 } else {
2317 return -EINVAL;
2318 }
2319
2320 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2321 if (ret >= 0) {
2322 tmp_mdata.encoder_padding = atoi(value);
2323 } else {
2324 return -EINVAL;
2325 }
2326
2327 out->gapless_mdata = tmp_mdata;
2328 out->send_new_metadata = 1;
2329 ALOGV("%s new encoder delay %u and padding %u", __func__,
2330 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2331
2332 return 0;
2333}
2334
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002335static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2336{
2337 return out == adev->primary_output || out == adev->voice_tx_output;
2338}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002339
Kevin Rocard1e02c882017-08-09 15:26:07 -07002340static int get_alive_usb_card(struct str_parms* parms) {
2341 int card;
2342 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2343 !audio_extn_usb_alive(card)) {
2344 return card;
2345 }
2346 return -ENODEV;
2347}
2348
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002349static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2350{
2351 struct stream_out *out = (struct stream_out *)stream;
2352 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002353 struct audio_usecase *usecase;
2354 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002355 struct str_parms *parms;
2356 char value[32];
2357 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002358 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002359 int status = 0;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002360 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002361
Eric Laurent2e140aa2016-06-30 17:14:46 -07002362 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002363 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002364 parms = str_parms_create_str(kvpairs);
2365 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2366 if (ret >= 0) {
2367 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002368
Eric Laurenta1478072015-09-21 17:21:52 -07002369 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002370
2371 // The usb driver needs to be closed after usb device disconnection
2372 // otherwise audio is no longer played on the new usb devices.
2373 // By forcing the stream in standby, the usb stack refcount drops to 0
2374 // and the driver is closed.
2375 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD && val == AUDIO_DEVICE_NONE &&
2376 audio_is_usb_out_device(out->devices)) {
2377 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2378 out_standby_l(&out->stream.common);
2379 }
2380
Eric Laurent150dbfe2013-02-27 14:31:02 -08002381 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002382
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002383 /*
2384 * When HDMI cable is unplugged the music playback is paused and
2385 * the policy manager sends routing=0. But the audioflinger
2386 * continues to write data until standby time (3sec).
2387 * As the HDMI core is turned off, the write gets blocked.
2388 * Avoid this by routing audio to speaker until standby.
2389 */
2390 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2391 val == AUDIO_DEVICE_NONE) {
2392 val = AUDIO_DEVICE_OUT_SPEAKER;
2393 }
2394
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002395 /*
2396 * When A2DP is disconnected the
2397 * music playback is paused and the policy manager sends routing=0
2398 * But the audioflingercontinues to write data until standby time
2399 * (3sec). As BT is turned off, the write gets blocked.
2400 * Avoid this by routing audio to speaker until standby.
2401 */
2402 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2403 (val == AUDIO_DEVICE_NONE) &&
2404 !audio_extn_a2dp_is_ready()) {
2405 val = AUDIO_DEVICE_OUT_SPEAKER;
2406 }
2407
2408 /* To avoid a2dp to sco overlapping / BT device improper state
2409 * check with BT lib about a2dp streaming support before routing
2410 */
2411 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2412 if (!audio_extn_a2dp_is_ready()) {
2413 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
2414 //combo usecase just by pass a2dp
2415 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2416 bypass_a2dp = true;
2417 } else {
2418 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2419 /* update device to a2dp and don't route as BT returned error
2420 * However it is still possible a2dp routing called because
2421 * of current active device disconnection (like wired headset)
2422 */
2423 out->devices = val;
2424 pthread_mutex_unlock(&out->lock);
2425 pthread_mutex_unlock(&adev->lock);
2426 status = -ENOSYS;
2427 goto routing_fail;
2428 }
2429 }
2430 }
2431
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002432 audio_devices_t new_dev = val;
2433
2434 // Workaround: If routing to an non existing usb device, fail gracefully
2435 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002436 int card;
2437 if (audio_is_usb_out_device(new_dev) &&
2438 (card = get_alive_usb_card(parms)) >= 0) {
2439
2440 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002441 pthread_mutex_unlock(&adev->lock);
2442 pthread_mutex_unlock(&out->lock);
2443 status = -ENOSYS;
2444 goto routing_fail;
2445 }
2446
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002447 /*
2448 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002449 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002450 * the select_devices(). But how do we undo this?
2451 *
2452 * For example, music playback is active on headset (deep-buffer usecase)
2453 * and if we go to ringtones and select a ringtone, low-latency usecase
2454 * will be started on headset+speaker. As we can't enable headset+speaker
2455 * and headset devices at the same time, select_devices() switches the music
2456 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2457 * So when the ringtone playback is completed, how do we undo the same?
2458 *
2459 * We are relying on the out_set_parameters() call on deep-buffer output,
2460 * once the ringtone playback is ended.
2461 * NOTE: We should not check if the current devices are same as new devices.
2462 * Because select_devices() must be called to switch back the music
2463 * playback to headset.
2464 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002465 if (new_dev != AUDIO_DEVICE_NONE) {
2466 bool same_dev = out->devices == new_dev;
2467 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002468
Eric Laurenta7657192014-10-09 21:09:33 -07002469 if (output_drives_call(adev, out)) {
2470 if (!voice_is_in_call(adev)) {
2471 if (adev->mode == AUDIO_MODE_IN_CALL) {
2472 adev->current_call_output = out;
2473 ret = voice_start_call(adev);
2474 }
2475 } else {
2476 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002477 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002478 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002479 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002480
2481 if (!out->standby) {
2482 if (!same_dev) {
2483 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002484 // inform adm before actual routing to prevent glitches.
2485 if (adev->adm_on_routing_change) {
2486 adev->adm_on_routing_change(adev->adm_data,
2487 out->handle);
2488 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002489 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002490 if (!bypass_a2dp) {
2491 select_devices(adev, out->usecase);
2492 } else {
2493 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2494 select_devices(adev, out->usecase);
2495 out->devices = new_dev;
2496 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002497 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002498
2499 // on device switch force swap, lower functions will make sure
2500 // to check if swap is allowed or not.
2501
2502 if (!same_dev)
2503 platform_set_swap_channels(adev, true);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002504
2505 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2506 out->a2dp_compress_mute &&
2507 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
2508 pthread_mutex_lock(&out->compr_mute_lock);
2509 out->a2dp_compress_mute = false;
2510 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
2511 pthread_mutex_unlock(&out->compr_mute_lock);
2512 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002513 }
2514
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002515 }
2516
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002517 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002518 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002519
2520 /*handles device and call state changes*/
2521 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002522 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002523 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002524
2525 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2526 parse_compress_metadata(out, parms);
2527 }
2528
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002529 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002530 ALOGV("%s: exit: code(%d)", __func__, status);
2531 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002532}
2533
Haynes Mathew George569b7482017-05-08 14:44:27 -07002534static bool stream_get_parameter_channels(struct str_parms *query,
2535 struct str_parms *reply,
2536 audio_channel_mask_t *supported_channel_masks) {
2537 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002538 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002539 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002540 size_t i, j;
2541
2542 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2543 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002544 value[0] = '\0';
2545 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002546 while (supported_channel_masks[i] != 0) {
2547 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2548 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002549 if (!first) {
2550 strcat(value, "|");
2551 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002552 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002553 first = false;
2554 break;
2555 }
2556 }
2557 i++;
2558 }
2559 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002560 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002561 return ret >= 0;
2562}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002563
Haynes Mathew George569b7482017-05-08 14:44:27 -07002564static bool stream_get_parameter_formats(struct str_parms *query,
2565 struct str_parms *reply,
2566 audio_format_t *supported_formats) {
2567 int ret = -1;
2568 char value[256];
2569 int i;
2570
2571 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2572 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002573 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002574 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002575 case AUDIO_FORMAT_PCM_16_BIT:
2576 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2577 break;
2578 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2579 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2580 break;
2581 case AUDIO_FORMAT_PCM_32_BIT:
2582 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2583 break;
2584 default:
2585 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002586 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002587 break;
2588 }
2589 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002590 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002591 return ret >= 0;
2592}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002593
Haynes Mathew George569b7482017-05-08 14:44:27 -07002594static bool stream_get_parameter_rates(struct str_parms *query,
2595 struct str_parms *reply,
2596 uint32_t *supported_sample_rates) {
2597
2598 int i;
2599 char value[256];
2600 int ret = -1;
2601 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2602 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002603 value[0] = '\0';
2604 i=0;
2605 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002606 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002607 int avail = sizeof(value) - cursor;
2608 ret = snprintf(value + cursor, avail, "%s%d",
2609 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002610 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002611 if (ret < 0 || ret >= avail) {
2612 // if cursor is at the last element of the array
2613 // overwrite with \0 is duplicate work as
2614 // snprintf already put a \0 in place.
2615 // else
2616 // we had space to write the '|' at value[cursor]
2617 // (which will be overwritten) or no space to fill
2618 // the first element (=> cursor == 0)
2619 value[cursor] = '\0';
2620 break;
2621 }
2622 cursor += ret;
2623 ++i;
2624 }
2625 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2626 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002627 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002628 return ret >= 0;
2629}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002630
Haynes Mathew George569b7482017-05-08 14:44:27 -07002631static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2632{
2633 struct stream_out *out = (struct stream_out *)stream;
2634 struct str_parms *query = str_parms_create_str(keys);
2635 char *str;
2636 struct str_parms *reply = str_parms_create();
2637 bool replied = false;
2638 ALOGV("%s: enter: keys - %s", __func__, keys);
2639
2640 replied |= stream_get_parameter_channels(query, reply,
2641 &out->supported_channel_masks[0]);
2642 replied |= stream_get_parameter_formats(query, reply,
2643 &out->supported_formats[0]);
2644 replied |= stream_get_parameter_rates(query, reply,
2645 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002646 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002647 str = str_parms_to_str(reply);
2648 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002649 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002650 }
2651 str_parms_destroy(query);
2652 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002653 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002654 return str;
2655}
2656
2657static uint32_t out_get_latency(const struct audio_stream_out *stream)
2658{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002659 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002660 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002661 uint32_t latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002662
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002663 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2664 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002665 else if ((out->realtime) ||
2666 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002667 // since the buffer won't be filled up faster than realtime,
2668 // return a smaller number
2669 period_ms = (out->af_period_multiplier * out->config.period_size *
2670 1000) / (out->config.rate);
2671 hw_delay = platform_render_latency(out->usecase)/1000;
2672 return period_ms + hw_delay;
2673 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002674
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002675 latency = (out->config.period_count * out->config.period_size * 1000) /
2676 (out->config.rate);
2677
2678 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
2679 latency += audio_extn_a2dp_get_encoder_latency();
2680
2681 return latency;
2682}
2683
2684static int set_compr_volume(struct audio_stream_out *stream, float left,
2685 float right)
2686{
2687 struct stream_out *out = (struct stream_out *)stream;
2688 int volume[2];
2689 char mixer_ctl_name[128];
2690 struct audio_device *adev = out->dev;
2691 struct mixer_ctl *ctl;
2692 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2693 PCM_PLAYBACK);
2694
2695 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2696 "Compress Playback %d Volume", pcm_device_id);
2697 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2698 if (!ctl) {
2699 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2700 __func__, mixer_ctl_name);
2701 return -EINVAL;
2702 }
2703 ALOGV("%s: ctl for mixer cmd - %s, left %f, right %f",
2704 __func__, mixer_ctl_name, left, right);
2705 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2706 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2707 mixer_ctl_set_array(ctl, volume, sizeof(volume) / sizeof(volume[0]));
2708
2709 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002710}
2711
2712static int out_set_volume(struct audio_stream_out *stream, float left,
2713 float right)
2714{
Eric Laurenta9024de2013-04-04 09:19:12 -07002715 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002716 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002717
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002718 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002719 /* only take left channel into account: the API is for stereo anyway */
2720 out->muted = (left == 0.0f);
2721 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002722 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002723 pthread_mutex_lock(&out->compr_mute_lock);
2724 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
2725 if (!out->a2dp_compress_mute)
2726 ret = set_compr_volume(stream, left, right);
2727 out->volume_l = left;
2728 out->volume_r = right;
2729 pthread_mutex_unlock(&out->compr_mute_lock);
2730 return ret;
vivek mehtaa68fea62017-06-08 19:04:02 -07002731 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002732 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2733 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2734 if (!out->standby) {
2735 // if in standby, cached volume will be sent after stream is opened
2736 audio_extn_utils_send_app_type_gain(out->dev,
2737 out->app_type_cfg.app_type,
2738 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002739 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002740 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002741 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002742
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002743 return -ENOSYS;
2744}
2745
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002746// note: this call is safe only if the stream_cb is
2747// removed first in close_output_stream (as is done now).
2748static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2749{
2750 if (!stream || !parms)
2751 return;
2752
2753 struct stream_out *out = (struct stream_out *)stream;
2754 struct audio_device *adev = out->dev;
2755
2756 card_status_t status;
2757 int card;
2758 if (parse_snd_card_status(parms, &card, &status) < 0)
2759 return;
2760
2761 pthread_mutex_lock(&adev->lock);
2762 bool valid_cb = (card == adev->snd_card);
2763 pthread_mutex_unlock(&adev->lock);
2764
2765 if (!valid_cb)
2766 return;
2767
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002768 lock_output_stream(out);
2769 if (out->card_status != status)
2770 out->card_status = status;
2771 pthread_mutex_unlock(&out->lock);
2772
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002773 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2774 use_case_table[out->usecase],
2775 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2776
2777 if (status == CARD_STATUS_OFFLINE)
2778 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002779
2780 return;
2781}
2782
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002783#ifdef NO_AUDIO_OUT
2784static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002785 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002786{
2787 struct stream_out *out = (struct stream_out *)stream;
2788
2789 /* No Output device supported other than BT for playback.
2790 * Sleep for the amount of buffer duration
2791 */
Eric Laurenta1478072015-09-21 17:21:52 -07002792 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002793 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2794 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002795 out_get_sample_rate(&out->stream.common));
2796 pthread_mutex_unlock(&out->lock);
2797 return bytes;
2798}
2799#endif
2800
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002801static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2802 size_t bytes)
2803{
2804 struct stream_out *out = (struct stream_out *)stream;
2805 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002806 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002807 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002808
Eric Laurenta1478072015-09-21 17:21:52 -07002809 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002810 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07002811 const size_t frame_size = audio_stream_out_frame_size(stream);
2812 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002813
Eric Laurent0e46adf2016-12-16 12:49:24 -08002814 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2815 error_code = ERROR_CODE_WRITE;
2816 goto exit;
2817 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002818
2819 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2820 (audio_extn_a2dp_is_suspended())) {
2821 if (!(out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2822 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2823 ret = -EIO;
2824 goto exit;
2825 }
2826 }
2827 }
2828
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002829 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002830 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002831 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002832 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07002833
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002834 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002835 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002836 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07002837 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002838 goto exit;
2839 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002840
vivek mehta40125092017-08-21 18:48:51 -07002841 // after standby always force set last known cal step
2842 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
2843 ALOGD("%s: retry previous failed cal level set", __func__);
2844 send_gain_dep_calibration_l();
2845 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002846 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002847
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002848 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002849 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002850 if (out->send_new_metadata) {
2851 ALOGVV("send new gapless metadata");
2852 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2853 out->send_new_metadata = 0;
2854 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002855 unsigned int avail;
2856 struct timespec tstamp;
2857 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2858 /* Do not limit write size if the available frames count is unknown */
2859 if (ret != 0) {
2860 avail = bytes;
2861 }
2862 if (avail == 0) {
2863 ret = 0;
2864 } else {
2865 if (avail > bytes) {
2866 avail = bytes;
2867 }
2868 ret = compress_write(out->compr, buffer, avail);
2869 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2870 __func__, avail, ret);
2871 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002872
Eric Laurent6e895242013-09-05 16:10:57 -07002873 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002874 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2875 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002876 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002877 compress_start(out->compr);
2878 out->playback_started = 1;
2879 out->offload_state = OFFLOAD_STATE_PLAYING;
2880 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002881 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002882 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002883 } else {
2884 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002885 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002886 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002887 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002888 return ret;
2889 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002890 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002891 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07002892 size_t bytes_to_write = bytes;
2893
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002894 if (out->muted)
2895 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07002896 // FIXME: this can be removed once audio flinger mixer supports mono output
Nadav Bar3d72cfc2018-01-07 12:19:24 +02002897 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP || out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
Eric Laurentad2dde92017-09-20 18:27:31 -07002898 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
2899 int16_t *src = (int16_t *)buffer;
2900 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002901
Eric Laurentad2dde92017-09-20 18:27:31 -07002902 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
2903 out->format != AUDIO_FORMAT_PCM_16_BIT,
2904 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002905
Eric Laurentad2dde92017-09-20 18:27:31 -07002906 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
2907 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
2908 }
2909 bytes_to_write /= 2;
2910 }
2911 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes_to_write);
2912
Glenn Kasten5a59dff2018-02-22 08:05:35 -08002913 long ns = (frames * (int64_t) NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002914 request_out_focus(out, ns);
2915
2916 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2917 if (use_mmap)
Eric Laurentad2dde92017-09-20 18:27:31 -07002918 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002919 else
Eric Laurentad2dde92017-09-20 18:27:31 -07002920 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002921
Haynes Mathew George03c40102016-01-29 17:57:48 -08002922 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002923 } else {
2924 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002925 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002926 }
2927
2928exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002929 // For PCM we always consume the buffer and return #bytes regardless of ret.
2930 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07002931 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07002932 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002933 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07002934
Andy Hung7401c7c2016-09-21 12:41:21 -07002935 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07002936 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07002937 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2938 ALOGE_IF(out->pcm != NULL,
2939 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07002940 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002941 // usleep not guaranteed for values over 1 second but we don't limit here.
2942 }
2943 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002944
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002945 pthread_mutex_unlock(&out->lock);
2946
2947 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002948 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002949 if (sleeptime_us != 0)
2950 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002951 }
2952 return bytes;
2953}
2954
2955static int out_get_render_position(const struct audio_stream_out *stream,
2956 uint32_t *dsp_frames)
2957{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002958 struct stream_out *out = (struct stream_out *)stream;
2959 *dsp_frames = 0;
2960 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002961 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002962 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002963 unsigned long frames = 0;
2964 // TODO: check return value
2965 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2966 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002967 ALOGVV("%s rendered frames %d sample_rate %d",
2968 __func__, *dsp_frames, out->sample_rate);
2969 }
2970 pthread_mutex_unlock(&out->lock);
2971 return 0;
2972 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002973 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002974}
2975
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002976static int out_add_audio_effect(const struct audio_stream *stream __unused,
2977 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002978{
2979 return 0;
2980}
2981
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002982static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2983 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002984{
2985 return 0;
2986}
2987
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002988static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2989 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002990{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002991 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002992}
2993
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002994static int out_get_presentation_position(const struct audio_stream_out *stream,
2995 uint64_t *frames, struct timespec *timestamp)
2996{
2997 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002998 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07002999 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003000
Eric Laurenta1478072015-09-21 17:21:52 -07003001 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003002
Eric Laurent949a0892013-09-20 09:20:13 -07003003 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3004 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003005 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07003006 compress_get_tstamp(out->compr, &dsp_frames,
3007 &out->sample_rate);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003008 // Adjustment accounts for A2DP encoder latency with offload usecases
3009 // Note: Encoder latency is returned in ms.
3010 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3011 unsigned long offset =
3012 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3013 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
3014 }
Eric Laurent949a0892013-09-20 09:20:13 -07003015 ALOGVV("%s rendered frames %ld sample_rate %d",
3016 __func__, dsp_frames, out->sample_rate);
3017 *frames = dsp_frames;
3018 ret = 0;
3019 /* this is the best we can do */
3020 clock_gettime(CLOCK_MONOTONIC, timestamp);
3021 }
3022 } else {
3023 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07003024 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003025 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3026 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003027 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003028 // This adjustment accounts for buffering after app processor.
3029 // It is based on estimated DSP latency per use case, rather than exact.
3030 signed_frames -=
3031 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3032
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003033 // Adjustment accounts for A2DP encoder latency with non-offload usecases
3034 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3035 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3036 signed_frames -=
3037 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3038 }
3039
Eric Laurent949a0892013-09-20 09:20:13 -07003040 // It would be unusual for this value to be negative, but check just in case ...
3041 if (signed_frames >= 0) {
3042 *frames = signed_frames;
3043 ret = 0;
3044 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003045 }
3046 }
3047 }
3048
3049 pthread_mutex_unlock(&out->lock);
3050
3051 return ret;
3052}
3053
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003054static int out_set_callback(struct audio_stream_out *stream,
3055 stream_callback_t callback, void *cookie)
3056{
3057 struct stream_out *out = (struct stream_out *)stream;
3058
3059 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003060 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003061 out->offload_callback = callback;
3062 out->offload_cookie = cookie;
3063 pthread_mutex_unlock(&out->lock);
3064 return 0;
3065}
3066
3067static int out_pause(struct audio_stream_out* stream)
3068{
3069 struct stream_out *out = (struct stream_out *)stream;
3070 int status = -ENOSYS;
3071 ALOGV("%s", __func__);
3072 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003073 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003074 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
3075 status = compress_pause(out->compr);
3076 out->offload_state = OFFLOAD_STATE_PAUSED;
3077 }
3078 pthread_mutex_unlock(&out->lock);
3079 }
3080 return status;
3081}
3082
3083static int out_resume(struct audio_stream_out* stream)
3084{
3085 struct stream_out *out = (struct stream_out *)stream;
3086 int status = -ENOSYS;
3087 ALOGV("%s", __func__);
3088 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3089 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07003090 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003091 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
3092 status = compress_resume(out->compr);
3093 out->offload_state = OFFLOAD_STATE_PLAYING;
3094 }
3095 pthread_mutex_unlock(&out->lock);
3096 }
3097 return status;
3098}
3099
3100static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3101{
3102 struct stream_out *out = (struct stream_out *)stream;
3103 int status = -ENOSYS;
3104 ALOGV("%s", __func__);
3105 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003106 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003107 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3108 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3109 else
3110 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3111 pthread_mutex_unlock(&out->lock);
3112 }
3113 return status;
3114}
3115
3116static int out_flush(struct audio_stream_out* stream)
3117{
3118 struct stream_out *out = (struct stream_out *)stream;
3119 ALOGV("%s", __func__);
3120 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003121 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003122 stop_compressed_output_l(out);
3123 pthread_mutex_unlock(&out->lock);
3124 return 0;
3125 }
3126 return -ENOSYS;
3127}
3128
Eric Laurent0e46adf2016-12-16 12:49:24 -08003129static int out_stop(const struct audio_stream_out* stream)
3130{
3131 struct stream_out *out = (struct stream_out *)stream;
3132 struct audio_device *adev = out->dev;
3133 int ret = -ENOSYS;
3134
3135 ALOGV("%s", __func__);
3136 pthread_mutex_lock(&adev->lock);
3137 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3138 out->playback_started && out->pcm != NULL) {
3139 pcm_stop(out->pcm);
3140 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08003141 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003142 }
3143 pthread_mutex_unlock(&adev->lock);
3144 return ret;
3145}
3146
3147static int out_start(const struct audio_stream_out* stream)
3148{
3149 struct stream_out *out = (struct stream_out *)stream;
3150 struct audio_device *adev = out->dev;
3151 int ret = -ENOSYS;
3152
3153 ALOGV("%s", __func__);
3154 pthread_mutex_lock(&adev->lock);
3155 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3156 !out->playback_started && out->pcm != NULL) {
3157 ret = start_output_stream(out);
3158 if (ret == 0) {
3159 out->playback_started = true;
3160 }
3161 }
3162 pthread_mutex_unlock(&adev->lock);
3163 return ret;
3164}
3165
Phil Burkbc991042017-02-24 08:06:44 -08003166/*
3167 * Modify config->period_count based on min_size_frames
3168 */
3169static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
3170{
3171 int periodCountRequested = (min_size_frames + config->period_size - 1)
3172 / config->period_size;
3173 int periodCount = MMAP_PERIOD_COUNT_MIN;
3174
3175 ALOGV("%s original config.period_size = %d config.period_count = %d",
3176 __func__, config->period_size, config->period_count);
3177
3178 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
3179 periodCount *= 2;
3180 }
3181 config->period_count = periodCount;
3182
3183 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
3184}
3185
Eric Laurent0e46adf2016-12-16 12:49:24 -08003186static int out_create_mmap_buffer(const struct audio_stream_out *stream,
3187 int32_t min_size_frames,
3188 struct audio_mmap_buffer_info *info)
3189{
3190 struct stream_out *out = (struct stream_out *)stream;
3191 struct audio_device *adev = out->dev;
3192 int ret = 0;
3193 unsigned int offset1;
3194 unsigned int frames1;
3195 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003196 uint32_t mmap_size;
3197 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003198
3199 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003200 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003201 pthread_mutex_lock(&adev->lock);
3202
3203 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003204 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003205 ret = -EINVAL;
3206 goto exit;
3207 }
3208 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003209 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003210 ret = -ENOSYS;
3211 goto exit;
3212 }
3213 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3214 if (out->pcm_device_id < 0) {
3215 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3216 __func__, out->pcm_device_id, out->usecase);
3217 ret = -EINVAL;
3218 goto exit;
3219 }
Phil Burkbc991042017-02-24 08:06:44 -08003220
3221 adjust_mmap_period_count(&out->config, min_size_frames);
3222
Eric Laurent0e46adf2016-12-16 12:49:24 -08003223 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3224 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3225 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3226 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3227 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3228 step = "open";
3229 ret = -ENODEV;
3230 goto exit;
3231 }
3232 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3233 if (ret < 0) {
3234 step = "begin";
3235 goto exit;
3236 }
3237 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003238 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003239 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003240 ret = platform_get_mmap_data_fd(adev->platform,
3241 out->pcm_device_id, 0 /*playback*/,
3242 &info->shared_memory_fd,
3243 &mmap_size);
3244 if (ret < 0) {
3245 // Fall back to non exclusive mode
3246 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3247 } else {
3248 if (mmap_size < buffer_size) {
3249 step = "mmap";
3250 goto exit;
3251 }
3252 // FIXME: indicate exclusive mode support by returning a negative buffer size
3253 info->buffer_size_frames *= -1;
3254 }
3255 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003256
3257 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3258 if (ret < 0) {
3259 step = "commit";
3260 goto exit;
3261 }
Phil Burkbc991042017-02-24 08:06:44 -08003262
3263 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003264 ret = 0;
3265
3266 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3267 __func__, info->shared_memory_address, info->buffer_size_frames);
3268
3269exit:
3270 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003271 if (out->pcm == NULL) {
3272 ALOGE("%s: %s - %d", __func__, step, ret);
3273 } else {
3274 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003275 pcm_close(out->pcm);
3276 out->pcm = NULL;
3277 }
3278 }
3279 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003280 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003281 return ret;
3282}
3283
3284static int out_get_mmap_position(const struct audio_stream_out *stream,
3285 struct audio_mmap_position *position)
3286{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003287 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003288 struct stream_out *out = (struct stream_out *)stream;
3289 ALOGVV("%s", __func__);
3290 if (position == NULL) {
3291 return -EINVAL;
3292 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003293 lock_output_stream(out);
3294 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3295 out->pcm == NULL) {
3296 ret = -ENOSYS;
3297 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003298 }
3299
3300 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003301 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003302 if (ret < 0) {
3303 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003304 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003305 }
Andy Hungfc044e12017-03-20 09:24:22 -07003306 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003307exit:
3308 pthread_mutex_unlock(&out->lock);
3309 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003310}
3311
3312
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003313/** audio_stream_in implementation **/
3314static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3315{
3316 struct stream_in *in = (struct stream_in *)stream;
3317
3318 return in->config.rate;
3319}
3320
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003321static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003322{
3323 return -ENOSYS;
3324}
3325
3326static size_t in_get_buffer_size(const struct audio_stream *stream)
3327{
3328 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003329 return in->config.period_size * in->af_period_multiplier *
3330 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003331}
3332
3333static uint32_t in_get_channels(const struct audio_stream *stream)
3334{
3335 struct stream_in *in = (struct stream_in *)stream;
3336
3337 return in->channel_mask;
3338}
3339
vivek mehta4ed66e62016-04-15 23:33:34 -07003340static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003341{
vivek mehta4ed66e62016-04-15 23:33:34 -07003342 struct stream_in *in = (struct stream_in *)stream;
3343 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003344}
3345
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003346static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003347{
3348 return -ENOSYS;
3349}
3350
3351static int in_standby(struct audio_stream *stream)
3352{
3353 struct stream_in *in = (struct stream_in *)stream;
3354 struct audio_device *adev = in->dev;
3355 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003356 bool do_stop = true;
3357
Eric Laurent994a6932013-07-17 11:51:42 -07003358 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003359
3360 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003361
3362 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003363 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003364 audio_extn_sound_trigger_stop_lab(in);
3365 in->standby = true;
3366 }
3367
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003368 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003369 if (adev->adm_deregister_stream)
3370 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3371
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003372 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003373 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003374 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003375 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003376 in->capture_started = false;
3377 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003378 if (in->pcm) {
3379 pcm_close(in->pcm);
3380 in->pcm = NULL;
3381 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003382 adev->enable_voicerx = false;
3383 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003384 if (do_stop) {
3385 status = stop_input_stream(in);
3386 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003387 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003388 }
3389 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003390 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003391 return status;
3392}
3393
Andy Hungd13f0d32017-06-12 13:58:37 -07003394static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003395{
Andy Hungd13f0d32017-06-12 13:58:37 -07003396 struct stream_in *in = (struct stream_in *)stream;
3397
3398 // We try to get the lock for consistency,
3399 // but it isn't necessary for these variables.
3400 // If we're not in standby, we may be blocked on a read.
3401 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3402 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3403 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3404 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3405
3406 if (locked) {
3407 pthread_mutex_unlock(&in->lock);
3408 }
3409
3410 // dump error info
3411 (void)error_log_dump(
3412 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003413 return 0;
3414}
3415
3416static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3417{
3418 struct stream_in *in = (struct stream_in *)stream;
3419 struct audio_device *adev = in->dev;
3420 struct str_parms *parms;
3421 char *str;
3422 char value[32];
3423 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003424 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003425
Eric Laurent994a6932013-07-17 11:51:42 -07003426 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003427 parms = str_parms_create_str(kvpairs);
3428
3429 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3430
Eric Laurenta1478072015-09-21 17:21:52 -07003431 lock_input_stream(in);
3432
Eric Laurent150dbfe2013-02-27 14:31:02 -08003433 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003434 if (ret >= 0) {
3435 val = atoi(value);
3436 /* no audio source uses val == 0 */
3437 if ((in->source != val) && (val != 0)) {
3438 in->source = val;
3439 }
3440 }
3441
3442 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003443
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003444 if (ret >= 0) {
3445 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003446 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003447
3448 // Workaround: If routing to an non existing usb device, fail gracefully
3449 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003450 int card;
3451 if (audio_is_usb_in_device(val) &&
3452 (card = get_alive_usb_card(parms)) >= 0) {
3453
3454 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003455 status = -ENOSYS;
3456 } else {
3457
3458 in->device = val;
3459 /* If recording is in progress, change the tx device to new device */
3460 if (!in->standby) {
3461 ALOGV("update input routing change");
3462 // inform adm before actual routing to prevent glitches.
3463 if (adev->adm_on_routing_change) {
3464 adev->adm_on_routing_change(adev->adm_data,
3465 in->capture_handle);
3466 }
3467 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003468 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003469 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003470 }
3471 }
3472
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003473 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003474 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003475
3476 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003477 ALOGV("%s: exit: status(%d)", __func__, status);
3478 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003479}
3480
Haynes Mathew George569b7482017-05-08 14:44:27 -07003481static char* in_get_parameters(const struct audio_stream *stream,
3482 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003483{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003484 struct stream_in *in = (struct stream_in *)stream;
3485 struct str_parms *query = str_parms_create_str(keys);
3486 char *str;
3487 struct str_parms *reply = str_parms_create();
3488 bool replied = false;
3489
3490 ALOGV("%s: enter: keys - %s", __func__, keys);
3491 replied |= stream_get_parameter_channels(query, reply,
3492 &in->supported_channel_masks[0]);
3493 replied |= stream_get_parameter_formats(query, reply,
3494 &in->supported_formats[0]);
3495 replied |= stream_get_parameter_rates(query, reply,
3496 &in->supported_sample_rates[0]);
3497 if (replied) {
3498 str = str_parms_to_str(reply);
3499 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003500 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003501 }
3502 str_parms_destroy(query);
3503 str_parms_destroy(reply);
3504 ALOGV("%s: exit: returns - %s", __func__, str);
3505 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003506}
3507
Eric Laurent51f3c662018-04-10 18:21:34 -07003508static int in_set_gain(struct audio_stream_in *stream, float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003509{
Eric Laurent51f3c662018-04-10 18:21:34 -07003510 struct stream_in *in = (struct stream_in *)stream;
3511 char mixer_ctl_name[128];
3512 struct mixer_ctl *ctl;
3513 int ctl_value;
3514
3515 ALOGV("%s: gain %f", __func__, gain);
3516
3517 if (stream == NULL)
3518 return -EINVAL;
3519
3520 /* in_set_gain() only used to silence MMAP capture for now */
3521 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
3522 return -ENOSYS;
3523
3524 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
3525
3526 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
3527 if (!ctl) {
3528 ALOGW("%s: Could not get ctl for mixer cmd - %s",
3529 __func__, mixer_ctl_name);
3530 return -ENOSYS;
3531 }
3532
3533 if (gain < RECORD_GAIN_MIN)
3534 gain = RECORD_GAIN_MIN;
3535 else if (gain > RECORD_GAIN_MAX)
3536 gain = RECORD_GAIN_MAX;
3537 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
3538
3539 mixer_ctl_set_value(ctl, 0, ctl_value);
3540 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003541}
3542
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003543static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3544{
3545 if (!stream || !parms)
3546 return;
3547
3548 struct stream_in *in = (struct stream_in *)stream;
3549 struct audio_device *adev = in->dev;
3550
3551 card_status_t status;
3552 int card;
3553 if (parse_snd_card_status(parms, &card, &status) < 0)
3554 return;
3555
3556 pthread_mutex_lock(&adev->lock);
3557 bool valid_cb = (card == adev->snd_card);
3558 pthread_mutex_unlock(&adev->lock);
3559
3560 if (!valid_cb)
3561 return;
3562
3563 lock_input_stream(in);
3564 if (in->card_status != status)
3565 in->card_status = status;
3566 pthread_mutex_unlock(&in->lock);
3567
3568 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3569 use_case_table[in->usecase],
3570 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3571
3572 // a better solution would be to report error back to AF and let
3573 // it put the stream to standby
3574 if (status == CARD_STATUS_OFFLINE)
3575 in_standby(&in->stream.common);
3576
3577 return;
3578}
3579
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003580static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3581 size_t bytes)
3582{
3583 struct stream_in *in = (struct stream_in *)stream;
3584 struct audio_device *adev = in->dev;
3585 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003586 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003587 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003588
Eric Laurenta1478072015-09-21 17:21:52 -07003589 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003590 const size_t frame_size = audio_stream_in_frame_size(stream);
3591 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003592
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003593 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003594 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003595 /* Read from sound trigger HAL */
3596 audio_extn_sound_trigger_read(in, buffer, bytes);
3597 pthread_mutex_unlock(&in->lock);
3598 return bytes;
3599 }
3600
Eric Laurent0e46adf2016-12-16 12:49:24 -08003601 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3602 ret = -ENOSYS;
3603 goto exit;
3604 }
3605
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003606 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003607 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003608 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003609 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003610 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003611 goto exit;
3612 }
3613 in->standby = 0;
3614 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003615
Andy Hungd13f0d32017-06-12 13:58:37 -07003616 // errors that occur here are read errors.
3617 error_code = ERROR_CODE_READ;
3618
Haynes Mathew George03c40102016-01-29 17:57:48 -08003619 //what's the duration requested by the client?
3620 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3621 in->config.rate;
3622 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003623
Haynes Mathew George03c40102016-01-29 17:57:48 -08003624 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003625 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003626 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003627 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003628 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003629 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003630 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003631 if (ret < 0) {
3632 ALOGE("Failed to read w/err %s", strerror(errno));
3633 ret = -errno;
3634 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003635 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3636 if (bytes % 4 == 0) {
3637 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3638 int_buf_stream = buffer;
3639 for (size_t itt=0; itt < bytes/4 ; itt++) {
3640 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003641 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003642 } else {
3643 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3644 ret = -EINVAL;
3645 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003646 }
3647 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003648 }
3649
Haynes Mathew George03c40102016-01-29 17:57:48 -08003650 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003651
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003652 /*
3653 * Instead of writing zeroes here, we could trust the hardware
3654 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003655 * 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 -08003656 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08003657 if (ret == 0 && adev->mic_muted &&
3658 !voice_is_in_call_rec_stream(in) &&
3659 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003660 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07003661 in->frames_muted += frames;
3662 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003663
3664exit:
3665 pthread_mutex_unlock(&in->lock);
3666
3667 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07003668 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003669 in_standby(&in->stream.common);
3670 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003671 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003672 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07003673 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08003674 }
3675 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003676 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003677 }
3678 return bytes;
3679}
3680
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003681static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003682{
3683 return 0;
3684}
3685
Andy Hung6ebe5962016-01-15 17:46:57 -08003686static int in_get_capture_position(const struct audio_stream_in *stream,
3687 int64_t *frames, int64_t *time)
3688{
3689 if (stream == NULL || frames == NULL || time == NULL) {
3690 return -EINVAL;
3691 }
3692 struct stream_in *in = (struct stream_in *)stream;
3693 int ret = -ENOSYS;
3694
3695 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003696 // note: ST sessions do not close the alsa pcm driver synchronously
3697 // on standby. Therefore, we may return an error even though the
3698 // pcm stream is still opened.
3699 if (in->standby) {
3700 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
3701 "%s stream in standby but pcm not NULL for non ST session", __func__);
3702 goto exit;
3703 }
Andy Hung6ebe5962016-01-15 17:46:57 -08003704 if (in->pcm) {
3705 struct timespec timestamp;
3706 unsigned int avail;
3707 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3708 *frames = in->frames_read + avail;
3709 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3710 ret = 0;
3711 }
3712 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003713exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08003714 pthread_mutex_unlock(&in->lock);
3715 return ret;
3716}
3717
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003718static int add_remove_audio_effect(const struct audio_stream *stream,
3719 effect_handle_t effect,
3720 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003721{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003722 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003723 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003724 int status = 0;
3725 effect_descriptor_t desc;
3726
3727 status = (*effect)->get_descriptor(effect, &desc);
3728 if (status != 0)
3729 return status;
3730
Eric Laurenta1478072015-09-21 17:21:52 -07003731 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003732 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003733 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003734 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003735 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003736 in->enable_aec != enable &&
3737 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3738 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003739 if (!enable)
3740 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003741 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3742 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3743 adev->enable_voicerx = enable;
3744 struct audio_usecase *usecase;
3745 struct listnode *node;
3746 list_for_each(node, &adev->usecase_list) {
3747 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07003748 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07003749 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05003750 }
3751 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003752 if (!in->standby)
3753 select_devices(in->dev, in->usecase);
3754 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003755 if (in->enable_ns != enable &&
3756 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3757 in->enable_ns = enable;
3758 if (!in->standby)
3759 select_devices(in->dev, in->usecase);
3760 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003761 pthread_mutex_unlock(&in->dev->lock);
3762 pthread_mutex_unlock(&in->lock);
3763
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003764 return 0;
3765}
3766
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003767static int in_add_audio_effect(const struct audio_stream *stream,
3768 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003769{
Eric Laurent994a6932013-07-17 11:51:42 -07003770 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003771 return add_remove_audio_effect(stream, effect, true);
3772}
3773
3774static int in_remove_audio_effect(const struct audio_stream *stream,
3775 effect_handle_t effect)
3776{
Eric Laurent994a6932013-07-17 11:51:42 -07003777 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003778 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003779}
3780
Eric Laurent0e46adf2016-12-16 12:49:24 -08003781static int in_stop(const struct audio_stream_in* stream)
3782{
3783 struct stream_in *in = (struct stream_in *)stream;
3784 struct audio_device *adev = in->dev;
3785
3786 int ret = -ENOSYS;
3787 ALOGV("%s", __func__);
3788 pthread_mutex_lock(&adev->lock);
3789 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3790 in->capture_started && in->pcm != NULL) {
3791 pcm_stop(in->pcm);
3792 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003793 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003794 }
3795 pthread_mutex_unlock(&adev->lock);
3796 return ret;
3797}
3798
3799static int in_start(const struct audio_stream_in* stream)
3800{
3801 struct stream_in *in = (struct stream_in *)stream;
3802 struct audio_device *adev = in->dev;
3803 int ret = -ENOSYS;
3804
3805 ALOGV("%s in %p", __func__, in);
3806 pthread_mutex_lock(&adev->lock);
3807 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3808 !in->capture_started && in->pcm != NULL) {
3809 if (!in->capture_started) {
3810 ret = start_input_stream(in);
3811 if (ret == 0) {
3812 in->capture_started = true;
3813 }
3814 }
3815 }
3816 pthread_mutex_unlock(&adev->lock);
3817 return ret;
3818}
3819
3820static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3821 int32_t min_size_frames,
3822 struct audio_mmap_buffer_info *info)
3823{
3824 struct stream_in *in = (struct stream_in *)stream;
3825 struct audio_device *adev = in->dev;
3826 int ret = 0;
3827 unsigned int offset1;
3828 unsigned int frames1;
3829 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003830 uint32_t mmap_size;
3831 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003832
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003833 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003834 pthread_mutex_lock(&adev->lock);
3835 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003836
Eric Laurent0e46adf2016-12-16 12:49:24 -08003837 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003838 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003839 ret = -EINVAL;
3840 goto exit;
3841 }
3842 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003843 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003844 ALOGV("%s in %p", __func__, in);
3845 ret = -ENOSYS;
3846 goto exit;
3847 }
3848 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3849 if (in->pcm_device_id < 0) {
3850 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3851 __func__, in->pcm_device_id, in->usecase);
3852 ret = -EINVAL;
3853 goto exit;
3854 }
Phil Burkbc991042017-02-24 08:06:44 -08003855
3856 adjust_mmap_period_count(&in->config, min_size_frames);
3857
Eric Laurent0e46adf2016-12-16 12:49:24 -08003858 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3859 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3860 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3861 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3862 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3863 step = "open";
3864 ret = -ENODEV;
3865 goto exit;
3866 }
3867
3868 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3869 if (ret < 0) {
3870 step = "begin";
3871 goto exit;
3872 }
3873 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003874 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003875 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003876 ret = platform_get_mmap_data_fd(adev->platform,
3877 in->pcm_device_id, 1 /*capture*/,
3878 &info->shared_memory_fd,
3879 &mmap_size);
3880 if (ret < 0) {
3881 // Fall back to non exclusive mode
3882 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3883 } else {
3884 if (mmap_size < buffer_size) {
3885 step = "mmap";
3886 goto exit;
3887 }
3888 // FIXME: indicate exclusive mode support by returning a negative buffer size
3889 info->buffer_size_frames *= -1;
3890 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08003891
Haynes Mathew George96483a22017-03-28 14:52:47 -07003892 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003893
3894 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3895 if (ret < 0) {
3896 step = "commit";
3897 goto exit;
3898 }
3899
Phil Burkbc991042017-02-24 08:06:44 -08003900 in->standby = false;
3901 ret = 0;
3902
Eric Laurent0e46adf2016-12-16 12:49:24 -08003903 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3904 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003905
3906exit:
3907 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003908 if (in->pcm == NULL) {
3909 ALOGE("%s: %s - %d", __func__, step, ret);
3910 } else {
3911 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003912 pcm_close(in->pcm);
3913 in->pcm = NULL;
3914 }
3915 }
3916 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003917 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003918 return ret;
3919}
3920
3921static int in_get_mmap_position(const struct audio_stream_in *stream,
3922 struct audio_mmap_position *position)
3923{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003924 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003925 struct stream_in *in = (struct stream_in *)stream;
3926 ALOGVV("%s", __func__);
3927 if (position == NULL) {
3928 return -EINVAL;
3929 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003930 lock_input_stream(in);
3931 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
3932 in->pcm == NULL) {
3933 ret = -ENOSYS;
3934 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003935 }
3936 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003937 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003938 if (ret < 0) {
3939 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003940 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003941 }
Andy Hungfc044e12017-03-20 09:24:22 -07003942 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003943exit:
3944 pthread_mutex_unlock(&in->lock);
3945 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003946}
3947
jiabin8962a4d2018-03-19 18:21:24 -07003948static int in_get_active_microphones(const struct audio_stream_in *stream,
3949 struct audio_microphone_characteristic_t *mic_array,
3950 size_t *mic_count) {
3951 struct stream_in *in = (struct stream_in *)stream;
3952 struct audio_device *adev = in->dev;
3953 ALOGVV("%s", __func__);
3954
3955 lock_input_stream(in);
3956 pthread_mutex_lock(&adev->lock);
3957 int ret = platform_get_active_microphones(adev->platform, in->device,
3958 audio_channel_count_from_in_mask(in->channel_mask),
3959 in->source, in->usecase, mic_array, mic_count);
3960 pthread_mutex_unlock(&adev->lock);
3961 pthread_mutex_unlock(&in->lock);
3962
3963 return ret;
3964}
3965
3966static int adev_get_microphones(const struct audio_hw_device *dev,
3967 struct audio_microphone_characteristic_t *mic_array,
3968 size_t *mic_count) {
3969 struct audio_device *adev = (struct audio_device *)dev;
3970 ALOGVV("%s", __func__);
3971
3972 pthread_mutex_lock(&adev->lock);
3973 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
3974 pthread_mutex_unlock(&adev->lock);
3975
3976 return ret;
3977}
Eric Laurent0e46adf2016-12-16 12:49:24 -08003978
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003979static int adev_open_output_stream(struct audio_hw_device *dev,
3980 audio_io_handle_t handle,
3981 audio_devices_t devices,
3982 audio_output_flags_t flags,
3983 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003984 struct audio_stream_out **stream_out,
3985 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003986{
3987 struct audio_device *adev = (struct audio_device *)dev;
3988 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003989 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003990 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
3991 bool is_usb_dev = audio_is_usb_out_device(devices) &&
3992 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003993
Andy Hungd9653bd2017-08-01 19:31:39 -07003994 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
3995 return -ENOSYS;
3996 }
3997
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003998 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
3999 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004000 *stream_out = NULL;
4001 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4002
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004003 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
4004
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004005 if (devices == AUDIO_DEVICE_NONE)
4006 devices = AUDIO_DEVICE_OUT_SPEAKER;
4007
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004008 out->flags = flags;
4009 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004010 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004011 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07004012 out->handle = handle;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004013 out->a2dp_compress_mute = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004014
4015 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004016 if ((is_hdmi || is_usb_dev) &&
4017 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
4018 (flags == AUDIO_OUTPUT_FLAG_NONE ||
4019 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Eric Laurentab805ee2018-03-30 12:20:38 -07004020 audio_format_t req_format = config->format;
4021 audio_channel_mask_t req_channel_mask = config->channel_mask;
4022 uint32_t req_sample_rate = config->sample_rate;
4023
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004024 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004025 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004026 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004027 if (config->sample_rate == 0)
4028 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Eric Laurentab805ee2018-03-30 12:20:38 -07004029 if (config->channel_mask == AUDIO_CHANNEL_NONE)
Haynes Mathew George569b7482017-05-08 14:44:27 -07004030 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
4031 if (config->format == AUDIO_FORMAT_DEFAULT)
4032 config->format = AUDIO_FORMAT_PCM_16_BIT;
4033 } else if (is_usb_dev) {
4034 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
4035 &config->format,
4036 &out->supported_formats[0],
4037 MAX_SUPPORTED_FORMATS,
4038 &config->channel_mask,
4039 &out->supported_channel_masks[0],
4040 MAX_SUPPORTED_CHANNEL_MASKS,
4041 &config->sample_rate,
4042 &out->supported_sample_rates[0],
4043 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004044 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004045 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004046 pthread_mutex_unlock(&adev->lock);
Eric Laurentab805ee2018-03-30 12:20:38 -07004047 if (ret != 0) {
4048 // For MMAP NO IRQ, allow conversions in ADSP
4049 if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
4050 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004051
Eric Laurentab805ee2018-03-30 12:20:38 -07004052 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
4053 config->sample_rate = req_sample_rate;
4054 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
4055 config->channel_mask = req_channel_mask;
4056 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
4057 config->format = req_format;
4058 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004059
Haynes Mathew George569b7482017-05-08 14:44:27 -07004060 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004061 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004062 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004063 if (is_hdmi) {
4064 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4065 out->config = pcm_config_hdmi_multi;
4066 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
4067 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4068 out->config = pcm_config_mmap_playback;
4069 out->stream.start = out_start;
4070 out->stream.stop = out_stop;
4071 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4072 out->stream.get_mmap_position = out_get_mmap_position;
4073 } else {
4074 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4075 out->config = pcm_config_hifi;
4076 }
4077
4078 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004079 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004080 if (is_hdmi) {
4081 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
4082 audio_bytes_per_sample(out->format));
4083 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004084 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004085 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07004086 pthread_mutex_lock(&adev->lock);
4087 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4088 pthread_mutex_unlock(&adev->lock);
4089
4090 // reject offload during card offline to allow
4091 // fallback to s/w paths
4092 if (offline) {
4093 ret = -ENODEV;
4094 goto error_open;
4095 }
4096
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004097 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4098 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4099 ALOGE("%s: Unsupported Offload information", __func__);
4100 ret = -EINVAL;
4101 goto error_open;
4102 }
4103 if (!is_supported_format(config->offload_info.format)) {
4104 ALOGE("%s: Unsupported audio format", __func__);
4105 ret = -EINVAL;
4106 goto error_open;
4107 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004108 out->sample_rate = config->offload_info.sample_rate;
4109 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
4110 out->channel_mask = config->offload_info.channel_mask;
4111 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
4112 out->channel_mask = config->channel_mask;
4113 else
4114 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4115
4116 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004117
4118 out->compr_config.codec = (struct snd_codec *)
4119 calloc(1, sizeof(struct snd_codec));
4120
4121 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004122
4123 out->stream.set_callback = out_set_callback;
4124 out->stream.pause = out_pause;
4125 out->stream.resume = out_resume;
4126 out->stream.drain = out_drain;
4127 out->stream.flush = out_flush;
4128
4129 out->compr_config.codec->id =
4130 get_snd_codec_id(config->offload_info.format);
4131 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
4132 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004133 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004134 out->compr_config.codec->bit_rate =
4135 config->offload_info.bit_rate;
4136 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004137 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004138 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
4139
4140 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4141 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004142
4143 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004144 create_offload_callback_thread(out);
4145 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4146 __func__, config->offload_info.version,
4147 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02004148 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4149 switch (config->sample_rate) {
4150 case 0:
4151 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4152 break;
4153 case 8000:
4154 case 16000:
4155 case 48000:
4156 out->sample_rate = config->sample_rate;
4157 break;
4158 default:
4159 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
4160 config->sample_rate);
4161 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4162 ret = -EINVAL;
4163 goto error_open;
4164 }
4165 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4166 switch (config->channel_mask) {
4167 case AUDIO_CHANNEL_NONE:
4168 case AUDIO_CHANNEL_OUT_STEREO:
4169 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4170 break;
4171 default:
4172 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
4173 config->channel_mask);
4174 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4175 ret = -EINVAL;
4176 goto error_open;
4177 }
4178 switch (config->format) {
4179 case AUDIO_FORMAT_DEFAULT:
4180 case AUDIO_FORMAT_PCM_16_BIT:
4181 out->format = AUDIO_FORMAT_PCM_16_BIT;
4182 break;
4183 default:
4184 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
4185 config->format);
4186 config->format = AUDIO_FORMAT_PCM_16_BIT;
4187 ret = -EINVAL;
4188 goto error_open;
4189 }
4190
4191 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004192 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004193 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004194 case 0:
4195 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
4196 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07004197 case 8000:
4198 case 16000:
4199 case 48000:
4200 out->sample_rate = config->sample_rate;
4201 break;
4202 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004203 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
4204 config->sample_rate);
4205 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4206 ret = -EINVAL;
4207 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004208 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004209 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4210 switch (config->channel_mask) {
4211 case AUDIO_CHANNEL_NONE:
4212 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4213 break;
4214 case AUDIO_CHANNEL_OUT_STEREO:
4215 out->channel_mask = config->channel_mask;
4216 break;
4217 default:
4218 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
4219 config->channel_mask);
4220 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4221 ret = -EINVAL;
4222 break;
4223 }
4224 switch (config->format) {
4225 case AUDIO_FORMAT_DEFAULT:
4226 out->format = AUDIO_FORMAT_PCM_16_BIT;
4227 break;
4228 case AUDIO_FORMAT_PCM_16_BIT:
4229 out->format = config->format;
4230 break;
4231 default:
4232 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
4233 config->format);
4234 config->format = AUDIO_FORMAT_PCM_16_BIT;
4235 ret = -EINVAL;
4236 break;
4237 }
4238 if (ret != 0)
4239 goto error_open;
4240
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004241 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4242 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004243 out->config.rate = out->sample_rate;
4244 out->config.channels =
4245 audio_channel_count_from_out_mask(out->channel_mask);
4246 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004247 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004248 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
4249 switch (config->sample_rate) {
4250 case 0:
4251 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4252 break;
4253 case 8000:
4254 case 16000:
4255 case 32000:
4256 case 48000:
4257 out->sample_rate = config->sample_rate;
4258 break;
4259 default:
4260 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
4261 config->sample_rate);
4262 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4263 ret = -EINVAL;
4264 break;
4265 }
Eric Laurentad2dde92017-09-20 18:27:31 -07004266 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004267 switch (config->channel_mask) {
4268 case AUDIO_CHANNEL_NONE:
4269 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4270 break;
4271 case AUDIO_CHANNEL_OUT_STEREO:
4272 out->channel_mask = config->channel_mask;
4273 break;
4274 default:
4275 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
4276 config->channel_mask);
4277 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4278 ret = -EINVAL;
4279 break;
4280 }
4281 switch (config->format) {
4282 case AUDIO_FORMAT_DEFAULT:
4283 out->format = AUDIO_FORMAT_PCM_16_BIT;
4284 break;
4285 case AUDIO_FORMAT_PCM_16_BIT:
4286 out->format = config->format;
4287 break;
4288 default:
4289 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
4290 config->format);
4291 config->format = AUDIO_FORMAT_PCM_16_BIT;
4292 ret = -EINVAL;
4293 break;
4294 }
4295 if (ret != 0)
4296 goto error_open;
4297
vivek mehtaa68fea62017-06-08 19:04:02 -07004298 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07004299 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4300 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004301 out->config.rate = out->sample_rate;
4302 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07004303 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004304 out->sample_rate,
4305 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07004306 out->config.channels,
4307 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004308 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07004309 out->config.period_size = buffer_size / frame_size;
4310 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
4311 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004312 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004313 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07004314 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4315 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004316 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07004317 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
4318 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004319 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07004320 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004321 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004322 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004323 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004324 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4325 out->config = pcm_config_mmap_playback;
4326 out->stream.start = out_start;
4327 out->stream.stop = out_stop;
4328 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4329 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004330 } else {
4331 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4332 out->config = pcm_config_low_latency;
4333 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004334
4335 if (config->sample_rate == 0) {
4336 out->sample_rate = out->config.rate;
4337 } else {
4338 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004339 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004340 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
4341 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
4342 } else {
4343 out->channel_mask = config->channel_mask;
4344 }
4345 if (config->format == AUDIO_FORMAT_DEFAULT)
4346 out->format = audio_format_from_pcm_format(out->config.format);
4347 else if (!audio_is_linear_pcm(config->format)) {
4348 config->format = AUDIO_FORMAT_PCM_16_BIT;
4349 ret = -EINVAL;
4350 goto error_open;
4351 } else {
4352 out->format = config->format;
4353 }
4354
4355 out->config.rate = out->sample_rate;
4356 out->config.channels =
4357 audio_channel_count_from_out_mask(out->channel_mask);
4358 if (out->format != audio_format_from_pcm_format(out->config.format)) {
4359 out->config.format = pcm_format_from_audio_format(out->format);
4360 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004361 }
Kevin Rocard50eff892017-05-02 16:52:05 -07004362
4363 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
4364 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004365 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004366 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
4367 __func__, config->sample_rate, config->format, config->channel_mask);
4368 config->sample_rate = out->sample_rate;
4369 config->format = out->format;
4370 config->channel_mask = out->channel_mask;
4371 ret = -EINVAL;
4372 goto error_open;
4373 }
4374
Andy Hung6fcba9c2014-03-18 11:53:32 -07004375 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
4376 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004377
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004378 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004379 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004380 adev->primary_output = out;
4381 else {
4382 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004383 ret = -EEXIST;
4384 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004385 }
4386 }
4387
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004388 /* Check if this usecase is already existing */
4389 pthread_mutex_lock(&adev->lock);
4390 if (get_usecase_from_list(adev, out->usecase) != NULL) {
4391 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004392 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004393 ret = -EEXIST;
4394 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004395 }
4396 pthread_mutex_unlock(&adev->lock);
4397
4398 out->stream.common.get_sample_rate = out_get_sample_rate;
4399 out->stream.common.set_sample_rate = out_set_sample_rate;
4400 out->stream.common.get_buffer_size = out_get_buffer_size;
4401 out->stream.common.get_channels = out_get_channels;
4402 out->stream.common.get_format = out_get_format;
4403 out->stream.common.set_format = out_set_format;
4404 out->stream.common.standby = out_standby;
4405 out->stream.common.dump = out_dump;
4406 out->stream.common.set_parameters = out_set_parameters;
4407 out->stream.common.get_parameters = out_get_parameters;
4408 out->stream.common.add_audio_effect = out_add_audio_effect;
4409 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4410 out->stream.get_latency = out_get_latency;
4411 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004412#ifdef NO_AUDIO_OUT
4413 out->stream.write = out_write_for_no_output;
4414#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004415 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004416#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004417 out->stream.get_render_position = out_get_render_position;
4418 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004419 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004420
Eric Laurent0e46adf2016-12-16 12:49:24 -08004421 if (out->realtime)
4422 out->af_period_multiplier = af_period_multiplier;
4423 else
4424 out->af_period_multiplier = 1;
4425
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004426 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004427 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004428 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004429
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004430 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004431 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004432 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4433
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004434 config->format = out->stream.common.get_format(&out->stream.common);
4435 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4436 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4437
Andy Hunga452b0a2017-03-15 14:51:15 -07004438 out->error_log = error_log_create(
4439 ERROR_LOG_ENTRIES,
4440 1000000000 /* aggregate consecutive identical errors within one second in ns */);
4441
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004442 /*
4443 By locking output stream before registering, we allow the callback
4444 to update stream's state only after stream's initial state is set to
4445 adev state.
4446 */
4447 lock_output_stream(out);
4448 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4449 pthread_mutex_lock(&adev->lock);
4450 out->card_status = adev->card_status;
4451 pthread_mutex_unlock(&adev->lock);
4452 pthread_mutex_unlock(&out->lock);
4453
vivek mehta4a824772017-06-08 19:05:49 -07004454 stream_app_type_cfg_init(&out->app_type_cfg);
4455
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004456 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004457
Eric Laurent994a6932013-07-17 11:51:42 -07004458 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004459 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004460
4461error_open:
4462 free(out);
4463 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07004464 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004465 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004466}
4467
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004468static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004469 struct audio_stream_out *stream)
4470{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004471 struct stream_out *out = (struct stream_out *)stream;
4472 struct audio_device *adev = out->dev;
4473
Eric Laurent994a6932013-07-17 11:51:42 -07004474 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004475
4476 // must deregister from sndmonitor first to prevent races
4477 // between the callback and close_stream
4478 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004479 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004480 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
4481 destroy_offload_callback_thread(out);
4482
4483 if (out->compr_config.codec != NULL)
4484 free(out->compr_config.codec);
4485 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004486
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004487 out->a2dp_compress_mute = false;
4488
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004489 if (adev->voice_tx_output == out)
4490 adev->voice_tx_output = NULL;
4491
Andy Hunga452b0a2017-03-15 14:51:15 -07004492 error_log_destroy(out->error_log);
4493 out->error_log = NULL;
4494
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004495 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004496 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004497 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004498 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004499 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004500}
4501
4502static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4503{
4504 struct audio_device *adev = (struct audio_device *)dev;
4505 struct str_parms *parms;
4506 char *str;
4507 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004508 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004509 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07004510 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004511
Joe Onorato188b6222016-03-01 11:02:27 -08004512 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004513
4514 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004515
4516 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004517 status = voice_set_parameters(adev, parms);
4518 if (status != 0) {
4519 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004520 }
4521
4522 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4523 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07004524 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004525 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4526 adev->bluetooth_nrec = true;
4527 else
4528 adev->bluetooth_nrec = false;
4529 }
4530
4531 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4532 if (ret >= 0) {
4533 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4534 adev->screen_off = false;
4535 else
4536 adev->screen_off = true;
4537 }
4538
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004539 ret = str_parms_get_int(parms, "rotation", &val);
4540 if (ret >= 0) {
4541 bool reverse_speakers = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004542 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004543 // FIXME: note that the code below assumes that the speakers are in the correct placement
4544 // relative to the user when the device is rotated 90deg from its default rotation. This
4545 // assumption is device-specific, not platform-specific like this code.
4546 case 270:
4547 reverse_speakers = true;
4548 break;
4549 case 0:
4550 case 90:
4551 case 180:
4552 break;
4553 default:
4554 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07004555 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004556 }
Eric Laurent03f09432014-03-25 18:09:11 -07004557 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004558 // check and set swap
4559 // - check if orientation changed and speaker active
4560 // - set rotation and cache the rotation value
4561 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004562 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004563 }
4564
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004565 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4566 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004567 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004568 }
4569
David Linee3fe402017-03-13 10:00:42 -07004570 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4571 if (ret >= 0) {
4572 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004573 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004574 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4575 if (ret >= 0) {
4576 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004577 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004578 }
Eric Laurent99dab492017-06-17 15:19:08 -07004579 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004580 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4581 if (ret >= 0) {
4582 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004583 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004584 }
4585 }
4586 }
4587
4588 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4589 if (ret >= 0) {
4590 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004591 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004592 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4593 if (ret >= 0) {
4594 const int card = atoi(value);
4595
Eric Laurent99dab492017-06-17 15:19:08 -07004596 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004597 }
Eric Laurent99dab492017-06-17 15:19:08 -07004598 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004599 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4600 if (ret >= 0) {
4601 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004602 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004603 }
4604 }
4605 }
4606
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004607 audio_extn_hfp_set_parameters(adev, parms);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004608 audio_extn_a2dp_set_parameters(parms);
4609 // reconfigure should be done only after updating A2DP state in audio extension
4610 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4611 if (ret >= 0) {
4612 struct audio_usecase *usecase;
4613 struct listnode *node;
4614 list_for_each(node, &adev->usecase_list) {
4615 usecase = node_to_item(node, struct audio_usecase, list);
4616 if ((usecase->type == PCM_PLAYBACK) &&
4617 (usecase->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP)) {
4618 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
4619
4620 pthread_mutex_unlock(&adev->lock);
4621 lock_output_stream(usecase->stream.out);
4622 pthread_mutex_lock(&adev->lock);
4623 audio_extn_a2dp_set_handoff_mode(true);
4624 // force device switch to reconfigure encoder
4625 select_devices(adev, usecase->id);
4626 audio_extn_a2dp_set_handoff_mode(false);
4627 pthread_mutex_unlock(&usecase->stream.out->lock);
4628 break;
4629 }
4630 }
4631 }
4632
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004633done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004634 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004635 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004636 ALOGV("%s: exit with code(%d)", __func__, status);
4637 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004638}
4639
4640static char* adev_get_parameters(const struct audio_hw_device *dev,
4641 const char *keys)
4642{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004643 struct audio_device *adev = (struct audio_device *)dev;
4644 struct str_parms *reply = str_parms_create();
4645 struct str_parms *query = str_parms_create_str(keys);
4646 char *str;
4647
4648 pthread_mutex_lock(&adev->lock);
4649
4650 voice_get_parameters(adev, query, reply);
4651 str = str_parms_to_str(reply);
4652 str_parms_destroy(query);
4653 str_parms_destroy(reply);
4654
4655 pthread_mutex_unlock(&adev->lock);
4656 ALOGV("%s: exit: returns - %s", __func__, str);
4657 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004658}
4659
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004660static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004661{
4662 return 0;
4663}
4664
Haynes Mathew George5191a852013-09-11 14:19:36 -07004665static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4666{
4667 int ret;
4668 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004669
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004670 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4671
Haynes Mathew George5191a852013-09-11 14:19:36 -07004672 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004673 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004674 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004675
Haynes Mathew George5191a852013-09-11 14:19:36 -07004676 return ret;
4677}
4678
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004679static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004680{
4681 return -ENOSYS;
4682}
4683
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004684static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4685 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004686{
4687 return -ENOSYS;
4688}
4689
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004690static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004691{
4692 return -ENOSYS;
4693}
4694
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004695static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004696{
4697 return -ENOSYS;
4698}
4699
4700static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4701{
4702 struct audio_device *adev = (struct audio_device *)dev;
4703
4704 pthread_mutex_lock(&adev->lock);
4705 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004706 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004707 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004708 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4709 voice_is_in_call(adev)) {
4710 voice_stop_call(adev);
4711 adev->current_call_output = NULL;
4712 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004713 }
4714 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004715
4716 audio_extn_extspk_set_mode(adev->extspk, mode);
4717
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004718 return 0;
4719}
4720
4721static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4722{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004723 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004724 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004725
Eric Laurent2bafff12016-03-17 12:17:23 -07004726 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004727 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004728 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4729 ret = audio_extn_hfp_set_mic_mute(adev, state);
4730 } else {
4731 ret = voice_set_mic_mute(adev, state);
4732 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004733 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004734 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004735
4736 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004737}
4738
4739static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4740{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004741 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004742 return 0;
4743}
4744
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004745static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004746 const struct audio_config *config)
4747{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004748 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004749
Eric Laurent74b55762017-07-09 17:04:53 -07004750 /* Don't know if USB HIFI in this context so use true to be conservative */
4751 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4752 true /*is_usb_hifi */) != 0)
4753 return 0;
4754
vivek mehtaa68fea62017-06-08 19:04:02 -07004755 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4756 config->sample_rate, config->format,
4757 channel_count,
4758 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004759}
4760
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004761static bool adev_input_allow_hifi_record(struct audio_device *adev,
4762 audio_devices_t devices,
4763 audio_input_flags_t flags,
4764 audio_source_t source) {
4765 const bool allowed = true;
4766
4767 if (!audio_is_usb_in_device(devices))
4768 return !allowed;
4769
4770 switch (flags) {
4771 case AUDIO_INPUT_FLAG_NONE:
4772 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4773 break;
4774 default:
4775 return !allowed;
4776 }
4777
4778 switch (source) {
4779 case AUDIO_SOURCE_DEFAULT:
4780 case AUDIO_SOURCE_MIC:
4781 case AUDIO_SOURCE_UNPROCESSED:
4782 break;
4783 default:
4784 return !allowed;
4785 }
4786
4787 switch (adev->mode) {
4788 case 0:
4789 break;
4790 default:
4791 return !allowed;
4792 }
4793
4794 return allowed;
4795}
4796
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004797static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004798 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004799 audio_devices_t devices,
4800 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004801 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004802 audio_input_flags_t flags,
4803 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004804 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004805{
4806 struct audio_device *adev = (struct audio_device *)dev;
4807 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004808 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004809 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004810 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004811 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004812 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4813 devices,
4814 flags,
4815 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004816 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004817 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004818
Andy Hungd9653bd2017-08-01 19:31:39 -07004819 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
4820 return -ENOSYS;
4821 }
4822
Eric Laurent74b55762017-07-09 17:04:53 -07004823 if (!(is_usb_dev && may_use_hifi_record)) {
4824 if (config->sample_rate == 0)
4825 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4826 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4827 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4828 if (config->format == AUDIO_FORMAT_DEFAULT)
4829 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004830
Eric Laurent74b55762017-07-09 17:04:53 -07004831 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
4832
4833 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
4834 return -EINVAL;
4835 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004836
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004837 if (audio_extn_tfa_98xx_is_supported() &&
4838 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004839 return -EINVAL;
4840
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004841 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4842
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004843 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004844 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004845
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004846 in->stream.common.get_sample_rate = in_get_sample_rate;
4847 in->stream.common.set_sample_rate = in_set_sample_rate;
4848 in->stream.common.get_buffer_size = in_get_buffer_size;
4849 in->stream.common.get_channels = in_get_channels;
4850 in->stream.common.get_format = in_get_format;
4851 in->stream.common.set_format = in_set_format;
4852 in->stream.common.standby = in_standby;
4853 in->stream.common.dump = in_dump;
4854 in->stream.common.set_parameters = in_set_parameters;
4855 in->stream.common.get_parameters = in_get_parameters;
4856 in->stream.common.add_audio_effect = in_add_audio_effect;
4857 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4858 in->stream.set_gain = in_set_gain;
4859 in->stream.read = in_read;
4860 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08004861 in->stream.get_capture_position = in_get_capture_position;
jiabin8962a4d2018-03-19 18:21:24 -07004862 in->stream.get_active_microphones = in_get_active_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004863
4864 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004865 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004866 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004867 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004868 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004869 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004870
Haynes Mathew George569b7482017-05-08 14:44:27 -07004871 if (is_usb_dev && may_use_hifi_record) {
4872 /* HiFi record selects an appropriate format, channel, rate combo
4873 depending on sink capabilities*/
4874 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
4875 &config->format,
4876 &in->supported_formats[0],
4877 MAX_SUPPORTED_FORMATS,
4878 &config->channel_mask,
4879 &in->supported_channel_masks[0],
4880 MAX_SUPPORTED_CHANNEL_MASKS,
4881 &config->sample_rate,
4882 &in->supported_sample_rates[0],
4883 MAX_SUPPORTED_SAMPLE_RATES);
4884 if (ret != 0) {
4885 ret = -EINVAL;
4886 goto err_open;
4887 }
Eric Laurent74b55762017-07-09 17:04:53 -07004888 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004889 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07004890 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07004891 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
4892 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
4893 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4894 bool ret_error = false;
4895 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4896 from HAL is 8_24
4897 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4898 8_24 return error indicating supported format is 8_24
4899 *> In case of any other source requesting 24 bit or float return error
4900 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07004901
vivek mehta57ff9b52016-04-28 14:13:08 -07004902 on error flinger will retry with supported format passed
4903 */
4904 if (source != AUDIO_SOURCE_UNPROCESSED) {
4905 config->format = AUDIO_FORMAT_PCM_16_BIT;
4906 ret_error = true;
4907 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
4908 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
4909 ret_error = true;
4910 }
4911
4912 if (ret_error) {
4913 ret = -EINVAL;
4914 goto err_open;
4915 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004916 }
4917
vivek mehta57ff9b52016-04-28 14:13:08 -07004918 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07004919 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07004920
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004921 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004922 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
4923 if (config->sample_rate == 0)
4924 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4925 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4926 config->sample_rate != 8000) {
4927 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4928 ret = -EINVAL;
4929 goto err_open;
4930 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004931
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004932 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4933 config->format = AUDIO_FORMAT_PCM_16_BIT;
4934 ret = -EINVAL;
4935 goto err_open;
4936 }
4937
4938 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4939 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07004940 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004941 } else if (is_usb_dev && may_use_hifi_record) {
4942 in->usecase = USECASE_AUDIO_RECORD_HIFI;
4943 in->config = pcm_config_audio_capture;
4944 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004945 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4946 config->sample_rate,
4947 config->format,
4948 channel_count,
4949 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004950 in->config.period_size = buffer_size / frame_size;
4951 in->config.rate = config->sample_rate;
4952 in->af_period_multiplier = 1;
4953 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004954 } else {
4955 in->usecase = USECASE_AUDIO_RECORD;
4956 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08004957 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004958 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07004959#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004960 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07004961#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08004962 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004963 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08004964 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004965 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004966 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4967 config->sample_rate,
4968 config->format,
4969 channel_count,
4970 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004971 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004972 in->config.rate = config->sample_rate;
4973 in->af_period_multiplier = 1;
4974 } else {
4975 // period size is left untouched for rt mode playback
4976 in->config = pcm_config_audio_capture_rt;
4977 in->af_period_multiplier = af_period_multiplier;
4978 }
4979 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
4980 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004981 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08004982 in->usecase = USECASE_AUDIO_RECORD_MMAP;
4983 in->config = pcm_config_mmap_capture;
4984 in->stream.start = in_start;
4985 in->stream.stop = in_stop;
4986 in->stream.create_mmap_buffer = in_create_mmap_buffer;
4987 in->stream.get_mmap_position = in_get_mmap_position;
4988 in->af_period_multiplier = 1;
4989 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07004990 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07004991 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07004992 (config->sample_rate == 8000 ||
4993 config->sample_rate == 16000 ||
4994 config->sample_rate == 32000 ||
4995 config->sample_rate == 48000) &&
4996 channel_count == 1) {
4997 in->usecase = USECASE_AUDIO_RECORD_VOIP;
4998 in->config = pcm_config_audio_capture;
4999 frame_size = audio_stream_in_frame_size(&in->stream);
5000 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
5001 config->sample_rate,
5002 config->format,
5003 channel_count, false /*is_low_latency*/);
5004 in->config.period_size = buffer_size / frame_size;
5005 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
5006 in->config.rate = config->sample_rate;
5007 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005008 } else {
5009 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005010 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005011 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5012 config->sample_rate,
5013 config->format,
5014 channel_count,
5015 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005016 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005017 in->config.rate = config->sample_rate;
5018 in->af_period_multiplier = 1;
5019 }
5020 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
5021 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005022 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08005023
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005024 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07005025 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005026
Andy Hungd13f0d32017-06-12 13:58:37 -07005027 in->error_log = error_log_create(
5028 ERROR_LOG_ENTRIES,
5029 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
5030
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005031 /* This stream could be for sound trigger lab,
5032 get sound trigger pcm if present */
5033 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005034
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005035 lock_input_stream(in);
5036 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5037 pthread_mutex_lock(&adev->lock);
5038 in->card_status = adev->card_status;
5039 pthread_mutex_unlock(&adev->lock);
5040 pthread_mutex_unlock(&in->lock);
5041
vivek mehta4a824772017-06-08 19:05:49 -07005042 stream_app_type_cfg_init(&in->app_type_cfg);
5043
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005044 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005045 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005046 return 0;
5047
5048err_open:
5049 free(in);
5050 *stream_in = NULL;
5051 return ret;
5052}
5053
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005054static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005055 struct audio_stream_in *stream)
5056{
Andy Hungd13f0d32017-06-12 13:58:37 -07005057 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005058 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005059
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005060 // must deregister from sndmonitor first to prevent races
5061 // between the callback and close_stream
5062 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005063 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07005064
5065 error_log_destroy(in->error_log);
5066 in->error_log = NULL;
5067
Andy Hung0dbb52b2017-08-09 13:51:38 -07005068 pthread_mutex_destroy(&in->pre_lock);
5069 pthread_mutex_destroy(&in->lock);
5070
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005071 free(stream);
5072
5073 return;
5074}
5075
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005076static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005077{
5078 return 0;
5079}
5080
Andy Hung31aca912014-03-20 17:14:59 -07005081/* verifies input and output devices and their capabilities.
5082 *
5083 * This verification is required when enabling extended bit-depth or
5084 * sampling rates, as not all qcom products support it.
5085 *
5086 * Suitable for calling only on initialization such as adev_open().
5087 * It fills the audio_device use_case_table[] array.
5088 *
5089 * Has a side-effect that it needs to configure audio routing / devices
5090 * in order to power up the devices and read the device parameters.
5091 * It does not acquire any hw device lock. Should restore the devices
5092 * back to "normal state" upon completion.
5093 */
5094static int adev_verify_devices(struct audio_device *adev)
5095{
5096 /* enumeration is a bit difficult because one really wants to pull
5097 * the use_case, device id, etc from the hidden pcm_device_table[].
5098 * In this case there are the following use cases and device ids.
5099 *
5100 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
5101 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005102 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07005103 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
5104 * [USECASE_AUDIO_RECORD] = {0, 0},
5105 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
5106 * [USECASE_VOICE_CALL] = {2, 2},
5107 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005108 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07005109 * USECASE_VOICE_CALL omitted, but possible for either input or output.
5110 */
5111
5112 /* should be the usecases enabled in adev_open_input_stream() */
5113 static const int test_in_usecases[] = {
5114 USECASE_AUDIO_RECORD,
5115 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
5116 };
5117 /* should be the usecases enabled in adev_open_output_stream()*/
5118 static const int test_out_usecases[] = {
5119 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
5120 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
5121 };
5122 static const usecase_type_t usecase_type_by_dir[] = {
5123 PCM_PLAYBACK,
5124 PCM_CAPTURE,
5125 };
5126 static const unsigned flags_by_dir[] = {
5127 PCM_OUT,
5128 PCM_IN,
5129 };
5130
5131 size_t i;
5132 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005133 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07005134 char info[512]; /* for possible debug info */
5135
5136 for (dir = 0; dir < 2; ++dir) {
5137 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
5138 const unsigned flags_dir = flags_by_dir[dir];
5139 const size_t testsize =
5140 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
5141 const int *testcases =
5142 dir ? test_in_usecases : test_out_usecases;
5143 const audio_devices_t audio_device =
5144 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
5145
5146 for (i = 0; i < testsize; ++i) {
5147 const audio_usecase_t audio_usecase = testcases[i];
5148 int device_id;
5149 snd_device_t snd_device;
5150 struct pcm_params **pparams;
5151 struct stream_out out;
5152 struct stream_in in;
5153 struct audio_usecase uc_info;
5154 int retval;
5155
5156 pparams = &adev->use_case_table[audio_usecase];
5157 pcm_params_free(*pparams); /* can accept null input */
5158 *pparams = NULL;
5159
5160 /* find the device ID for the use case (signed, for error) */
5161 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
5162 if (device_id < 0)
5163 continue;
5164
5165 /* prepare structures for device probing */
5166 memset(&uc_info, 0, sizeof(uc_info));
5167 uc_info.id = audio_usecase;
5168 uc_info.type = usecase_type;
5169 if (dir) {
5170 adev->active_input = &in;
5171 memset(&in, 0, sizeof(in));
5172 in.device = audio_device;
5173 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
5174 uc_info.stream.in = &in;
5175 } else {
5176 adev->active_input = NULL;
5177 }
5178 memset(&out, 0, sizeof(out));
5179 out.devices = audio_device; /* only field needed in select_devices */
5180 uc_info.stream.out = &out;
5181 uc_info.devices = audio_device;
5182 uc_info.in_snd_device = SND_DEVICE_NONE;
5183 uc_info.out_snd_device = SND_DEVICE_NONE;
5184 list_add_tail(&adev->usecase_list, &uc_info.list);
5185
5186 /* select device - similar to start_(in/out)put_stream() */
5187 retval = select_devices(adev, audio_usecase);
5188 if (retval >= 0) {
5189 *pparams = pcm_params_get(card_id, device_id, flags_dir);
5190#if LOG_NDEBUG == 0
5191 if (*pparams) {
5192 ALOGV("%s: (%s) card %d device %d", __func__,
5193 dir ? "input" : "output", card_id, device_id);
5194 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07005195 } else {
5196 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
5197 }
5198#endif
5199 }
5200
5201 /* deselect device - similar to stop_(in/out)put_stream() */
5202 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07005203 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07005204 /* 2. Disable the rx device */
5205 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07005206 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07005207 list_remove(&uc_info.list);
5208 }
5209 }
5210 adev->active_input = NULL; /* restore adev state */
5211 return 0;
5212}
5213
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005214static int adev_close(hw_device_t *device)
5215{
Andy Hung31aca912014-03-20 17:14:59 -07005216 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005217 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005218
5219 if (!adev)
5220 return 0;
5221
5222 pthread_mutex_lock(&adev_init_lock);
5223
5224 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005225 audio_extn_snd_mon_unregister_listener(adev);
5226 audio_extn_tfa_98xx_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005227 audio_route_free(adev->audio_route);
5228 free(adev->snd_dev_ref_cnt);
5229 platform_deinit(adev->platform);
5230 audio_extn_extspk_deinit(adev->extspk);
5231 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005232 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005233 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
5234 pcm_params_free(adev->use_case_table[i]);
5235 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005236 if (adev->adm_deinit)
5237 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005238 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005239 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07005240 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07005241
5242 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005243
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005244 return 0;
5245}
5246
Glenn Kasten4f993392014-05-14 07:30:48 -07005247/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5248 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5249 * just that it _might_ work.
5250 */
5251static int period_size_is_plausible_for_low_latency(int period_size)
5252{
5253 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005254 case 48:
5255 case 96:
5256 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07005257 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005258 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07005259 case 240:
5260 case 320:
5261 case 480:
5262 return 1;
5263 default:
5264 return 0;
5265 }
5266}
5267
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005268static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
5269{
5270 int card;
5271 card_status_t status;
5272
5273 if (!parms)
5274 return;
5275
5276 if (parse_snd_card_status(parms, &card, &status) < 0)
5277 return;
5278
5279 pthread_mutex_lock(&adev->lock);
5280 bool valid_cb = (card == adev->snd_card);
5281 if (valid_cb) {
5282 if (adev->card_status != status) {
5283 adev->card_status = status;
5284 platform_snd_card_update(adev->platform, status);
5285 }
5286 }
5287 pthread_mutex_unlock(&adev->lock);
5288 return;
5289}
5290
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005291/* out and adev lock held */
5292static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
5293{
5294 struct audio_usecase *uc_info;
5295 float left_p;
5296 float right_p;
5297 audio_devices_t devices;
5298
5299 uc_info = get_usecase_from_list(adev, out->usecase);
5300 if (uc_info == NULL) {
5301 ALOGE("%s: Could not find the usecase (%d) in the list",
5302 __func__, out->usecase);
5303 return -EINVAL;
5304 }
5305
5306 ALOGD("%s: enter: usecase(%d: %s)", __func__,
5307 out->usecase, use_case_table[out->usecase]);
5308
5309 if (restore) {
5310 // restore A2DP device for active usecases and unmute if required
5311 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
5312 !is_a2dp_device(uc_info->out_snd_device)) {
5313 ALOGD("%s: restoring A2DP and unmuting stream", __func__);
5314 select_devices(adev, uc_info->id);
5315 pthread_mutex_lock(&out->compr_mute_lock);
5316 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5317 (out->a2dp_compress_mute)) {
5318 out->a2dp_compress_mute = false;
5319 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5320 }
5321 pthread_mutex_unlock(&out->compr_mute_lock);
5322 }
5323 } else {
5324 // mute compress stream if suspended
5325 pthread_mutex_lock(&out->compr_mute_lock);
5326 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5327 (!out->a2dp_compress_mute)) {
5328 if (!out->standby) {
5329 ALOGD("%s: selecting speaker and muting stream", __func__);
5330 devices = out->devices;
5331 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
5332 left_p = out->volume_l;
5333 right_p = out->volume_r;
5334 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5335 compress_pause(out->compr);
5336 set_compr_volume(&out->stream, 0.0f, 0.0f);
5337 out->a2dp_compress_mute = true;
5338 select_devices(adev, out->usecase);
5339 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5340 compress_resume(out->compr);
5341 out->devices = devices;
5342 out->volume_l = left_p;
5343 out->volume_r = right_p;
5344 }
5345 }
5346 pthread_mutex_unlock(&out->compr_mute_lock);
5347 }
5348 ALOGV("%s: exit", __func__);
5349 return 0;
5350}
5351
5352int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
5353{
5354 int ret = 0;
5355
5356 lock_output_stream(out);
5357 pthread_mutex_lock(&adev->lock);
5358
5359 ret = check_a2dp_restore_l(adev, out, restore);
5360
5361 pthread_mutex_unlock(&adev->lock);
5362 pthread_mutex_unlock(&out->lock);
5363 return ret;
5364}
5365
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005366static int adev_open(const hw_module_t *module, const char *name,
5367 hw_device_t **device)
5368{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005369 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005370
Eric Laurent2bafff12016-03-17 12:17:23 -07005371 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005372 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005373 pthread_mutex_lock(&adev_init_lock);
5374 if (audio_device_ref_count != 0) {
5375 *device = &adev->device.common;
5376 audio_device_ref_count++;
5377 ALOGV("%s: returning existing instance of adev", __func__);
5378 ALOGV("%s: exit", __func__);
5379 pthread_mutex_unlock(&adev_init_lock);
5380 return 0;
5381 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005382 adev = calloc(1, sizeof(struct audio_device));
5383
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005384 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5385
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005386 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5387 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5388 adev->device.common.module = (struct hw_module_t *)module;
5389 adev->device.common.close = adev_close;
5390
5391 adev->device.init_check = adev_init_check;
5392 adev->device.set_voice_volume = adev_set_voice_volume;
5393 adev->device.set_master_volume = adev_set_master_volume;
5394 adev->device.get_master_volume = adev_get_master_volume;
5395 adev->device.set_master_mute = adev_set_master_mute;
5396 adev->device.get_master_mute = adev_get_master_mute;
5397 adev->device.set_mode = adev_set_mode;
5398 adev->device.set_mic_mute = adev_set_mic_mute;
5399 adev->device.get_mic_mute = adev_get_mic_mute;
5400 adev->device.set_parameters = adev_set_parameters;
5401 adev->device.get_parameters = adev_get_parameters;
5402 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5403 adev->device.open_output_stream = adev_open_output_stream;
5404 adev->device.close_output_stream = adev_close_output_stream;
5405 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005406
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005407 adev->device.close_input_stream = adev_close_input_stream;
5408 adev->device.dump = adev_dump;
jiabin8962a4d2018-03-19 18:21:24 -07005409 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005410
5411 /* Set the default route before the PCM stream is opened */
5412 pthread_mutex_lock(&adev->lock);
5413 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005414 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005415 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005416 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005417 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005418 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005419 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005420 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005421 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005422 pthread_mutex_unlock(&adev->lock);
5423
5424 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005425 adev->platform = platform_init(adev);
5426 if (!adev->platform) {
5427 free(adev->snd_dev_ref_cnt);
5428 free(adev);
5429 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5430 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005431 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005432 return -EINVAL;
5433 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05005434 adev->extspk = audio_extn_extspk_init(adev);
5435
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005436 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5437 if (adev->visualizer_lib == NULL) {
5438 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5439 } else {
5440 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5441 adev->visualizer_start_output =
5442 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5443 "visualizer_hal_start_output");
5444 adev->visualizer_stop_output =
5445 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5446 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07005447 }
5448
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005449 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5450 if (adev->offload_effects_lib == NULL) {
5451 ALOGW("%s: DLOPEN failed for %s", __func__,
5452 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5453 } else {
5454 ALOGV("%s: DLOPEN successful for %s", __func__,
5455 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5456 adev->offload_effects_start_output =
5457 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5458 "offload_effects_bundle_hal_start_output");
5459 adev->offload_effects_stop_output =
5460 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5461 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07005462 }
5463
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005464 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5465 if (adev->adm_lib == NULL) {
5466 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5467 } else {
5468 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5469 adev->adm_init = (adm_init_t)
5470 dlsym(adev->adm_lib, "adm_init");
5471 adev->adm_deinit = (adm_deinit_t)
5472 dlsym(adev->adm_lib, "adm_deinit");
5473 adev->adm_register_input_stream = (adm_register_input_stream_t)
5474 dlsym(adev->adm_lib, "adm_register_input_stream");
5475 adev->adm_register_output_stream = (adm_register_output_stream_t)
5476 dlsym(adev->adm_lib, "adm_register_output_stream");
5477 adev->adm_deregister_stream = (adm_deregister_stream_t)
5478 dlsym(adev->adm_lib, "adm_deregister_stream");
5479 adev->adm_request_focus = (adm_request_focus_t)
5480 dlsym(adev->adm_lib, "adm_request_focus");
5481 adev->adm_abandon_focus = (adm_abandon_focus_t)
5482 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08005483 adev->adm_set_config = (adm_set_config_t)
5484 dlsym(adev->adm_lib, "adm_set_config");
5485 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5486 dlsym(adev->adm_lib, "adm_request_focus_v2");
5487 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5488 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5489 adev->adm_on_routing_change = (adm_on_routing_change_t)
5490 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005491 }
5492
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005493 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005494 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005495
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005496 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005497
Andy Hung31aca912014-03-20 17:14:59 -07005498 if (k_enable_extended_precision)
5499 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005500
Glenn Kasten4f993392014-05-14 07:30:48 -07005501 char value[PROPERTY_VALUE_MAX];
5502 int trial;
5503 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5504 trial = atoi(value);
5505 if (period_size_is_plausible_for_low_latency(trial)) {
5506 pcm_config_low_latency.period_size = trial;
5507 pcm_config_low_latency.start_threshold = trial / 4;
5508 pcm_config_low_latency.avail_min = trial / 4;
5509 configured_low_latency_capture_period_size = trial;
5510 }
5511 }
5512 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5513 trial = atoi(value);
5514 if (period_size_is_plausible_for_low_latency(trial)) {
5515 configured_low_latency_capture_period_size = trial;
5516 }
5517 }
5518
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005519 // commented as full set of app type cfg is sent from platform
5520 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005521 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005522
5523 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5524 af_period_multiplier = atoi(value);
5525 if (af_period_multiplier < 0) {
5526 af_period_multiplier = 2;
5527 } else if (af_period_multiplier > 4) {
5528 af_period_multiplier = 4;
5529 }
5530 ALOGV("new period_multiplier = %d", af_period_multiplier);
5531 }
5532
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005533 audio_extn_tfa_98xx_init(adev);
5534
vivek mehta1a9b7c02015-06-25 11:49:38 -07005535 pthread_mutex_unlock(&adev_init_lock);
5536
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005537 if (adev->adm_init)
5538 adev->adm_data = adev->adm_init();
5539
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005540 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005541 audio_extn_snd_mon_init();
5542 pthread_mutex_lock(&adev->lock);
5543 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
5544 adev->card_status = CARD_STATUS_ONLINE;
5545 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005546 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005547
Eric Laurent2bafff12016-03-17 12:17:23 -07005548 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005549 return 0;
5550}
5551
5552static struct hw_module_methods_t hal_module_methods = {
5553 .open = adev_open,
5554};
5555
5556struct audio_module HAL_MODULE_INFO_SYM = {
5557 .common = {
5558 .tag = HARDWARE_MODULE_TAG,
5559 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5560 .hal_api_version = HARDWARE_HAL_API_VERSION,
5561 .id = AUDIO_HARDWARE_MODULE_ID,
5562 .name = "QCOM Audio HAL",
5563 .author = "Code Aurora Forum",
5564 .methods = &hal_module_methods,
5565 },
5566};