blob: 6b0acd4f9a371fb2383700e838c9f4ac286dc1be [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 ||
juyuchen1d05ba32018-03-31 16:03:51 +0800665 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700666 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
667 audio_extn_spkr_prot_is_enabled()) {
Aniket Kumar Lata9d6679a2018-04-11 18:13:23 -0700668 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800669 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700670 }
671 if (audio_extn_spkr_prot_start_processing(snd_device)) {
672 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800673 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700674 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700675 } else if (platform_can_split_snd_device(snd_device,
676 &num_devices,
677 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700678 for (i = 0; i < num_devices; i++) {
679 enable_snd_device(adev, new_snd_devices[i]);
680 }
vivek mehtab6506412015-08-07 16:55:17 -0700681 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700682 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800683 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
684 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
685 ALOGE(" %s: Invalid sound device returned", __func__);
686 goto on_error;
687 }
Ed Tam70b5c142016-03-21 19:14:29 -0700688
Eric Laurent2e140aa2016-06-30 17:14:46 -0700689 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800690 audio_route_apply_and_update_path(adev->audio_route, device_name);
691 }
692on_success:
693 adev->snd_dev_ref_cnt[snd_device]++;
694 ret_val = 0;
695on_error:
696 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800697}
698
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800699int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700700 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800701{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700702 int i, num_devices = 0;
703 snd_device_t new_snd_devices[2];
704
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800705 if (snd_device < SND_DEVICE_MIN ||
706 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800707 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800708 return -EINVAL;
709 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700710 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
711 ALOGE("%s: device ref cnt is already 0", __func__);
712 return -EINVAL;
713 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800714 audio_extn_tfa_98xx_disable_speaker(snd_device);
715
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700716 adev->snd_dev_ref_cnt[snd_device]--;
717 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800718 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800719
720 if (is_a2dp_device(snd_device))
721 audio_extn_a2dp_stop_playback();
722
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700723 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800724 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700725 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700726 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
727 audio_extn_spkr_prot_is_enabled()) {
728 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700729
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700730 // FIXME b/65363602: bullhead is the only Nexus with audio_extn_spkr_prot_is_enabled()
731 // and does not use speaker swap. As this code causes a problem with device enable ref
732 // counting we remove it for now.
vivek mehtae59cfb22017-06-16 15:57:11 -0700733 // when speaker device is disabled, reset swap.
734 // will be renabled on usecase start
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700735 // platform_set_swap_channels(adev, false);
vivek mehtae59cfb22017-06-16 15:57:11 -0700736
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700737 } else if (platform_can_split_snd_device(snd_device,
738 &num_devices,
739 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700740 for (i = 0; i < num_devices; i++) {
741 disable_snd_device(adev, new_snd_devices[i]);
742 }
vivek mehtab6506412015-08-07 16:55:17 -0700743 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700744 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800745 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
746 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
747 ALOGE(" %s: Invalid sound device returned", __func__);
748 return -EINVAL;
749 }
750
Eric Laurent2e140aa2016-06-30 17:14:46 -0700751 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800752 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700753 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700754 audio_extn_sound_trigger_update_device_status(snd_device,
755 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700756 }
vivek mehtab6506412015-08-07 16:55:17 -0700757
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800758 return 0;
759}
760
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700761/*
762 legend:
763 uc - existing usecase
764 new_uc - new usecase
765 d1, d11, d2 - SND_DEVICE enums
766 a1, a2 - corresponding ANDROID device enums
767 B, B1, B2 - backend strings
768
769case 1
770 uc->dev d1 (a1) B1
771 new_uc->dev d1 (a1), d2 (a2) B1, B2
772
773 resolution: disable and enable uc->dev on d1
774
775case 2
776 uc->dev d1 (a1) B1
777 new_uc->dev d11 (a1) B1
778
779 resolution: need to switch uc since d1 and d11 are related
780 (e.g. speaker and voice-speaker)
781 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
782
783case 3
784 uc->dev d1 (a1) B1
785 new_uc->dev d2 (a2) B2
786
787 resolution: no need to switch uc
788
789case 4
790 uc->dev d1 (a1) B
791 new_uc->dev d2 (a2) B
792
793 resolution: disable enable uc-dev on d2 since backends match
794 we cannot enable two streams on two different devices if they
795 share the same backend. e.g. if offload is on speaker device using
796 QUAD_MI2S backend and a low-latency stream is started on voice-handset
797 using the same backend, offload must also be switched to voice-handset.
798
799case 5
800 uc->dev d1 (a1) B
801 new_uc->dev d1 (a1), d2 (a2) B
802
803 resolution: disable enable uc-dev on d2 since backends match
804 we cannot enable two streams on two different devices if they
805 share the same backend.
806
807case 6
808 uc->dev d1 a1 B1
809 new_uc->dev d2 a1 B2
810
811 resolution: no need to switch
812
813case 7
814
815 uc->dev d1 (a1), d2 (a2) B1, B2
816 new_uc->dev d1 B1
817
818 resolution: no need to switch
819
820*/
821static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
822 struct audio_usecase *new_uc,
823 snd_device_t new_snd_device)
824{
825 audio_devices_t a1 = uc->stream.out->devices;
826 audio_devices_t a2 = new_uc->stream.out->devices;
827
828 snd_device_t d1 = uc->out_snd_device;
829 snd_device_t d2 = new_snd_device;
830
831 // Treat as a special case when a1 and a2 are not disjoint
832 if ((a1 != a2) && (a1 & a2)) {
833 snd_device_t d3[2];
834 int num_devices = 0;
835 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
836 &num_devices,
837 d3);
838 if (ret < 0) {
839 if (ret != -ENOSYS) {
840 ALOGW("%s failed to split snd_device %d",
841 __func__,
842 popcount(a1) > 1 ? d1 : d2);
843 }
844 goto end;
845 }
846
847 // NB: case 7 is hypothetical and isn't a practical usecase yet.
848 // But if it does happen, we need to give priority to d2 if
849 // the combo devices active on the existing usecase share a backend.
850 // This is because we cannot have a usecase active on a combo device
851 // and a new usecase requests one device in this combo pair.
852 if (platform_check_backends_match(d3[0], d3[1])) {
853 return d2; // case 5
854 } else {
855 return d1; // case 1
856 }
857 } else {
858 if (platform_check_backends_match(d1, d2)) {
859 return d2; // case 2, 4
860 } else {
861 return d1; // case 6, 3
862 }
863 }
864
865end:
866 return d2; // return whatever was calculated before.
867}
868
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700869static void check_and_route_playback_usecases(struct audio_device *adev,
870 struct audio_usecase *uc_info,
871 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700872{
873 struct listnode *node;
874 struct audio_usecase *usecase;
875 bool switch_device[AUDIO_USECASE_MAX];
876 int i, num_uc_to_switch = 0;
877
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700878 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
879 uc_info,
880 snd_device);
David Linee3fe402017-03-13 10:00:42 -0700881
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800882 /* For a2dp device reconfigure all active sessions
883 * with new AFE encoder format based on a2dp state
884 */
885 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
886 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
887 audio_extn_a2dp_is_force_device_switch()) {
888 force_routing = true;
889 }
890
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700891 /*
892 * This function is to make sure that all the usecases that are active on
893 * the hardware codec backend are always routed to any one device that is
894 * handled by the hardware codec.
895 * For example, if low-latency and deep-buffer usecases are currently active
896 * on speaker and out_set_parameters(headset) is received on low-latency
897 * output, then we have to make sure deep-buffer is also switched to headset,
898 * because of the limitation that both the devices cannot be enabled
899 * at the same time as they share the same backend.
900 */
901 /* Disable all the usecases on the shared backend other than the
902 specified usecase */
903 for (i = 0; i < AUDIO_USECASE_MAX; i++)
904 switch_device[i] = false;
905
906 list_for_each(node, &adev->usecase_list) {
907 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700908 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
909 continue;
910
911 if (force_routing ||
912 (usecase->out_snd_device != snd_device &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -0700913 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
914 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700915 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700916 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
917 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700918 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700919 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700920 switch_device[usecase->id] = true;
921 num_uc_to_switch++;
922 }
923 }
924
925 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700926 list_for_each(node, &adev->usecase_list) {
927 usecase = node_to_item(node, struct audio_usecase, list);
928 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700929 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900930 }
931 }
932
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700933 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900934 list_for_each(node, &adev->usecase_list) {
935 usecase = node_to_item(node, struct audio_usecase, list);
936 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700937 d_device = derive_playback_snd_device(usecase, uc_info,
938 snd_device);
939 enable_snd_device(adev, d_device);
940 /* Update the out_snd_device before enabling the audio route */
941 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700942 }
943 }
944
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700945 /* Re-route all the usecases on the shared backend other than the
946 specified usecase to new snd devices */
947 list_for_each(node, &adev->usecase_list) {
948 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700949 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700950 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700951 }
952 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700953 }
954}
955
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700956static void check_and_route_capture_usecases(struct audio_device *adev,
957 struct audio_usecase *uc_info,
958 snd_device_t snd_device)
959{
960 struct listnode *node;
961 struct audio_usecase *usecase;
962 bool switch_device[AUDIO_USECASE_MAX];
963 int i, num_uc_to_switch = 0;
964
vivek mehta4ed66e62016-04-15 23:33:34 -0700965 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
966
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700967 /*
968 * This function is to make sure that all the active capture usecases
969 * are always routed to the same input sound device.
970 * For example, if audio-record and voice-call usecases are currently
971 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
972 * is received for voice call then we have to make sure that audio-record
973 * usecase is also switched to earpiece i.e. voice-dmic-ef,
974 * because of the limitation that two devices cannot be enabled
975 * at the same time if they share the same backend.
976 */
977 for (i = 0; i < AUDIO_USECASE_MAX; i++)
978 switch_device[i] = false;
979
980 list_for_each(node, &adev->usecase_list) {
981 usecase = node_to_item(node, struct audio_usecase, list);
982 if (usecase->type != PCM_PLAYBACK &&
983 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700984 usecase->in_snd_device != snd_device &&
985 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700986 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
987 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700988 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700989 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700990 switch_device[usecase->id] = true;
991 num_uc_to_switch++;
992 }
993 }
994
995 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700996 list_for_each(node, &adev->usecase_list) {
997 usecase = node_to_item(node, struct audio_usecase, list);
998 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700999 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001000 }
1001 }
1002
1003 list_for_each(node, &adev->usecase_list) {
1004 usecase = node_to_item(node, struct audio_usecase, list);
1005 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001006 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001007 }
1008 }
1009
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001010 /* Re-route all the usecases on the shared backend other than the
1011 specified usecase to new snd devices */
1012 list_for_each(node, &adev->usecase_list) {
1013 usecase = node_to_item(node, struct audio_usecase, list);
1014 /* Update the in_snd_device only before enabling the audio route */
1015 if (switch_device[usecase->id] ) {
1016 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001017 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001018 }
1019 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001020 }
1021}
1022
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001023/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001024static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001025{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001026 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001027 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001028
1029 switch (channels) {
1030 /*
1031 * Do not handle stereo output in Multi-channel cases
1032 * Stereo case is handled in normal playback path
1033 */
1034 case 6:
1035 ALOGV("%s: HDMI supports 5.1", __func__);
1036 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1037 break;
1038 case 8:
1039 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
1040 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1041 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
1042 break;
1043 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001044 ALOGE("HDMI does not support multi channel playback");
1045 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001046 break;
1047 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001048 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001049}
1050
Andy Hung18859412017-08-09 11:47:21 -07001051static ssize_t read_usb_sup_sample_rates(bool is_playback,
1052 uint32_t *supported_sample_rates,
1053 uint32_t max_rates)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001054{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001055 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1056 supported_sample_rates,
1057 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001058#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001059 for (ssize_t i=0; i<count; i++) {
1060 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1061 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001062 }
1063#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001064 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001065}
1066
Haynes Mathew George569b7482017-05-08 14:44:27 -07001067static int read_usb_sup_channel_masks(bool is_playback,
1068 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001069 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001070{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001071 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001072 int channel_count;
1073 uint32_t num_masks = 0;
1074 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1075 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001076 }
Eric Laurent74b55762017-07-09 17:04:53 -07001077 if (is_playback) {
Andy Hung6c1afb12017-12-22 11:34:41 -08001078 // start from 2 channels as framework currently doesn't support mono.
1079 // TODO: consider only supporting channel index masks beyond stereo here.
1080 for (channel_count = FCC_2;
1081 channel_count <= channels && num_masks < max_masks;
1082 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001083 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1084 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001085 for (channel_count = FCC_2;
1086 channel_count <= channels && num_masks < max_masks;
1087 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001088 supported_channel_masks[num_masks++] =
1089 audio_channel_mask_for_index_assignment_from_count(channel_count);
1090 }
1091 } else {
1092 // For capture we report all supported channel masks from 1 channel up.
1093 channel_count = MIN_CHANNEL_COUNT;
1094 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1095 // indexed mask
1096 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1097 supported_channel_masks[num_masks++] =
1098 audio_channel_in_mask_from_count(channel_count);
1099 }
1100 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001101#ifdef NDEBUG
1102 for (size_t i = 0; i < num_masks; ++i) {
1103 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1104 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
1105 }
1106#endif
Eric Laurent74b55762017-07-09 17:04:53 -07001107 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001108}
1109
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001110static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001111 audio_format_t *supported_formats,
1112 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001113{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001114 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001115 switch (bitwidth) {
1116 case 24:
1117 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001118 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001119 break;
1120 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001121 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001122 break;
1123 case 16:
1124 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001125 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001126 break;
1127 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001128 ALOGV("%s: %s supported format %d", __func__,
1129 is_playback ? "P" : "C", bitwidth);
1130 return 1;
1131}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001132
Haynes Mathew George569b7482017-05-08 14:44:27 -07001133static int read_usb_sup_params_and_compare(bool is_playback,
1134 audio_format_t *format,
1135 audio_format_t *supported_formats,
1136 uint32_t max_formats,
1137 audio_channel_mask_t *mask,
1138 audio_channel_mask_t *supported_channel_masks,
1139 uint32_t max_masks,
1140 uint32_t *rate,
1141 uint32_t *supported_sample_rates,
1142 uint32_t max_rates) {
1143 int ret = 0;
1144 int num_formats;
1145 int num_masks;
1146 int num_rates;
1147 int i;
1148
1149 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1150 max_formats);
1151 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1152 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001153
Haynes Mathew George569b7482017-05-08 14:44:27 -07001154 num_rates = read_usb_sup_sample_rates(is_playback,
1155 supported_sample_rates, max_rates);
1156
1157#define LUT(table, len, what, dflt) \
1158 for (i=0; i<len && (table[i] != what); i++); \
1159 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1160
1161 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1162 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1163 LUT(supported_sample_rates, num_rates, *rate, 0);
1164
1165#undef LUT
1166 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001167}
1168
Andy Hungd9653bd2017-08-01 19:31:39 -07001169static bool is_usb_ready(struct audio_device *adev, bool is_playback)
1170{
1171 // Check if usb is ready.
1172 // The usb device may have been removed quickly after insertion and hence
1173 // no longer available. This will show up as empty channel masks, or rates.
1174
1175 pthread_mutex_lock(&adev->lock);
1176 uint32_t supported_sample_rate;
1177
1178 // we consider usb ready if we can fetch at least one sample rate.
1179 const bool ready = read_usb_sup_sample_rates(
1180 is_playback, &supported_sample_rate, 1 /* max_rates */) > 0;
1181 pthread_mutex_unlock(&adev->lock);
1182 return ready;
1183}
1184
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001185static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1186{
1187 struct audio_usecase *usecase;
1188 struct listnode *node;
1189
1190 list_for_each(node, &adev->usecase_list) {
1191 usecase = node_to_item(node, struct audio_usecase, list);
1192 if (usecase->type == VOICE_CALL) {
1193 ALOGV("%s: usecase id %d", __func__, usecase->id);
1194 return usecase->id;
1195 }
1196 }
1197 return USECASE_INVALID;
1198}
1199
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001200struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1201 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001202{
1203 struct audio_usecase *usecase;
1204 struct listnode *node;
1205
1206 list_for_each(node, &adev->usecase_list) {
1207 usecase = node_to_item(node, struct audio_usecase, list);
1208 if (usecase->id == uc_id)
1209 return usecase;
1210 }
1211 return NULL;
1212}
1213
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001214static bool force_device_switch(struct audio_usecase *usecase)
1215{
1216 if (usecase->stream.out == NULL) {
1217 ALOGE("%s: stream.out is NULL", __func__);
1218 return false;
1219 }
1220
1221 // Force all A2DP output devices to reconfigure for proper AFE encode format
1222 // Also handle a case where in earlier A2DP start failed as A2DP stream was
1223 // in suspended state, hence try to trigger a retry when we again get a routing request.
1224 if ((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
1225 audio_extn_a2dp_is_force_device_switch()) {
1226 ALOGD("%s: Force A2DP device switch to update new encoder config", __func__);
1227 return true;
1228 }
1229
1230 return false;
1231}
1232
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001233int select_devices(struct audio_device *adev,
1234 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001235{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001236 snd_device_t out_snd_device = SND_DEVICE_NONE;
1237 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001238 struct audio_usecase *usecase = NULL;
1239 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001240 struct audio_usecase *hfp_usecase = NULL;
1241 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001242 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001243 int status = 0;
Eric Laurentf4520b02017-09-20 18:31:58 -07001244 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1245 USECASE_AUDIO_PLAYBACK_VOIP);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001246
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001247 usecase = get_usecase_from_list(adev, uc_id);
1248 if (usecase == NULL) {
1249 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1250 return -EINVAL;
1251 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001252
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001253 if ((usecase->type == VOICE_CALL) ||
1254 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001255 out_snd_device = platform_get_output_snd_device(adev->platform,
1256 usecase->stream.out->devices);
1257 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001258 usecase->devices = usecase->stream.out->devices;
1259 } else {
1260 /*
1261 * If the voice call is active, use the sound devices of voice call usecase
1262 * so that it would not result any device switch. All the usecases will
1263 * be switched to new device when select_devices() is called for voice call
1264 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001265 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001266 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001267 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001268 vc_usecase = get_usecase_from_list(adev,
1269 get_voice_usecase_id_from_list(adev));
1270 if ((vc_usecase != NULL) &&
1271 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1272 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001273 in_snd_device = vc_usecase->in_snd_device;
1274 out_snd_device = vc_usecase->out_snd_device;
1275 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001276 } else if (audio_extn_hfp_is_active(adev)) {
1277 hfp_ucid = audio_extn_hfp_get_usecase();
1278 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1279 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1280 in_snd_device = hfp_usecase->in_snd_device;
1281 out_snd_device = hfp_usecase->out_snd_device;
1282 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001283 }
1284 if (usecase->type == PCM_PLAYBACK) {
1285 usecase->devices = usecase->stream.out->devices;
1286 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001287 if (out_snd_device == SND_DEVICE_NONE) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001288 struct stream_out *voip_out = adev->primary_output;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001289
Eric Laurentb23d5282013-05-14 15:27:20 -07001290 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001291 usecase->stream.out->devices);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001292
1293 if (voip_usecase)
1294 voip_out = voip_usecase->stream.out;
1295
1296 if (usecase->stream.out == voip_out &&
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001297 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001298 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001299 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001300 select_devices(adev, adev->active_input->usecase);
1301 }
1302 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001303 } else if (usecase->type == PCM_CAPTURE) {
1304 usecase->devices = usecase->stream.in->device;
1305 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001306 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001307 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001308 if (adev->active_input &&
1309 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1310 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001311
1312 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1313 USECASE_AUDIO_PLAYBACK_VOIP);
1314
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001315 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001316 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1317 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001318 } else if (voip_usecase) {
1319 out_device = voip_usecase->stream.out->devices;
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001320 } else if (adev->primary_output) {
1321 out_device = adev->primary_output->devices;
1322 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001323 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001324 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001325 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001326 }
1327 }
1328
1329 if (out_snd_device == usecase->out_snd_device &&
1330 in_snd_device == usecase->in_snd_device) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001331 if (!force_device_switch(usecase))
1332 return 0;
1333 }
1334
1335 if (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready()) {
1336 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1337 return 0;
1338 }
1339
1340 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP) &&
1341 (!audio_extn_a2dp_is_ready())) {
1342 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
1343 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001344 }
1345
Eric Laurent2bafff12016-03-17 12:17:23 -07001346 if (out_snd_device != SND_DEVICE_NONE &&
1347 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1348 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1349 __func__,
1350 use_case_table[uc_id],
1351 adev->last_logged_snd_device[uc_id][0],
1352 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1353 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1354 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1355 -1,
1356 out_snd_device,
1357 platform_get_snd_device_name(out_snd_device),
1358 platform_get_snd_device_acdb_id(out_snd_device));
1359 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1360 }
1361 if (in_snd_device != SND_DEVICE_NONE &&
1362 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1363 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1364 __func__,
1365 use_case_table[uc_id],
1366 adev->last_logged_snd_device[uc_id][1],
1367 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1368 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1369 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1370 -1,
1371 in_snd_device,
1372 platform_get_snd_device_name(in_snd_device),
1373 platform_get_snd_device_acdb_id(in_snd_device));
1374 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1375 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001376
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001377 /*
1378 * Limitation: While in call, to do a device switch we need to disable
1379 * and enable both RX and TX devices though one of them is same as current
1380 * device.
1381 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001382 if ((usecase->type == VOICE_CALL) &&
1383 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1384 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001385 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001386 /* Disable sidetone only if voice call already exists */
1387 if (voice_is_call_state_active(adev))
1388 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001389 }
1390
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001391 /* Disable current sound devices */
1392 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001393 disable_audio_route(adev, usecase);
1394 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001395 }
1396
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001397 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001398 disable_audio_route(adev, usecase);
1399 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001400 }
1401
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001402 /* Applicable only on the targets that has external modem.
1403 * New device information should be sent to modem before enabling
1404 * the devices to reduce in-call device switch time.
1405 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001406 if ((usecase->type == VOICE_CALL) &&
1407 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1408 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001409 status = platform_switch_voice_call_enable_device_config(adev->platform,
1410 out_snd_device,
1411 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001412 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001413
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001414 /* Enable new sound devices */
1415 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001416 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001417 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) ||
1418 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001419 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001420 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001421 }
1422
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001423 if (in_snd_device != SND_DEVICE_NONE) {
1424 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001425 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001426 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001427
Eric Laurentb23d5282013-05-14 15:27:20 -07001428 if (usecase->type == VOICE_CALL)
1429 status = platform_switch_voice_call_device_post(adev->platform,
1430 out_snd_device,
1431 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001432
sangwoo170731f2013-06-08 15:36:36 +09001433 usecase->in_snd_device = in_snd_device;
1434 usecase->out_snd_device = out_snd_device;
1435
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001436 audio_extn_tfa_98xx_set_mode();
1437
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001438 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001439
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001440 /* Applicable only on the targets that has external modem.
1441 * Enable device command should be sent to modem only after
1442 * enabling voice call mixer controls
1443 */
vivek mehta765eb642015-08-07 19:46:06 -07001444 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001445 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1446 out_snd_device,
1447 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001448 /* Enable sidetone only if voice call already exists */
1449 if (voice_is_call_state_active(adev))
1450 voice_set_sidetone(adev, out_snd_device, true);
1451 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001452
Eric Laurentf4520b02017-09-20 18:31:58 -07001453 if (usecase == voip_usecase) {
1454 struct stream_out *voip_out = voip_usecase->stream.out;
1455 audio_extn_utils_send_app_type_gain(adev,
1456 voip_out->app_type_cfg.app_type,
1457 &voip_out->app_type_cfg.gain[0]);
1458 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001459 return status;
1460}
1461
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001462static int stop_input_stream(struct stream_in *in)
1463{
1464 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001465 struct audio_usecase *uc_info;
1466 struct audio_device *adev = in->dev;
1467
Eric Laurent994a6932013-07-17 11:51:42 -07001468 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001469 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001470
1471 if (adev->active_input) {
1472 if (adev->active_input->usecase == in->usecase) {
1473 adev->active_input = NULL;
1474 } else {
1475 ALOGW("%s adev->active_input->usecase %s, v/s in->usecase %s",
1476 __func__,
1477 use_case_table[adev->active_input->usecase],
1478 use_case_table[in->usecase]);
1479 }
1480 }
1481
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001482 uc_info = get_usecase_from_list(adev, in->usecase);
1483 if (uc_info == NULL) {
1484 ALOGE("%s: Could not find the usecase (%d) in the list",
1485 __func__, in->usecase);
1486 return -EINVAL;
1487 }
1488
vivek mehta781065c2017-04-04 12:55:01 -07001489 /* Close in-call recording streams */
1490 voice_check_and_stop_incall_rec_usecase(adev, in);
1491
Eric Laurent150dbfe2013-02-27 14:31:02 -08001492 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001493 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001494
1495 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001496 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001497
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001498 list_remove(&uc_info->list);
1499 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001500
Eric Laurent994a6932013-07-17 11:51:42 -07001501 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001502 return ret;
1503}
1504
1505int start_input_stream(struct stream_in *in)
1506{
1507 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001508 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001509 struct audio_usecase *uc_info;
1510 struct audio_device *adev = in->dev;
1511
Eric Laurent994a6932013-07-17 11:51:42 -07001512 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001513
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001514 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1515 return -EIO;
1516
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001517 if (in->card_status == CARD_STATUS_OFFLINE ||
1518 adev->card_status == CARD_STATUS_OFFLINE) {
1519 ALOGW("in->card_status or adev->card_status offline, try again");
1520 ret = -EAGAIN;
1521 goto error_config;
1522 }
1523
vivek mehta781065c2017-04-04 12:55:01 -07001524 /* Check if source matches incall recording usecase criteria */
1525 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1526 if (ret)
1527 goto error_config;
1528 else
1529 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1530
Eric Laurentb23d5282013-05-14 15:27:20 -07001531 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001532 if (in->pcm_device_id < 0) {
1533 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1534 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001535 ret = -EINVAL;
1536 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001537 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001538
1539 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001540 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1541 uc_info->id = in->usecase;
1542 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001543 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001544 uc_info->devices = in->device;
1545 uc_info->in_snd_device = SND_DEVICE_NONE;
1546 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001547
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001548 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001549
Wei Wangf4837d52017-11-21 14:51:20 -08001550 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001551 audio_extn_perf_lock_acquire();
1552
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001553 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001554
Eric Laurent0e46adf2016-12-16 12:49:24 -08001555 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001556 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001557 ALOGE("%s: pcm stream not ready", __func__);
1558 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001559 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001560 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001561 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001562 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1563 goto error_open;
1564 }
1565 } else {
1566 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1567 unsigned int pcm_open_retry_count = 0;
1568
1569 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1570 flags |= PCM_MMAP | PCM_NOIRQ;
1571 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1572 } else if (in->realtime) {
1573 flags |= PCM_MMAP | PCM_NOIRQ;
1574 }
1575
1576 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1577 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1578
1579 while (1) {
1580 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1581 flags, &in->config);
1582 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1583 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1584 if (in->pcm != NULL) {
1585 pcm_close(in->pcm);
1586 in->pcm = NULL;
1587 }
1588 if (pcm_open_retry_count-- == 0) {
1589 ret = -EIO;
1590 goto error_open;
1591 }
1592 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1593 continue;
1594 }
1595 break;
1596 }
1597
1598 ALOGV("%s: pcm_prepare", __func__);
1599 ret = pcm_prepare(in->pcm);
1600 if (ret < 0) {
1601 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001602 pcm_close(in->pcm);
1603 in->pcm = NULL;
1604 goto error_open;
1605 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001606 if (in->realtime) {
1607 ret = pcm_start(in->pcm);
1608 if (ret < 0) {
1609 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1610 pcm_close(in->pcm);
1611 in->pcm = NULL;
1612 goto error_open;
1613 }
1614 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001615 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001616 register_in_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001617 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001618 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001619 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001620
Eric Laurent0e46adf2016-12-16 12:49:24 -08001621 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001622
1623error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001624 stop_input_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001625 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001626 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001627
1628error_config:
1629 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001630 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001631 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001632}
1633
Eric Laurenta1478072015-09-21 17:21:52 -07001634void lock_input_stream(struct stream_in *in)
1635{
1636 pthread_mutex_lock(&in->pre_lock);
1637 pthread_mutex_lock(&in->lock);
1638 pthread_mutex_unlock(&in->pre_lock);
1639}
1640
1641void lock_output_stream(struct stream_out *out)
1642{
1643 pthread_mutex_lock(&out->pre_lock);
1644 pthread_mutex_lock(&out->lock);
1645 pthread_mutex_unlock(&out->pre_lock);
1646}
1647
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001648/* must be called with out->lock locked */
1649static int send_offload_cmd_l(struct stream_out* out, int command)
1650{
1651 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1652
1653 ALOGVV("%s %d", __func__, command);
1654
1655 cmd->cmd = command;
1656 list_add_tail(&out->offload_cmd_list, &cmd->node);
1657 pthread_cond_signal(&out->offload_cond);
1658 return 0;
1659}
1660
1661/* must be called iwth out->lock locked */
1662static void stop_compressed_output_l(struct stream_out *out)
1663{
1664 out->offload_state = OFFLOAD_STATE_IDLE;
1665 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001666 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001667 if (out->compr != NULL) {
1668 compress_stop(out->compr);
1669 while (out->offload_thread_blocked) {
1670 pthread_cond_wait(&out->cond, &out->lock);
1671 }
1672 }
1673}
1674
1675static void *offload_thread_loop(void *context)
1676{
1677 struct stream_out *out = (struct stream_out *) context;
1678 struct listnode *item;
1679
1680 out->offload_state = OFFLOAD_STATE_IDLE;
1681 out->playback_started = 0;
1682
1683 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1684 set_sched_policy(0, SP_FOREGROUND);
1685 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1686
1687 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001688 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001689 for (;;) {
1690 struct offload_cmd *cmd = NULL;
1691 stream_callback_event_t event;
1692 bool send_callback = false;
1693
1694 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1695 __func__, list_empty(&out->offload_cmd_list),
1696 out->offload_state);
1697 if (list_empty(&out->offload_cmd_list)) {
1698 ALOGV("%s SLEEPING", __func__);
1699 pthread_cond_wait(&out->offload_cond, &out->lock);
1700 ALOGV("%s RUNNING", __func__);
1701 continue;
1702 }
1703
1704 item = list_head(&out->offload_cmd_list);
1705 cmd = node_to_item(item, struct offload_cmd, node);
1706 list_remove(item);
1707
1708 ALOGVV("%s STATE %d CMD %d out->compr %p",
1709 __func__, out->offload_state, cmd->cmd, out->compr);
1710
1711 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1712 free(cmd);
1713 break;
1714 }
1715
1716 if (out->compr == NULL) {
1717 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001718 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001719 pthread_cond_signal(&out->cond);
1720 continue;
1721 }
1722 out->offload_thread_blocked = true;
1723 pthread_mutex_unlock(&out->lock);
1724 send_callback = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001725 switch (cmd->cmd) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001726 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1727 compress_wait(out->compr, -1);
1728 send_callback = true;
1729 event = STREAM_CBK_EVENT_WRITE_READY;
1730 break;
1731 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001732 compress_next_track(out->compr);
1733 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001734 send_callback = true;
1735 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001736 /* Resend the metadata for next iteration */
1737 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001738 break;
1739 case OFFLOAD_CMD_DRAIN:
1740 compress_drain(out->compr);
1741 send_callback = true;
1742 event = STREAM_CBK_EVENT_DRAIN_READY;
1743 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001744 case OFFLOAD_CMD_ERROR:
1745 send_callback = true;
1746 event = STREAM_CBK_EVENT_ERROR;
1747 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001748 default:
1749 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1750 break;
1751 }
Eric Laurenta1478072015-09-21 17:21:52 -07001752 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001753 out->offload_thread_blocked = false;
1754 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001755 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001756 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001757 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001758 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001759 free(cmd);
1760 }
1761
1762 pthread_cond_signal(&out->cond);
1763 while (!list_empty(&out->offload_cmd_list)) {
1764 item = list_head(&out->offload_cmd_list);
1765 list_remove(item);
1766 free(node_to_item(item, struct offload_cmd, node));
1767 }
1768 pthread_mutex_unlock(&out->lock);
1769
1770 return NULL;
1771}
1772
1773static int create_offload_callback_thread(struct stream_out *out)
1774{
1775 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1776 list_init(&out->offload_cmd_list);
1777 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1778 offload_thread_loop, out);
1779 return 0;
1780}
1781
1782static int destroy_offload_callback_thread(struct stream_out *out)
1783{
Eric Laurenta1478072015-09-21 17:21:52 -07001784 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001785 stop_compressed_output_l(out);
1786 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1787
1788 pthread_mutex_unlock(&out->lock);
1789 pthread_join(out->offload_thread, (void **) NULL);
1790 pthread_cond_destroy(&out->offload_cond);
1791
1792 return 0;
1793}
1794
Eric Laurent07eeafd2013-10-06 12:52:49 -07001795static bool allow_hdmi_channel_config(struct audio_device *adev)
1796{
1797 struct listnode *node;
1798 struct audio_usecase *usecase;
1799 bool ret = true;
1800
1801 list_for_each(node, &adev->usecase_list) {
1802 usecase = node_to_item(node, struct audio_usecase, list);
1803 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1804 /*
1805 * If voice call is already existing, do not proceed further to avoid
1806 * disabling/enabling both RX and TX devices, CSD calls, etc.
1807 * Once the voice call done, the HDMI channels can be configured to
1808 * max channels of remaining use cases.
1809 */
1810 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001811 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001812 __func__);
1813 ret = false;
1814 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001815 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1816 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001817 "no change in HDMI channels", __func__);
1818 ret = false;
1819 break;
1820 }
1821 }
1822 }
1823 return ret;
1824}
1825
1826static int check_and_set_hdmi_channels(struct audio_device *adev,
1827 unsigned int channels)
1828{
1829 struct listnode *node;
1830 struct audio_usecase *usecase;
1831
1832 /* Check if change in HDMI channel config is allowed */
1833 if (!allow_hdmi_channel_config(adev))
1834 return 0;
1835
1836 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001837 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001838 return 0;
1839 }
1840
1841 platform_set_hdmi_channels(adev->platform, channels);
1842 adev->cur_hdmi_channels = channels;
1843
1844 /*
1845 * Deroute all the playback streams routed to HDMI so that
1846 * the back end is deactivated. Note that backend will not
1847 * be deactivated if any one stream is connected to it.
1848 */
1849 list_for_each(node, &adev->usecase_list) {
1850 usecase = node_to_item(node, struct audio_usecase, list);
1851 if (usecase->type == PCM_PLAYBACK &&
1852 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001853 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001854 }
1855 }
1856
1857 /*
1858 * Enable all the streams disabled above. Now the HDMI backend
1859 * will be activated with new channel configuration
1860 */
1861 list_for_each(node, &adev->usecase_list) {
1862 usecase = node_to_item(node, struct audio_usecase, list);
1863 if (usecase->type == PCM_PLAYBACK &&
1864 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001865 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001866 }
1867 }
1868
1869 return 0;
1870}
1871
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001872static int stop_output_stream(struct stream_out *out)
1873{
1874 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001875 struct audio_usecase *uc_info;
1876 struct audio_device *adev = out->dev;
1877
Eric Laurent994a6932013-07-17 11:51:42 -07001878 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001879 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001880 uc_info = get_usecase_from_list(adev, out->usecase);
1881 if (uc_info == NULL) {
1882 ALOGE("%s: Could not find the usecase (%d) in the list",
1883 __func__, out->usecase);
1884 return -EINVAL;
1885 }
1886
Haynes Mathew George41f86652014-06-17 14:22:15 -07001887 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1888 if (adev->visualizer_stop_output != NULL)
1889 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1890 if (adev->offload_effects_stop_output != NULL)
1891 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08001892 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
1893 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
1894 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07001895 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001896
Eric Laurent150dbfe2013-02-27 14:31:02 -08001897 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001898 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001899
1900 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001901 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001902
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001903 list_remove(&uc_info->list);
1904 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001905
Eric Laurent0499d4f2014-08-25 22:39:29 -05001906 audio_extn_extspk_update(adev->extspk);
1907
Eric Laurent07eeafd2013-10-06 12:52:49 -07001908 /* Must be called after removing the usecase from list */
1909 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1910 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07001911 else if (out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
1912 struct listnode *node;
1913 struct audio_usecase *usecase;
1914 list_for_each(node, &adev->usecase_list) {
1915 usecase = node_to_item(node, struct audio_usecase, list);
1916 if (usecase->devices & AUDIO_DEVICE_OUT_SPEAKER)
1917 select_devices(adev, usecase->id);
1918 }
1919 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001920
Eric Laurent994a6932013-07-17 11:51:42 -07001921 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001922 return ret;
1923}
1924
1925int start_output_stream(struct stream_out *out)
1926{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001927 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001928 struct audio_usecase *uc_info;
1929 struct audio_device *adev = out->dev;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001930 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001931
Eric Laurent994a6932013-07-17 11:51:42 -07001932 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001933 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001934
1935 if (out->card_status == CARD_STATUS_OFFLINE ||
1936 adev->card_status == CARD_STATUS_OFFLINE) {
1937 ALOGW("out->card_status or adev->card_status offline, try again");
1938 ret = -EAGAIN;
1939 goto error_config;
1940 }
1941
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001942 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
1943 if (!audio_extn_a2dp_is_ready()) {
1944 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
1945 a2dp_combo = true;
1946 } else {
1947 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
1948 ALOGE("%s: A2DP profile is not ready, return error", __func__);
1949 ret = -EAGAIN;
1950 goto error_config;
1951 }
1952 }
1953 }
1954 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001955 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001956 if (out->pcm_device_id < 0) {
1957 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1958 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001959 ret = -EINVAL;
1960 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001961 }
1962
1963 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1964 uc_info->id = out->usecase;
1965 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001966 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001967 uc_info->devices = out->devices;
1968 uc_info->in_snd_device = SND_DEVICE_NONE;
1969 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001970
Eric Laurent07eeafd2013-10-06 12:52:49 -07001971 /* This must be called before adding this usecase to the list */
1972 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1973 check_and_set_hdmi_channels(adev, out->config.channels);
1974
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001975 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001976
Wei Wangf4837d52017-11-21 14:51:20 -08001977 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001978 audio_extn_perf_lock_acquire();
1979
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001980 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
1981 (!audio_extn_a2dp_is_ready())) {
1982 if (!a2dp_combo) {
1983 check_a2dp_restore_l(adev, out, false);
1984 } else {
1985 audio_devices_t dev = out->devices;
1986 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
1987 select_devices(adev, out->usecase);
1988 out->devices = dev;
1989 }
1990 } else {
1991 select_devices(adev, out->usecase);
1992 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001993
Eric Laurent0499d4f2014-08-25 22:39:29 -05001994 audio_extn_extspk_update(adev->extspk);
1995
Andy Hung31aca912014-03-20 17:14:59 -07001996 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001997 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001998 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1999 out->pcm = NULL;
2000 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
2001 COMPRESS_IN, &out->compr_config);
2002 if (out->compr && !is_compress_ready(out->compr)) {
2003 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2004 compress_close(out->compr);
2005 out->compr = NULL;
2006 ret = -EIO;
2007 goto error_open;
2008 }
2009 if (out->offload_callback)
2010 compress_nonblock(out->compr, out->non_blocking);
2011
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07002012 if (adev->visualizer_start_output != NULL) {
2013 int capture_device_id =
2014 platform_get_pcm_device_id(USECASE_AUDIO_RECORD_AFE_PROXY,
2015 PCM_CAPTURE);
2016 adev->visualizer_start_output(out->handle, out->pcm_device_id,
2017 adev->snd_card, capture_device_id);
2018 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002019 if (adev->offload_effects_start_output != NULL)
2020 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
2021 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002022 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002023 ALOGE("%s: pcm stream not ready", __func__);
2024 goto error_open;
2025 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002026 ret = pcm_start(out->pcm);
2027 if (ret < 0) {
2028 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2029 goto error_open;
2030 }
2031 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07002032 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002033 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002034
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002035 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2036 flags |= PCM_MMAP | PCM_NOIRQ;
2037 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002038 } else if (out->realtime) {
2039 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07002040 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002041
2042 while (1) {
2043 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2044 flags, &out->config);
2045 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2046 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2047 if (out->pcm != NULL) {
2048 pcm_close(out->pcm);
2049 out->pcm = NULL;
2050 }
2051 if (pcm_open_retry_count-- == 0) {
2052 ret = -EIO;
2053 goto error_open;
2054 }
2055 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2056 continue;
2057 }
2058 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002059 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002060 ALOGV("%s: pcm_prepare", __func__);
2061 if (pcm_is_ready(out->pcm)) {
2062 ret = pcm_prepare(out->pcm);
2063 if (ret < 0) {
2064 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2065 pcm_close(out->pcm);
2066 out->pcm = NULL;
2067 goto error_open;
2068 }
2069 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002070 if (out->realtime) {
2071 ret = pcm_start(out->pcm);
2072 if (ret < 0) {
2073 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
2074 pcm_close(out->pcm);
2075 out->pcm = NULL;
2076 goto error_open;
2077 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002078 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002079 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002080 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08002081 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002082 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002083 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07002084
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002085 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2086 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2087 audio_low_latency_hint_start();
2088 }
2089
vivek mehtae59cfb22017-06-16 15:57:11 -07002090 // consider a scenario where on pause lower layers are tear down.
2091 // so on resume, swap mixer control need to be sent only when
2092 // backend is active, hence rather than sending from enable device
2093 // sending it from start of streamtream
2094
2095 platform_set_swap_channels(adev, true);
2096
Eric Laurent994a6932013-07-17 11:51:42 -07002097 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002098 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002099error_open:
Wei Wangf4837d52017-11-21 14:51:20 -08002100 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002101 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002102 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002103error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002104 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002105}
2106
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002107static int check_input_parameters(uint32_t sample_rate,
2108 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07002109 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002110{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002111 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2112 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002113 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2114 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002115 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2116 return -EINVAL;
2117 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002118
Eric Laurent74b55762017-07-09 17:04:53 -07002119 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2120 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002121 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002122 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002123 return -EINVAL;
2124 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002125
2126 switch (sample_rate) {
2127 case 8000:
2128 case 11025:
2129 case 12000:
2130 case 16000:
2131 case 22050:
2132 case 24000:
2133 case 32000:
2134 case 44100:
2135 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002136 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002137 break;
2138 default:
vivek mehtadae44712015-07-27 14:13:18 -07002139 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002140 return -EINVAL;
2141 }
2142
2143 return 0;
2144}
2145
Kevin Rocarda325aa22018-04-03 09:15:52 -07002146/** Add a value in a list if not already present.
2147 * @return true if value was successfully inserted or already present,
2148 * false if the list is full and does not contain the value.
2149 */
2150static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
2151 for (size_t i = 0; i < list_length; i++) {
2152 if (list[i] == value) return true; // value is already present
2153 if (list[i] == 0) { // no values in this slot
2154 list[i] = value;
2155 return true; // value inserted
2156 }
2157 }
2158 return false; // could not insert value
2159}
2160
2161/** Add channel_mask in supported_channel_masks if not already present.
2162 * @return true if channel_mask was successfully inserted or already present,
2163 * false if supported_channel_masks is full and does not contain channel_mask.
2164 */
2165static void register_channel_mask(audio_channel_mask_t channel_mask,
2166 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
2167 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
2168 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
2169}
2170
2171/** Add format in supported_formats if not already present.
2172 * @return true if format was successfully inserted or already present,
2173 * false if supported_formats is full and does not contain format.
2174 */
2175static void register_format(audio_format_t format,
2176 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
2177 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
2178 "%s: stream can not declare supporting its format %x", __func__, format);
2179}
2180/** Add sample_rate in supported_sample_rates if not already present.
2181 * @return true if sample_rate was successfully inserted or already present,
2182 * false if supported_sample_rates is full and does not contain sample_rate.
2183 */
2184static void register_sample_rate(uint32_t sample_rate,
2185 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
2186 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
2187 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
2188}
2189
vivek mehtaa68fea62017-06-08 19:04:02 -07002190static size_t get_stream_buffer_size(size_t duration_ms,
2191 uint32_t sample_rate,
2192 audio_format_t format,
2193 int channel_count,
2194 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002195{
2196 size_t size = 0;
2197
vivek mehtaa68fea62017-06-08 19:04:02 -07002198 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002199 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002200 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002201
2202 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002203
Glenn Kasten4f993392014-05-14 07:30:48 -07002204 /* make sure the size is multiple of 32 bytes
2205 * At 48 kHz mono 16-bit PCM:
2206 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2207 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2208 */
2209 size += 0x1f;
2210 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002211
2212 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002213}
2214
2215static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2216{
2217 struct stream_out *out = (struct stream_out *)stream;
2218
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002219 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002220}
2221
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002222static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002223{
2224 return -ENOSYS;
2225}
2226
2227static size_t out_get_buffer_size(const struct audio_stream *stream)
2228{
2229 struct stream_out *out = (struct stream_out *)stream;
2230
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002231 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2232 return out->compr_config.fragment_size;
2233 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002234 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002235 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002236}
2237
2238static uint32_t out_get_channels(const struct audio_stream *stream)
2239{
2240 struct stream_out *out = (struct stream_out *)stream;
2241
2242 return out->channel_mask;
2243}
2244
2245static audio_format_t out_get_format(const struct audio_stream *stream)
2246{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002247 struct stream_out *out = (struct stream_out *)stream;
2248
2249 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002250}
2251
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002252static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002253{
2254 return -ENOSYS;
2255}
2256
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002257/* must be called with out->lock locked */
2258static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002259{
2260 struct stream_out *out = (struct stream_out *)stream;
2261 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002262 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002263
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002264 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002265 if (adev->adm_deregister_stream)
2266 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002267 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002268 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002269 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2270 if (out->pcm) {
2271 pcm_close(out->pcm);
2272 out->pcm = NULL;
2273 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002274 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002275 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002276 out->playback_started = false;
2277 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002278 } else {
2279 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002280 out->gapless_mdata.encoder_delay = 0;
2281 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002282 if (out->compr != NULL) {
2283 compress_close(out->compr);
2284 out->compr = NULL;
2285 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002286 }
Phil Burkbc991042017-02-24 08:06:44 -08002287 if (do_stop) {
2288 stop_output_stream(out);
2289 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002290 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002291 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002292 return 0;
2293}
2294
2295static int out_standby(struct audio_stream *stream)
2296{
2297 struct stream_out *out = (struct stream_out *)stream;
2298
2299 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2300 out->usecase, use_case_table[out->usecase]);
2301
2302 lock_output_stream(out);
2303 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002304 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002305 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002306 return 0;
2307}
2308
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002309static int out_on_error(struct audio_stream *stream)
2310{
2311 struct stream_out *out = (struct stream_out *)stream;
2312 struct audio_device *adev = out->dev;
2313 bool do_standby = false;
2314
2315 lock_output_stream(out);
2316 if (!out->standby) {
2317 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2318 stop_compressed_output_l(out);
2319 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2320 } else
2321 do_standby = true;
2322 }
2323 pthread_mutex_unlock(&out->lock);
2324
2325 if (do_standby)
2326 return out_standby(&out->stream.common);
2327
2328 return 0;
2329}
2330
Andy Hung7401c7c2016-09-21 12:41:21 -07002331static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002332{
Andy Hung7401c7c2016-09-21 12:41:21 -07002333 struct stream_out *out = (struct stream_out *)stream;
2334
2335 // We try to get the lock for consistency,
2336 // but it isn't necessary for these variables.
2337 // If we're not in standby, we may be blocked on a write.
2338 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2339 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2340 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2341
2342 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002343 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002344 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002345
2346 // dump error info
2347 (void)error_log_dump(
2348 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002349
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002350 return 0;
2351}
2352
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002353static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2354{
2355 int ret = 0;
2356 char value[32];
2357 struct compr_gapless_mdata tmp_mdata;
2358
2359 if (!out || !parms) {
2360 return -EINVAL;
2361 }
2362
2363 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2364 if (ret >= 0) {
2365 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2366 } else {
2367 return -EINVAL;
2368 }
2369
2370 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2371 if (ret >= 0) {
2372 tmp_mdata.encoder_padding = atoi(value);
2373 } else {
2374 return -EINVAL;
2375 }
2376
2377 out->gapless_mdata = tmp_mdata;
2378 out->send_new_metadata = 1;
2379 ALOGV("%s new encoder delay %u and padding %u", __func__,
2380 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2381
2382 return 0;
2383}
2384
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002385static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2386{
2387 return out == adev->primary_output || out == adev->voice_tx_output;
2388}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002389
Kevin Rocard1e02c882017-08-09 15:26:07 -07002390static int get_alive_usb_card(struct str_parms* parms) {
2391 int card;
2392 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2393 !audio_extn_usb_alive(card)) {
2394 return card;
2395 }
2396 return -ENODEV;
2397}
2398
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002399static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2400{
2401 struct stream_out *out = (struct stream_out *)stream;
2402 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002403 struct audio_usecase *usecase;
2404 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002405 struct str_parms *parms;
2406 char value[32];
2407 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002408 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002409 int status = 0;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002410 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002411
Eric Laurent2e140aa2016-06-30 17:14:46 -07002412 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002413 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002414 parms = str_parms_create_str(kvpairs);
2415 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2416 if (ret >= 0) {
2417 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002418
Eric Laurenta1478072015-09-21 17:21:52 -07002419 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002420
2421 // The usb driver needs to be closed after usb device disconnection
2422 // otherwise audio is no longer played on the new usb devices.
2423 // By forcing the stream in standby, the usb stack refcount drops to 0
2424 // and the driver is closed.
2425 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD && val == AUDIO_DEVICE_NONE &&
2426 audio_is_usb_out_device(out->devices)) {
2427 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2428 out_standby_l(&out->stream.common);
2429 }
2430
Eric Laurent150dbfe2013-02-27 14:31:02 -08002431 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002432
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002433 /*
2434 * When HDMI cable is unplugged the music playback is paused and
2435 * the policy manager sends routing=0. But the audioflinger
2436 * continues to write data until standby time (3sec).
2437 * As the HDMI core is turned off, the write gets blocked.
2438 * Avoid this by routing audio to speaker until standby.
2439 */
2440 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2441 val == AUDIO_DEVICE_NONE) {
2442 val = AUDIO_DEVICE_OUT_SPEAKER;
2443 }
2444
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002445 /*
2446 * When A2DP is disconnected the
2447 * music playback is paused and the policy manager sends routing=0
2448 * But the audioflingercontinues to write data until standby time
2449 * (3sec). As BT is turned off, the write gets blocked.
2450 * Avoid this by routing audio to speaker until standby.
2451 */
2452 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2453 (val == AUDIO_DEVICE_NONE) &&
2454 !audio_extn_a2dp_is_ready()) {
2455 val = AUDIO_DEVICE_OUT_SPEAKER;
2456 }
2457
2458 /* To avoid a2dp to sco overlapping / BT device improper state
2459 * check with BT lib about a2dp streaming support before routing
2460 */
2461 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2462 if (!audio_extn_a2dp_is_ready()) {
2463 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
2464 //combo usecase just by pass a2dp
2465 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2466 bypass_a2dp = true;
2467 } else {
2468 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2469 /* update device to a2dp and don't route as BT returned error
2470 * However it is still possible a2dp routing called because
2471 * of current active device disconnection (like wired headset)
2472 */
2473 out->devices = val;
2474 pthread_mutex_unlock(&out->lock);
2475 pthread_mutex_unlock(&adev->lock);
2476 status = -ENOSYS;
2477 goto routing_fail;
2478 }
2479 }
2480 }
2481
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002482 audio_devices_t new_dev = val;
2483
2484 // Workaround: If routing to an non existing usb device, fail gracefully
2485 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002486 int card;
2487 if (audio_is_usb_out_device(new_dev) &&
2488 (card = get_alive_usb_card(parms)) >= 0) {
2489
2490 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002491 pthread_mutex_unlock(&adev->lock);
2492 pthread_mutex_unlock(&out->lock);
2493 status = -ENOSYS;
2494 goto routing_fail;
2495 }
2496
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002497 /*
2498 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002499 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002500 * the select_devices(). But how do we undo this?
2501 *
2502 * For example, music playback is active on headset (deep-buffer usecase)
2503 * and if we go to ringtones and select a ringtone, low-latency usecase
2504 * will be started on headset+speaker. As we can't enable headset+speaker
2505 * and headset devices at the same time, select_devices() switches the music
2506 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2507 * So when the ringtone playback is completed, how do we undo the same?
2508 *
2509 * We are relying on the out_set_parameters() call on deep-buffer output,
2510 * once the ringtone playback is ended.
2511 * NOTE: We should not check if the current devices are same as new devices.
2512 * Because select_devices() must be called to switch back the music
2513 * playback to headset.
2514 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002515 if (new_dev != AUDIO_DEVICE_NONE) {
2516 bool same_dev = out->devices == new_dev;
2517 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002518
Eric Laurenta7657192014-10-09 21:09:33 -07002519 if (output_drives_call(adev, out)) {
2520 if (!voice_is_in_call(adev)) {
2521 if (adev->mode == AUDIO_MODE_IN_CALL) {
2522 adev->current_call_output = out;
2523 ret = voice_start_call(adev);
2524 }
2525 } else {
2526 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002527 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002528 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002529 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002530
2531 if (!out->standby) {
2532 if (!same_dev) {
2533 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002534 // inform adm before actual routing to prevent glitches.
2535 if (adev->adm_on_routing_change) {
2536 adev->adm_on_routing_change(adev->adm_data,
2537 out->handle);
2538 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002539 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002540 if (!bypass_a2dp) {
2541 select_devices(adev, out->usecase);
2542 } else {
2543 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2544 select_devices(adev, out->usecase);
2545 out->devices = new_dev;
2546 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002547 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002548
2549 // on device switch force swap, lower functions will make sure
2550 // to check if swap is allowed or not.
2551
2552 if (!same_dev)
2553 platform_set_swap_channels(adev, true);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002554
2555 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2556 out->a2dp_compress_mute &&
2557 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
2558 pthread_mutex_lock(&out->compr_mute_lock);
2559 out->a2dp_compress_mute = false;
2560 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
2561 pthread_mutex_unlock(&out->compr_mute_lock);
2562 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002563 }
2564
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002565 }
2566
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002567 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002568 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002569
2570 /*handles device and call state changes*/
2571 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002572 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002573 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002574
2575 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2576 parse_compress_metadata(out, parms);
2577 }
2578
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002579 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002580 ALOGV("%s: exit: code(%d)", __func__, status);
2581 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002582}
2583
Haynes Mathew George569b7482017-05-08 14:44:27 -07002584static bool stream_get_parameter_channels(struct str_parms *query,
2585 struct str_parms *reply,
2586 audio_channel_mask_t *supported_channel_masks) {
2587 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002588 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002589 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002590 size_t i, j;
2591
2592 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2593 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002594 value[0] = '\0';
2595 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002596 while (supported_channel_masks[i] != 0) {
2597 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2598 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002599 if (!first) {
2600 strcat(value, "|");
2601 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002602 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002603 first = false;
2604 break;
2605 }
2606 }
2607 i++;
2608 }
2609 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002610 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002611 return ret >= 0;
2612}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002613
Haynes Mathew George569b7482017-05-08 14:44:27 -07002614static bool stream_get_parameter_formats(struct str_parms *query,
2615 struct str_parms *reply,
2616 audio_format_t *supported_formats) {
2617 int ret = -1;
2618 char value[256];
2619 int i;
2620
2621 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2622 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002623 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002624 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002625 case AUDIO_FORMAT_PCM_16_BIT:
2626 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2627 break;
2628 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2629 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2630 break;
2631 case AUDIO_FORMAT_PCM_32_BIT:
2632 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2633 break;
2634 default:
2635 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002636 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002637 break;
2638 }
2639 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002640 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002641 return ret >= 0;
2642}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002643
Haynes Mathew George569b7482017-05-08 14:44:27 -07002644static bool stream_get_parameter_rates(struct str_parms *query,
2645 struct str_parms *reply,
2646 uint32_t *supported_sample_rates) {
2647
2648 int i;
2649 char value[256];
2650 int ret = -1;
2651 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2652 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002653 value[0] = '\0';
2654 i=0;
2655 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002656 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002657 int avail = sizeof(value) - cursor;
2658 ret = snprintf(value + cursor, avail, "%s%d",
2659 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002660 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002661 if (ret < 0 || ret >= avail) {
2662 // if cursor is at the last element of the array
2663 // overwrite with \0 is duplicate work as
2664 // snprintf already put a \0 in place.
2665 // else
2666 // we had space to write the '|' at value[cursor]
2667 // (which will be overwritten) or no space to fill
2668 // the first element (=> cursor == 0)
2669 value[cursor] = '\0';
2670 break;
2671 }
2672 cursor += ret;
2673 ++i;
2674 }
2675 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2676 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002677 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002678 return ret >= 0;
2679}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002680
Haynes Mathew George569b7482017-05-08 14:44:27 -07002681static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2682{
2683 struct stream_out *out = (struct stream_out *)stream;
2684 struct str_parms *query = str_parms_create_str(keys);
2685 char *str;
2686 struct str_parms *reply = str_parms_create();
2687 bool replied = false;
2688 ALOGV("%s: enter: keys - %s", __func__, keys);
2689
2690 replied |= stream_get_parameter_channels(query, reply,
2691 &out->supported_channel_masks[0]);
2692 replied |= stream_get_parameter_formats(query, reply,
2693 &out->supported_formats[0]);
2694 replied |= stream_get_parameter_rates(query, reply,
2695 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002696 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002697 str = str_parms_to_str(reply);
2698 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002699 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002700 }
2701 str_parms_destroy(query);
2702 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002703 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002704 return str;
2705}
2706
2707static uint32_t out_get_latency(const struct audio_stream_out *stream)
2708{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002709 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002710 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002711 uint32_t latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002712
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002713 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2714 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002715 else if ((out->realtime) ||
2716 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002717 // since the buffer won't be filled up faster than realtime,
2718 // return a smaller number
2719 period_ms = (out->af_period_multiplier * out->config.period_size *
2720 1000) / (out->config.rate);
2721 hw_delay = platform_render_latency(out->usecase)/1000;
2722 return period_ms + hw_delay;
2723 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002724
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002725 latency = (out->config.period_count * out->config.period_size * 1000) /
2726 (out->config.rate);
2727
2728 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
2729 latency += audio_extn_a2dp_get_encoder_latency();
2730
2731 return latency;
2732}
2733
2734static int set_compr_volume(struct audio_stream_out *stream, float left,
2735 float right)
2736{
2737 struct stream_out *out = (struct stream_out *)stream;
2738 int volume[2];
2739 char mixer_ctl_name[128];
2740 struct audio_device *adev = out->dev;
2741 struct mixer_ctl *ctl;
2742 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2743 PCM_PLAYBACK);
2744
2745 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2746 "Compress Playback %d Volume", pcm_device_id);
2747 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2748 if (!ctl) {
2749 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2750 __func__, mixer_ctl_name);
2751 return -EINVAL;
2752 }
2753 ALOGV("%s: ctl for mixer cmd - %s, left %f, right %f",
2754 __func__, mixer_ctl_name, left, right);
2755 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2756 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2757 mixer_ctl_set_array(ctl, volume, sizeof(volume) / sizeof(volume[0]));
2758
2759 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002760}
2761
2762static int out_set_volume(struct audio_stream_out *stream, float left,
2763 float right)
2764{
Eric Laurenta9024de2013-04-04 09:19:12 -07002765 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002766 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002767
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002768 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002769 /* only take left channel into account: the API is for stereo anyway */
2770 out->muted = (left == 0.0f);
2771 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002772 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002773 pthread_mutex_lock(&out->compr_mute_lock);
2774 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
2775 if (!out->a2dp_compress_mute)
2776 ret = set_compr_volume(stream, left, right);
2777 out->volume_l = left;
2778 out->volume_r = right;
2779 pthread_mutex_unlock(&out->compr_mute_lock);
2780 return ret;
vivek mehtaa68fea62017-06-08 19:04:02 -07002781 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002782 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2783 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2784 if (!out->standby) {
2785 // if in standby, cached volume will be sent after stream is opened
2786 audio_extn_utils_send_app_type_gain(out->dev,
2787 out->app_type_cfg.app_type,
2788 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002789 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002790 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002791 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002792
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002793 return -ENOSYS;
2794}
2795
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002796// note: this call is safe only if the stream_cb is
2797// removed first in close_output_stream (as is done now).
2798static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2799{
2800 if (!stream || !parms)
2801 return;
2802
2803 struct stream_out *out = (struct stream_out *)stream;
2804 struct audio_device *adev = out->dev;
2805
2806 card_status_t status;
2807 int card;
2808 if (parse_snd_card_status(parms, &card, &status) < 0)
2809 return;
2810
2811 pthread_mutex_lock(&adev->lock);
2812 bool valid_cb = (card == adev->snd_card);
2813 pthread_mutex_unlock(&adev->lock);
2814
2815 if (!valid_cb)
2816 return;
2817
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002818 lock_output_stream(out);
2819 if (out->card_status != status)
2820 out->card_status = status;
2821 pthread_mutex_unlock(&out->lock);
2822
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002823 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2824 use_case_table[out->usecase],
2825 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2826
2827 if (status == CARD_STATUS_OFFLINE)
2828 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002829
2830 return;
2831}
2832
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002833#ifdef NO_AUDIO_OUT
2834static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002835 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002836{
2837 struct stream_out *out = (struct stream_out *)stream;
2838
2839 /* No Output device supported other than BT for playback.
2840 * Sleep for the amount of buffer duration
2841 */
Eric Laurenta1478072015-09-21 17:21:52 -07002842 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002843 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2844 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002845 out_get_sample_rate(&out->stream.common));
2846 pthread_mutex_unlock(&out->lock);
2847 return bytes;
2848}
2849#endif
2850
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002851static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2852 size_t bytes)
2853{
2854 struct stream_out *out = (struct stream_out *)stream;
2855 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002856 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002857 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002858
Eric Laurenta1478072015-09-21 17:21:52 -07002859 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002860 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07002861 const size_t frame_size = audio_stream_out_frame_size(stream);
2862 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002863
Eric Laurent0e46adf2016-12-16 12:49:24 -08002864 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2865 error_code = ERROR_CODE_WRITE;
2866 goto exit;
2867 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002868
2869 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2870 (audio_extn_a2dp_is_suspended())) {
2871 if (!(out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2872 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2873 ret = -EIO;
2874 goto exit;
2875 }
2876 }
2877 }
2878
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002879 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002880 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002881 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002882 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07002883
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002884 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002885 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002886 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07002887 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002888 goto exit;
2889 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002890
vivek mehta40125092017-08-21 18:48:51 -07002891 // after standby always force set last known cal step
2892 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
2893 ALOGD("%s: retry previous failed cal level set", __func__);
2894 send_gain_dep_calibration_l();
2895 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002896 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002897
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002898 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002899 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002900 if (out->send_new_metadata) {
2901 ALOGVV("send new gapless metadata");
2902 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2903 out->send_new_metadata = 0;
2904 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002905 unsigned int avail;
2906 struct timespec tstamp;
2907 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2908 /* Do not limit write size if the available frames count is unknown */
2909 if (ret != 0) {
2910 avail = bytes;
2911 }
2912 if (avail == 0) {
2913 ret = 0;
2914 } else {
2915 if (avail > bytes) {
2916 avail = bytes;
2917 }
2918 ret = compress_write(out->compr, buffer, avail);
2919 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2920 __func__, avail, ret);
2921 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002922
Eric Laurent6e895242013-09-05 16:10:57 -07002923 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002924 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2925 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002926 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002927 compress_start(out->compr);
2928 out->playback_started = 1;
2929 out->offload_state = OFFLOAD_STATE_PLAYING;
2930 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002931 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002932 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002933 } else {
2934 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002935 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002936 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002937 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002938 return ret;
2939 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002940 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002941 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07002942 size_t bytes_to_write = bytes;
2943
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002944 if (out->muted)
2945 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07002946 // FIXME: this can be removed once audio flinger mixer supports mono output
Nadav Bar3d72cfc2018-01-07 12:19:24 +02002947 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP || out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
Eric Laurentad2dde92017-09-20 18:27:31 -07002948 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
2949 int16_t *src = (int16_t *)buffer;
2950 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002951
Eric Laurentad2dde92017-09-20 18:27:31 -07002952 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
2953 out->format != AUDIO_FORMAT_PCM_16_BIT,
2954 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002955
Eric Laurentad2dde92017-09-20 18:27:31 -07002956 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
2957 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
2958 }
2959 bytes_to_write /= 2;
2960 }
2961 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes_to_write);
2962
Glenn Kasten5a59dff2018-02-22 08:05:35 -08002963 long ns = (frames * (int64_t) NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002964 request_out_focus(out, ns);
2965
2966 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2967 if (use_mmap)
Eric Laurentad2dde92017-09-20 18:27:31 -07002968 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002969 else
Eric Laurentad2dde92017-09-20 18:27:31 -07002970 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002971
Haynes Mathew George03c40102016-01-29 17:57:48 -08002972 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002973 } else {
2974 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002975 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002976 }
2977
2978exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002979 // For PCM we always consume the buffer and return #bytes regardless of ret.
2980 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07002981 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07002982 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002983 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07002984
Andy Hung7401c7c2016-09-21 12:41:21 -07002985 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07002986 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07002987 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2988 ALOGE_IF(out->pcm != NULL,
2989 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07002990 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002991 // usleep not guaranteed for values over 1 second but we don't limit here.
2992 }
2993 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002994
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002995 pthread_mutex_unlock(&out->lock);
2996
2997 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002998 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002999 if (sleeptime_us != 0)
3000 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003001 }
3002 return bytes;
3003}
3004
3005static int out_get_render_position(const struct audio_stream_out *stream,
3006 uint32_t *dsp_frames)
3007{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003008 struct stream_out *out = (struct stream_out *)stream;
3009 *dsp_frames = 0;
3010 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07003011 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003012 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003013 unsigned long frames = 0;
3014 // TODO: check return value
3015 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
3016 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003017 ALOGVV("%s rendered frames %d sample_rate %d",
3018 __func__, *dsp_frames, out->sample_rate);
3019 }
3020 pthread_mutex_unlock(&out->lock);
3021 return 0;
3022 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003023 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003024}
3025
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003026static int out_add_audio_effect(const struct audio_stream *stream __unused,
3027 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003028{
3029 return 0;
3030}
3031
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003032static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3033 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003034{
3035 return 0;
3036}
3037
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003038static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3039 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003040{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003041 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003042}
3043
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003044static int out_get_presentation_position(const struct audio_stream_out *stream,
3045 uint64_t *frames, struct timespec *timestamp)
3046{
3047 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003048 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07003049 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003050
Eric Laurenta1478072015-09-21 17:21:52 -07003051 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003052
Eric Laurent949a0892013-09-20 09:20:13 -07003053 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3054 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003055 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07003056 compress_get_tstamp(out->compr, &dsp_frames,
3057 &out->sample_rate);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003058 // Adjustment accounts for A2DP encoder latency with offload usecases
3059 // Note: Encoder latency is returned in ms.
3060 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3061 unsigned long offset =
3062 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3063 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
3064 }
Eric Laurent949a0892013-09-20 09:20:13 -07003065 ALOGVV("%s rendered frames %ld sample_rate %d",
3066 __func__, dsp_frames, out->sample_rate);
3067 *frames = dsp_frames;
3068 ret = 0;
3069 /* this is the best we can do */
3070 clock_gettime(CLOCK_MONOTONIC, timestamp);
3071 }
3072 } else {
3073 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07003074 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003075 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3076 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003077 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003078 // This adjustment accounts for buffering after app processor.
3079 // It is based on estimated DSP latency per use case, rather than exact.
3080 signed_frames -=
3081 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3082
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003083 // Adjustment accounts for A2DP encoder latency with non-offload usecases
3084 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3085 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3086 signed_frames -=
3087 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3088 }
3089
Eric Laurent949a0892013-09-20 09:20:13 -07003090 // It would be unusual for this value to be negative, but check just in case ...
3091 if (signed_frames >= 0) {
3092 *frames = signed_frames;
3093 ret = 0;
3094 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003095 }
3096 }
3097 }
3098
3099 pthread_mutex_unlock(&out->lock);
3100
3101 return ret;
3102}
3103
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003104static int out_set_callback(struct audio_stream_out *stream,
3105 stream_callback_t callback, void *cookie)
3106{
3107 struct stream_out *out = (struct stream_out *)stream;
3108
3109 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003110 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003111 out->offload_callback = callback;
3112 out->offload_cookie = cookie;
3113 pthread_mutex_unlock(&out->lock);
3114 return 0;
3115}
3116
3117static int out_pause(struct audio_stream_out* stream)
3118{
3119 struct stream_out *out = (struct stream_out *)stream;
3120 int status = -ENOSYS;
3121 ALOGV("%s", __func__);
3122 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003123 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003124 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
3125 status = compress_pause(out->compr);
3126 out->offload_state = OFFLOAD_STATE_PAUSED;
3127 }
3128 pthread_mutex_unlock(&out->lock);
3129 }
3130 return status;
3131}
3132
3133static int out_resume(struct audio_stream_out* stream)
3134{
3135 struct stream_out *out = (struct stream_out *)stream;
3136 int status = -ENOSYS;
3137 ALOGV("%s", __func__);
3138 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3139 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07003140 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003141 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
3142 status = compress_resume(out->compr);
3143 out->offload_state = OFFLOAD_STATE_PLAYING;
3144 }
3145 pthread_mutex_unlock(&out->lock);
3146 }
3147 return status;
3148}
3149
3150static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3151{
3152 struct stream_out *out = (struct stream_out *)stream;
3153 int status = -ENOSYS;
3154 ALOGV("%s", __func__);
3155 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003156 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003157 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3158 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3159 else
3160 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3161 pthread_mutex_unlock(&out->lock);
3162 }
3163 return status;
3164}
3165
3166static int out_flush(struct audio_stream_out* stream)
3167{
3168 struct stream_out *out = (struct stream_out *)stream;
3169 ALOGV("%s", __func__);
3170 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003171 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003172 stop_compressed_output_l(out);
3173 pthread_mutex_unlock(&out->lock);
3174 return 0;
3175 }
3176 return -ENOSYS;
3177}
3178
Eric Laurent0e46adf2016-12-16 12:49:24 -08003179static int out_stop(const struct audio_stream_out* stream)
3180{
3181 struct stream_out *out = (struct stream_out *)stream;
3182 struct audio_device *adev = out->dev;
3183 int ret = -ENOSYS;
3184
3185 ALOGV("%s", __func__);
3186 pthread_mutex_lock(&adev->lock);
3187 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3188 out->playback_started && out->pcm != NULL) {
3189 pcm_stop(out->pcm);
3190 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08003191 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003192 }
3193 pthread_mutex_unlock(&adev->lock);
3194 return ret;
3195}
3196
3197static int out_start(const struct audio_stream_out* stream)
3198{
3199 struct stream_out *out = (struct stream_out *)stream;
3200 struct audio_device *adev = out->dev;
3201 int ret = -ENOSYS;
3202
3203 ALOGV("%s", __func__);
3204 pthread_mutex_lock(&adev->lock);
3205 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3206 !out->playback_started && out->pcm != NULL) {
3207 ret = start_output_stream(out);
3208 if (ret == 0) {
3209 out->playback_started = true;
3210 }
3211 }
3212 pthread_mutex_unlock(&adev->lock);
3213 return ret;
3214}
3215
Phil Burkbc991042017-02-24 08:06:44 -08003216/*
3217 * Modify config->period_count based on min_size_frames
3218 */
3219static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
3220{
3221 int periodCountRequested = (min_size_frames + config->period_size - 1)
3222 / config->period_size;
3223 int periodCount = MMAP_PERIOD_COUNT_MIN;
3224
3225 ALOGV("%s original config.period_size = %d config.period_count = %d",
3226 __func__, config->period_size, config->period_count);
3227
3228 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
3229 periodCount *= 2;
3230 }
3231 config->period_count = periodCount;
3232
3233 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
3234}
3235
Eric Laurent0e46adf2016-12-16 12:49:24 -08003236static int out_create_mmap_buffer(const struct audio_stream_out *stream,
3237 int32_t min_size_frames,
3238 struct audio_mmap_buffer_info *info)
3239{
3240 struct stream_out *out = (struct stream_out *)stream;
3241 struct audio_device *adev = out->dev;
3242 int ret = 0;
3243 unsigned int offset1;
3244 unsigned int frames1;
3245 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003246 uint32_t mmap_size;
3247 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003248
3249 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003250 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003251 pthread_mutex_lock(&adev->lock);
3252
3253 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003254 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003255 ret = -EINVAL;
3256 goto exit;
3257 }
3258 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003259 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003260 ret = -ENOSYS;
3261 goto exit;
3262 }
3263 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3264 if (out->pcm_device_id < 0) {
3265 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3266 __func__, out->pcm_device_id, out->usecase);
3267 ret = -EINVAL;
3268 goto exit;
3269 }
Phil Burkbc991042017-02-24 08:06:44 -08003270
3271 adjust_mmap_period_count(&out->config, min_size_frames);
3272
Eric Laurent0e46adf2016-12-16 12:49:24 -08003273 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3274 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3275 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3276 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3277 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3278 step = "open";
3279 ret = -ENODEV;
3280 goto exit;
3281 }
3282 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3283 if (ret < 0) {
3284 step = "begin";
3285 goto exit;
3286 }
3287 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003288 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003289 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003290 ret = platform_get_mmap_data_fd(adev->platform,
3291 out->pcm_device_id, 0 /*playback*/,
3292 &info->shared_memory_fd,
3293 &mmap_size);
3294 if (ret < 0) {
3295 // Fall back to non exclusive mode
3296 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3297 } else {
3298 if (mmap_size < buffer_size) {
3299 step = "mmap";
3300 goto exit;
3301 }
3302 // FIXME: indicate exclusive mode support by returning a negative buffer size
3303 info->buffer_size_frames *= -1;
3304 }
3305 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003306
3307 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3308 if (ret < 0) {
3309 step = "commit";
3310 goto exit;
3311 }
Phil Burkbc991042017-02-24 08:06:44 -08003312
3313 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003314 ret = 0;
3315
3316 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3317 __func__, info->shared_memory_address, info->buffer_size_frames);
3318
3319exit:
3320 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003321 if (out->pcm == NULL) {
3322 ALOGE("%s: %s - %d", __func__, step, ret);
3323 } else {
3324 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003325 pcm_close(out->pcm);
3326 out->pcm = NULL;
3327 }
3328 }
3329 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003330 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003331 return ret;
3332}
3333
3334static int out_get_mmap_position(const struct audio_stream_out *stream,
3335 struct audio_mmap_position *position)
3336{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003337 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003338 struct stream_out *out = (struct stream_out *)stream;
3339 ALOGVV("%s", __func__);
3340 if (position == NULL) {
3341 return -EINVAL;
3342 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003343 lock_output_stream(out);
3344 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3345 out->pcm == NULL) {
3346 ret = -ENOSYS;
3347 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003348 }
3349
3350 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003351 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003352 if (ret < 0) {
3353 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003354 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003355 }
Andy Hungfc044e12017-03-20 09:24:22 -07003356 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003357exit:
3358 pthread_mutex_unlock(&out->lock);
3359 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003360}
3361
3362
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003363/** audio_stream_in implementation **/
3364static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3365{
3366 struct stream_in *in = (struct stream_in *)stream;
3367
3368 return in->config.rate;
3369}
3370
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003371static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003372{
3373 return -ENOSYS;
3374}
3375
3376static size_t in_get_buffer_size(const struct audio_stream *stream)
3377{
3378 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003379 return in->config.period_size * in->af_period_multiplier *
3380 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003381}
3382
3383static uint32_t in_get_channels(const struct audio_stream *stream)
3384{
3385 struct stream_in *in = (struct stream_in *)stream;
3386
3387 return in->channel_mask;
3388}
3389
vivek mehta4ed66e62016-04-15 23:33:34 -07003390static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003391{
vivek mehta4ed66e62016-04-15 23:33:34 -07003392 struct stream_in *in = (struct stream_in *)stream;
3393 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003394}
3395
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003396static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003397{
3398 return -ENOSYS;
3399}
3400
3401static int in_standby(struct audio_stream *stream)
3402{
3403 struct stream_in *in = (struct stream_in *)stream;
3404 struct audio_device *adev = in->dev;
3405 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003406 bool do_stop = true;
3407
Eric Laurent994a6932013-07-17 11:51:42 -07003408 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003409
3410 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003411
3412 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003413 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003414 audio_extn_sound_trigger_stop_lab(in);
3415 in->standby = true;
3416 }
3417
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003418 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003419 if (adev->adm_deregister_stream)
3420 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3421
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003422 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003423 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003424 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003425 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003426 in->capture_started = false;
3427 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003428 if (in->pcm) {
3429 pcm_close(in->pcm);
3430 in->pcm = NULL;
3431 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003432 adev->enable_voicerx = false;
3433 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003434 if (do_stop) {
3435 status = stop_input_stream(in);
3436 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003437 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003438 }
3439 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003440 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003441 return status;
3442}
3443
Andy Hungd13f0d32017-06-12 13:58:37 -07003444static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003445{
Andy Hungd13f0d32017-06-12 13:58:37 -07003446 struct stream_in *in = (struct stream_in *)stream;
3447
3448 // We try to get the lock for consistency,
3449 // but it isn't necessary for these variables.
3450 // If we're not in standby, we may be blocked on a read.
3451 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3452 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3453 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3454 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3455
3456 if (locked) {
3457 pthread_mutex_unlock(&in->lock);
3458 }
3459
3460 // dump error info
3461 (void)error_log_dump(
3462 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003463 return 0;
3464}
3465
3466static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3467{
3468 struct stream_in *in = (struct stream_in *)stream;
3469 struct audio_device *adev = in->dev;
3470 struct str_parms *parms;
3471 char *str;
3472 char value[32];
3473 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003474 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003475
Eric Laurent994a6932013-07-17 11:51:42 -07003476 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003477 parms = str_parms_create_str(kvpairs);
3478
3479 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3480
Eric Laurenta1478072015-09-21 17:21:52 -07003481 lock_input_stream(in);
3482
Eric Laurent150dbfe2013-02-27 14:31:02 -08003483 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003484 if (ret >= 0) {
3485 val = atoi(value);
3486 /* no audio source uses val == 0 */
3487 if ((in->source != val) && (val != 0)) {
3488 in->source = val;
3489 }
3490 }
3491
3492 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003493
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003494 if (ret >= 0) {
3495 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003496 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003497
3498 // Workaround: If routing to an non existing usb device, fail gracefully
3499 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003500 int card;
3501 if (audio_is_usb_in_device(val) &&
3502 (card = get_alive_usb_card(parms)) >= 0) {
3503
3504 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003505 status = -ENOSYS;
3506 } else {
3507
3508 in->device = val;
3509 /* If recording is in progress, change the tx device to new device */
3510 if (!in->standby) {
3511 ALOGV("update input routing change");
3512 // inform adm before actual routing to prevent glitches.
3513 if (adev->adm_on_routing_change) {
3514 adev->adm_on_routing_change(adev->adm_data,
3515 in->capture_handle);
3516 }
3517 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003518 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003519 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003520 }
3521 }
3522
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003523 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003524 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003525
3526 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003527 ALOGV("%s: exit: status(%d)", __func__, status);
3528 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003529}
3530
Haynes Mathew George569b7482017-05-08 14:44:27 -07003531static char* in_get_parameters(const struct audio_stream *stream,
3532 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003533{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003534 struct stream_in *in = (struct stream_in *)stream;
3535 struct str_parms *query = str_parms_create_str(keys);
3536 char *str;
3537 struct str_parms *reply = str_parms_create();
3538 bool replied = false;
3539
3540 ALOGV("%s: enter: keys - %s", __func__, keys);
3541 replied |= stream_get_parameter_channels(query, reply,
3542 &in->supported_channel_masks[0]);
3543 replied |= stream_get_parameter_formats(query, reply,
3544 &in->supported_formats[0]);
3545 replied |= stream_get_parameter_rates(query, reply,
3546 &in->supported_sample_rates[0]);
3547 if (replied) {
3548 str = str_parms_to_str(reply);
3549 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003550 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003551 }
3552 str_parms_destroy(query);
3553 str_parms_destroy(reply);
3554 ALOGV("%s: exit: returns - %s", __func__, str);
3555 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003556}
3557
Eric Laurent51f3c662018-04-10 18:21:34 -07003558static int in_set_gain(struct audio_stream_in *stream, float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003559{
Eric Laurent51f3c662018-04-10 18:21:34 -07003560 struct stream_in *in = (struct stream_in *)stream;
3561 char mixer_ctl_name[128];
3562 struct mixer_ctl *ctl;
3563 int ctl_value;
3564
3565 ALOGV("%s: gain %f", __func__, gain);
3566
3567 if (stream == NULL)
3568 return -EINVAL;
3569
3570 /* in_set_gain() only used to silence MMAP capture for now */
3571 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
3572 return -ENOSYS;
3573
3574 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
3575
3576 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
3577 if (!ctl) {
3578 ALOGW("%s: Could not get ctl for mixer cmd - %s",
3579 __func__, mixer_ctl_name);
3580 return -ENOSYS;
3581 }
3582
3583 if (gain < RECORD_GAIN_MIN)
3584 gain = RECORD_GAIN_MIN;
3585 else if (gain > RECORD_GAIN_MAX)
3586 gain = RECORD_GAIN_MAX;
3587 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
3588
3589 mixer_ctl_set_value(ctl, 0, ctl_value);
3590 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003591}
3592
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003593static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3594{
3595 if (!stream || !parms)
3596 return;
3597
3598 struct stream_in *in = (struct stream_in *)stream;
3599 struct audio_device *adev = in->dev;
3600
3601 card_status_t status;
3602 int card;
3603 if (parse_snd_card_status(parms, &card, &status) < 0)
3604 return;
3605
3606 pthread_mutex_lock(&adev->lock);
3607 bool valid_cb = (card == adev->snd_card);
3608 pthread_mutex_unlock(&adev->lock);
3609
3610 if (!valid_cb)
3611 return;
3612
3613 lock_input_stream(in);
3614 if (in->card_status != status)
3615 in->card_status = status;
3616 pthread_mutex_unlock(&in->lock);
3617
3618 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3619 use_case_table[in->usecase],
3620 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3621
3622 // a better solution would be to report error back to AF and let
3623 // it put the stream to standby
3624 if (status == CARD_STATUS_OFFLINE)
3625 in_standby(&in->stream.common);
3626
3627 return;
3628}
3629
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003630static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3631 size_t bytes)
3632{
3633 struct stream_in *in = (struct stream_in *)stream;
3634 struct audio_device *adev = in->dev;
3635 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003636 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003637 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003638
Eric Laurenta1478072015-09-21 17:21:52 -07003639 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003640 const size_t frame_size = audio_stream_in_frame_size(stream);
3641 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003642
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003643 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003644 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003645 /* Read from sound trigger HAL */
3646 audio_extn_sound_trigger_read(in, buffer, bytes);
3647 pthread_mutex_unlock(&in->lock);
3648 return bytes;
3649 }
3650
Eric Laurent0e46adf2016-12-16 12:49:24 -08003651 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3652 ret = -ENOSYS;
3653 goto exit;
3654 }
3655
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003656 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003657 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003658 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003659 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003660 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003661 goto exit;
3662 }
3663 in->standby = 0;
3664 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003665
Andy Hungd13f0d32017-06-12 13:58:37 -07003666 // errors that occur here are read errors.
3667 error_code = ERROR_CODE_READ;
3668
Haynes Mathew George03c40102016-01-29 17:57:48 -08003669 //what's the duration requested by the client?
3670 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3671 in->config.rate;
3672 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003673
Haynes Mathew George03c40102016-01-29 17:57:48 -08003674 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003675 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003676 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003677 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003678 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003679 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003680 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003681 if (ret < 0) {
3682 ALOGE("Failed to read w/err %s", strerror(errno));
3683 ret = -errno;
3684 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003685 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3686 if (bytes % 4 == 0) {
3687 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3688 int_buf_stream = buffer;
3689 for (size_t itt=0; itt < bytes/4 ; itt++) {
3690 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003691 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003692 } else {
3693 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3694 ret = -EINVAL;
3695 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003696 }
3697 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003698 }
3699
Haynes Mathew George03c40102016-01-29 17:57:48 -08003700 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003701
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003702 /*
3703 * Instead of writing zeroes here, we could trust the hardware
3704 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003705 * 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 -08003706 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08003707 if (ret == 0 && adev->mic_muted &&
3708 !voice_is_in_call_rec_stream(in) &&
3709 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003710 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07003711 in->frames_muted += frames;
3712 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003713
3714exit:
3715 pthread_mutex_unlock(&in->lock);
3716
3717 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07003718 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003719 in_standby(&in->stream.common);
3720 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003721 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003722 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07003723 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08003724 }
3725 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003726 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003727 }
3728 return bytes;
3729}
3730
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003731static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003732{
3733 return 0;
3734}
3735
Andy Hung6ebe5962016-01-15 17:46:57 -08003736static int in_get_capture_position(const struct audio_stream_in *stream,
3737 int64_t *frames, int64_t *time)
3738{
3739 if (stream == NULL || frames == NULL || time == NULL) {
3740 return -EINVAL;
3741 }
3742 struct stream_in *in = (struct stream_in *)stream;
3743 int ret = -ENOSYS;
3744
3745 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003746 // note: ST sessions do not close the alsa pcm driver synchronously
3747 // on standby. Therefore, we may return an error even though the
3748 // pcm stream is still opened.
3749 if (in->standby) {
3750 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
3751 "%s stream in standby but pcm not NULL for non ST session", __func__);
3752 goto exit;
3753 }
Andy Hung6ebe5962016-01-15 17:46:57 -08003754 if (in->pcm) {
3755 struct timespec timestamp;
3756 unsigned int avail;
3757 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3758 *frames = in->frames_read + avail;
3759 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3760 ret = 0;
3761 }
3762 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003763exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08003764 pthread_mutex_unlock(&in->lock);
3765 return ret;
3766}
3767
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003768static int add_remove_audio_effect(const struct audio_stream *stream,
3769 effect_handle_t effect,
3770 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003771{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003772 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003773 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003774 int status = 0;
3775 effect_descriptor_t desc;
3776
3777 status = (*effect)->get_descriptor(effect, &desc);
3778 if (status != 0)
3779 return status;
3780
Eric Laurenta1478072015-09-21 17:21:52 -07003781 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003782 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003783 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003784 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003785 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003786 in->enable_aec != enable &&
3787 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3788 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003789 if (!enable)
3790 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003791 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3792 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3793 adev->enable_voicerx = enable;
3794 struct audio_usecase *usecase;
3795 struct listnode *node;
3796 list_for_each(node, &adev->usecase_list) {
3797 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07003798 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07003799 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05003800 }
3801 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003802 if (!in->standby)
3803 select_devices(in->dev, in->usecase);
3804 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003805 if (in->enable_ns != enable &&
3806 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3807 in->enable_ns = enable;
3808 if (!in->standby)
3809 select_devices(in->dev, in->usecase);
3810 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003811 pthread_mutex_unlock(&in->dev->lock);
3812 pthread_mutex_unlock(&in->lock);
3813
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003814 return 0;
3815}
3816
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003817static int in_add_audio_effect(const struct audio_stream *stream,
3818 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003819{
Eric Laurent994a6932013-07-17 11:51:42 -07003820 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003821 return add_remove_audio_effect(stream, effect, true);
3822}
3823
3824static int in_remove_audio_effect(const struct audio_stream *stream,
3825 effect_handle_t effect)
3826{
Eric Laurent994a6932013-07-17 11:51:42 -07003827 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003828 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003829}
3830
Eric Laurent0e46adf2016-12-16 12:49:24 -08003831static int in_stop(const struct audio_stream_in* stream)
3832{
3833 struct stream_in *in = (struct stream_in *)stream;
3834 struct audio_device *adev = in->dev;
3835
3836 int ret = -ENOSYS;
3837 ALOGV("%s", __func__);
3838 pthread_mutex_lock(&adev->lock);
3839 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3840 in->capture_started && in->pcm != NULL) {
3841 pcm_stop(in->pcm);
3842 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003843 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003844 }
3845 pthread_mutex_unlock(&adev->lock);
3846 return ret;
3847}
3848
3849static int in_start(const struct audio_stream_in* stream)
3850{
3851 struct stream_in *in = (struct stream_in *)stream;
3852 struct audio_device *adev = in->dev;
3853 int ret = -ENOSYS;
3854
3855 ALOGV("%s in %p", __func__, in);
3856 pthread_mutex_lock(&adev->lock);
3857 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3858 !in->capture_started && in->pcm != NULL) {
3859 if (!in->capture_started) {
3860 ret = start_input_stream(in);
3861 if (ret == 0) {
3862 in->capture_started = true;
3863 }
3864 }
3865 }
3866 pthread_mutex_unlock(&adev->lock);
3867 return ret;
3868}
3869
3870static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3871 int32_t min_size_frames,
3872 struct audio_mmap_buffer_info *info)
3873{
3874 struct stream_in *in = (struct stream_in *)stream;
3875 struct audio_device *adev = in->dev;
3876 int ret = 0;
3877 unsigned int offset1;
3878 unsigned int frames1;
3879 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003880 uint32_t mmap_size;
3881 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003882
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003883 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003884 pthread_mutex_lock(&adev->lock);
3885 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003886
Eric Laurent0e46adf2016-12-16 12:49:24 -08003887 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003888 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003889 ret = -EINVAL;
3890 goto exit;
3891 }
3892 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003893 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003894 ALOGV("%s in %p", __func__, in);
3895 ret = -ENOSYS;
3896 goto exit;
3897 }
3898 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3899 if (in->pcm_device_id < 0) {
3900 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3901 __func__, in->pcm_device_id, in->usecase);
3902 ret = -EINVAL;
3903 goto exit;
3904 }
Phil Burkbc991042017-02-24 08:06:44 -08003905
3906 adjust_mmap_period_count(&in->config, min_size_frames);
3907
Eric Laurent0e46adf2016-12-16 12:49:24 -08003908 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3909 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3910 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3911 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3912 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3913 step = "open";
3914 ret = -ENODEV;
3915 goto exit;
3916 }
3917
3918 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3919 if (ret < 0) {
3920 step = "begin";
3921 goto exit;
3922 }
3923 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003924 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003925 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003926 ret = platform_get_mmap_data_fd(adev->platform,
3927 in->pcm_device_id, 1 /*capture*/,
3928 &info->shared_memory_fd,
3929 &mmap_size);
3930 if (ret < 0) {
3931 // Fall back to non exclusive mode
3932 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3933 } else {
3934 if (mmap_size < buffer_size) {
3935 step = "mmap";
3936 goto exit;
3937 }
3938 // FIXME: indicate exclusive mode support by returning a negative buffer size
3939 info->buffer_size_frames *= -1;
3940 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08003941
Haynes Mathew George96483a22017-03-28 14:52:47 -07003942 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003943
3944 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3945 if (ret < 0) {
3946 step = "commit";
3947 goto exit;
3948 }
3949
Phil Burkbc991042017-02-24 08:06:44 -08003950 in->standby = false;
3951 ret = 0;
3952
Eric Laurent0e46adf2016-12-16 12:49:24 -08003953 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3954 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003955
3956exit:
3957 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003958 if (in->pcm == NULL) {
3959 ALOGE("%s: %s - %d", __func__, step, ret);
3960 } else {
3961 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003962 pcm_close(in->pcm);
3963 in->pcm = NULL;
3964 }
3965 }
3966 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003967 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003968 return ret;
3969}
3970
3971static int in_get_mmap_position(const struct audio_stream_in *stream,
3972 struct audio_mmap_position *position)
3973{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003974 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003975 struct stream_in *in = (struct stream_in *)stream;
3976 ALOGVV("%s", __func__);
3977 if (position == NULL) {
3978 return -EINVAL;
3979 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003980 lock_input_stream(in);
3981 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
3982 in->pcm == NULL) {
3983 ret = -ENOSYS;
3984 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003985 }
3986 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003987 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003988 if (ret < 0) {
3989 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003990 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003991 }
Andy Hungfc044e12017-03-20 09:24:22 -07003992 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003993exit:
3994 pthread_mutex_unlock(&in->lock);
3995 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003996}
3997
jiabin8962a4d2018-03-19 18:21:24 -07003998static int in_get_active_microphones(const struct audio_stream_in *stream,
3999 struct audio_microphone_characteristic_t *mic_array,
4000 size_t *mic_count) {
4001 struct stream_in *in = (struct stream_in *)stream;
4002 struct audio_device *adev = in->dev;
4003 ALOGVV("%s", __func__);
4004
4005 lock_input_stream(in);
4006 pthread_mutex_lock(&adev->lock);
4007 int ret = platform_get_active_microphones(adev->platform, in->device,
4008 audio_channel_count_from_in_mask(in->channel_mask),
4009 in->source, in->usecase, mic_array, mic_count);
4010 pthread_mutex_unlock(&adev->lock);
4011 pthread_mutex_unlock(&in->lock);
4012
4013 return ret;
4014}
4015
4016static int adev_get_microphones(const struct audio_hw_device *dev,
4017 struct audio_microphone_characteristic_t *mic_array,
4018 size_t *mic_count) {
4019 struct audio_device *adev = (struct audio_device *)dev;
4020 ALOGVV("%s", __func__);
4021
4022 pthread_mutex_lock(&adev->lock);
4023 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
4024 pthread_mutex_unlock(&adev->lock);
4025
4026 return ret;
4027}
Eric Laurent0e46adf2016-12-16 12:49:24 -08004028
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004029static int adev_open_output_stream(struct audio_hw_device *dev,
4030 audio_io_handle_t handle,
4031 audio_devices_t devices,
4032 audio_output_flags_t flags,
4033 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07004034 struct audio_stream_out **stream_out,
4035 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004036{
4037 struct audio_device *adev = (struct audio_device *)dev;
4038 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004039 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004040 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
4041 bool is_usb_dev = audio_is_usb_out_device(devices) &&
4042 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004043
Andy Hungd9653bd2017-08-01 19:31:39 -07004044 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
4045 return -ENOSYS;
4046 }
4047
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004048 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
4049 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004050 *stream_out = NULL;
4051 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4052
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004053 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
4054
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004055 if (devices == AUDIO_DEVICE_NONE)
4056 devices = AUDIO_DEVICE_OUT_SPEAKER;
4057
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004058 out->flags = flags;
4059 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004060 out->dev = adev;
Eric Laurentc4aef752013-09-12 17:45:53 -07004061 out->handle = handle;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004062 out->a2dp_compress_mute = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004063
4064 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004065 if ((is_hdmi || is_usb_dev) &&
4066 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
4067 (flags == AUDIO_OUTPUT_FLAG_NONE ||
4068 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Eric Laurentab805ee2018-03-30 12:20:38 -07004069 audio_format_t req_format = config->format;
4070 audio_channel_mask_t req_channel_mask = config->channel_mask;
4071 uint32_t req_sample_rate = config->sample_rate;
4072
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004073 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004074 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004075 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004076 if (config->sample_rate == 0)
4077 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Eric Laurentab805ee2018-03-30 12:20:38 -07004078 if (config->channel_mask == AUDIO_CHANNEL_NONE)
Haynes Mathew George569b7482017-05-08 14:44:27 -07004079 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
4080 if (config->format == AUDIO_FORMAT_DEFAULT)
4081 config->format = AUDIO_FORMAT_PCM_16_BIT;
4082 } else if (is_usb_dev) {
4083 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
4084 &config->format,
4085 &out->supported_formats[0],
4086 MAX_SUPPORTED_FORMATS,
4087 &config->channel_mask,
4088 &out->supported_channel_masks[0],
4089 MAX_SUPPORTED_CHANNEL_MASKS,
4090 &config->sample_rate,
4091 &out->supported_sample_rates[0],
4092 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004093 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004094 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004095 pthread_mutex_unlock(&adev->lock);
Eric Laurentab805ee2018-03-30 12:20:38 -07004096 if (ret != 0) {
4097 // For MMAP NO IRQ, allow conversions in ADSP
4098 if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
4099 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004100
Eric Laurentab805ee2018-03-30 12:20:38 -07004101 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
4102 config->sample_rate = req_sample_rate;
4103 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
4104 config->channel_mask = req_channel_mask;
4105 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
4106 config->format = req_format;
4107 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004108
Haynes Mathew George569b7482017-05-08 14:44:27 -07004109 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004110 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004111 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004112 if (is_hdmi) {
4113 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4114 out->config = pcm_config_hdmi_multi;
4115 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
4116 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4117 out->config = pcm_config_mmap_playback;
4118 out->stream.start = out_start;
4119 out->stream.stop = out_stop;
4120 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4121 out->stream.get_mmap_position = out_get_mmap_position;
4122 } else {
4123 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4124 out->config = pcm_config_hifi;
4125 }
4126
4127 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004128 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004129 if (is_hdmi) {
4130 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
4131 audio_bytes_per_sample(out->format));
4132 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004133 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004134 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07004135 pthread_mutex_lock(&adev->lock);
4136 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4137 pthread_mutex_unlock(&adev->lock);
4138
4139 // reject offload during card offline to allow
4140 // fallback to s/w paths
4141 if (offline) {
4142 ret = -ENODEV;
4143 goto error_open;
4144 }
4145
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004146 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4147 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4148 ALOGE("%s: Unsupported Offload information", __func__);
4149 ret = -EINVAL;
4150 goto error_open;
4151 }
4152 if (!is_supported_format(config->offload_info.format)) {
4153 ALOGE("%s: Unsupported audio format", __func__);
4154 ret = -EINVAL;
4155 goto error_open;
4156 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004157 out->sample_rate = config->offload_info.sample_rate;
4158 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
4159 out->channel_mask = config->offload_info.channel_mask;
4160 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
4161 out->channel_mask = config->channel_mask;
4162 else
4163 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4164
4165 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004166
4167 out->compr_config.codec = (struct snd_codec *)
4168 calloc(1, sizeof(struct snd_codec));
4169
4170 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004171
4172 out->stream.set_callback = out_set_callback;
4173 out->stream.pause = out_pause;
4174 out->stream.resume = out_resume;
4175 out->stream.drain = out_drain;
4176 out->stream.flush = out_flush;
4177
4178 out->compr_config.codec->id =
4179 get_snd_codec_id(config->offload_info.format);
4180 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
4181 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004182 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004183 out->compr_config.codec->bit_rate =
4184 config->offload_info.bit_rate;
4185 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004186 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004187 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
4188
4189 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4190 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004191
4192 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004193 create_offload_callback_thread(out);
4194 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4195 __func__, config->offload_info.version,
4196 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02004197 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4198 switch (config->sample_rate) {
4199 case 0:
4200 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4201 break;
4202 case 8000:
4203 case 16000:
4204 case 48000:
4205 out->sample_rate = config->sample_rate;
4206 break;
4207 default:
4208 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
4209 config->sample_rate);
4210 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4211 ret = -EINVAL;
4212 goto error_open;
4213 }
4214 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4215 switch (config->channel_mask) {
4216 case AUDIO_CHANNEL_NONE:
4217 case AUDIO_CHANNEL_OUT_STEREO:
4218 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4219 break;
4220 default:
4221 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
4222 config->channel_mask);
4223 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4224 ret = -EINVAL;
4225 goto error_open;
4226 }
4227 switch (config->format) {
4228 case AUDIO_FORMAT_DEFAULT:
4229 case AUDIO_FORMAT_PCM_16_BIT:
4230 out->format = AUDIO_FORMAT_PCM_16_BIT;
4231 break;
4232 default:
4233 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
4234 config->format);
4235 config->format = AUDIO_FORMAT_PCM_16_BIT;
4236 ret = -EINVAL;
4237 goto error_open;
4238 }
4239
4240 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004241 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004242 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004243 case 0:
4244 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
4245 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07004246 case 8000:
4247 case 16000:
4248 case 48000:
4249 out->sample_rate = config->sample_rate;
4250 break;
4251 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004252 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
4253 config->sample_rate);
4254 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4255 ret = -EINVAL;
4256 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004257 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004258 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4259 switch (config->channel_mask) {
4260 case AUDIO_CHANNEL_NONE:
4261 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4262 break;
4263 case AUDIO_CHANNEL_OUT_STEREO:
4264 out->channel_mask = config->channel_mask;
4265 break;
4266 default:
4267 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
4268 config->channel_mask);
4269 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4270 ret = -EINVAL;
4271 break;
4272 }
4273 switch (config->format) {
4274 case AUDIO_FORMAT_DEFAULT:
4275 out->format = AUDIO_FORMAT_PCM_16_BIT;
4276 break;
4277 case AUDIO_FORMAT_PCM_16_BIT:
4278 out->format = config->format;
4279 break;
4280 default:
4281 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
4282 config->format);
4283 config->format = AUDIO_FORMAT_PCM_16_BIT;
4284 ret = -EINVAL;
4285 break;
4286 }
4287 if (ret != 0)
4288 goto error_open;
4289
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004290 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4291 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004292 out->config.rate = out->sample_rate;
4293 out->config.channels =
4294 audio_channel_count_from_out_mask(out->channel_mask);
4295 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004296 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004297 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
4298 switch (config->sample_rate) {
4299 case 0:
4300 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4301 break;
4302 case 8000:
4303 case 16000:
4304 case 32000:
4305 case 48000:
4306 out->sample_rate = config->sample_rate;
4307 break;
4308 default:
4309 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
4310 config->sample_rate);
4311 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4312 ret = -EINVAL;
4313 break;
4314 }
Eric Laurentad2dde92017-09-20 18:27:31 -07004315 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004316 switch (config->channel_mask) {
4317 case AUDIO_CHANNEL_NONE:
4318 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4319 break;
4320 case AUDIO_CHANNEL_OUT_STEREO:
4321 out->channel_mask = config->channel_mask;
4322 break;
4323 default:
4324 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
4325 config->channel_mask);
4326 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4327 ret = -EINVAL;
4328 break;
4329 }
4330 switch (config->format) {
4331 case AUDIO_FORMAT_DEFAULT:
4332 out->format = AUDIO_FORMAT_PCM_16_BIT;
4333 break;
4334 case AUDIO_FORMAT_PCM_16_BIT:
4335 out->format = config->format;
4336 break;
4337 default:
4338 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
4339 config->format);
4340 config->format = AUDIO_FORMAT_PCM_16_BIT;
4341 ret = -EINVAL;
4342 break;
4343 }
4344 if (ret != 0)
4345 goto error_open;
4346
vivek mehtaa68fea62017-06-08 19:04:02 -07004347 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07004348 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4349 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004350 out->config.rate = out->sample_rate;
4351 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07004352 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004353 out->sample_rate,
4354 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07004355 out->config.channels,
4356 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004357 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07004358 out->config.period_size = buffer_size / frame_size;
4359 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
4360 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004361 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004362 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07004363 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4364 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004365 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07004366 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
4367 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004368 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07004369 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004370 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004371 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004372 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004373 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4374 out->config = pcm_config_mmap_playback;
4375 out->stream.start = out_start;
4376 out->stream.stop = out_stop;
4377 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4378 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004379 } else {
4380 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4381 out->config = pcm_config_low_latency;
4382 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004383
4384 if (config->sample_rate == 0) {
4385 out->sample_rate = out->config.rate;
4386 } else {
4387 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004388 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004389 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
4390 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
4391 } else {
4392 out->channel_mask = config->channel_mask;
4393 }
4394 if (config->format == AUDIO_FORMAT_DEFAULT)
4395 out->format = audio_format_from_pcm_format(out->config.format);
4396 else if (!audio_is_linear_pcm(config->format)) {
4397 config->format = AUDIO_FORMAT_PCM_16_BIT;
4398 ret = -EINVAL;
4399 goto error_open;
4400 } else {
4401 out->format = config->format;
4402 }
4403
4404 out->config.rate = out->sample_rate;
4405 out->config.channels =
4406 audio_channel_count_from_out_mask(out->channel_mask);
4407 if (out->format != audio_format_from_pcm_format(out->config.format)) {
4408 out->config.format = pcm_format_from_audio_format(out->format);
4409 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004410 }
Kevin Rocard50eff892017-05-02 16:52:05 -07004411
4412 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
4413 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004414 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004415 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
4416 __func__, config->sample_rate, config->format, config->channel_mask);
4417 config->sample_rate = out->sample_rate;
4418 config->format = out->format;
4419 config->channel_mask = out->channel_mask;
4420 ret = -EINVAL;
4421 goto error_open;
4422 }
4423
Andy Hung6fcba9c2014-03-18 11:53:32 -07004424 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
4425 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004426
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004427 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004428 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004429 adev->primary_output = out;
4430 else {
4431 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004432 ret = -EEXIST;
4433 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004434 }
4435 }
4436
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004437 /* Check if this usecase is already existing */
4438 pthread_mutex_lock(&adev->lock);
4439 if (get_usecase_from_list(adev, out->usecase) != NULL) {
4440 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004441 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004442 ret = -EEXIST;
4443 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004444 }
4445 pthread_mutex_unlock(&adev->lock);
4446
4447 out->stream.common.get_sample_rate = out_get_sample_rate;
4448 out->stream.common.set_sample_rate = out_set_sample_rate;
4449 out->stream.common.get_buffer_size = out_get_buffer_size;
4450 out->stream.common.get_channels = out_get_channels;
4451 out->stream.common.get_format = out_get_format;
4452 out->stream.common.set_format = out_set_format;
4453 out->stream.common.standby = out_standby;
4454 out->stream.common.dump = out_dump;
4455 out->stream.common.set_parameters = out_set_parameters;
4456 out->stream.common.get_parameters = out_get_parameters;
4457 out->stream.common.add_audio_effect = out_add_audio_effect;
4458 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4459 out->stream.get_latency = out_get_latency;
4460 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004461#ifdef NO_AUDIO_OUT
4462 out->stream.write = out_write_for_no_output;
4463#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004464 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004465#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004466 out->stream.get_render_position = out_get_render_position;
4467 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004468 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004469
Eric Laurent0e46adf2016-12-16 12:49:24 -08004470 if (out->realtime)
4471 out->af_period_multiplier = af_period_multiplier;
4472 else
4473 out->af_period_multiplier = 1;
4474
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004475 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004476 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004477 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004478
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004479 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004480 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004481 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4482
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004483 config->format = out->stream.common.get_format(&out->stream.common);
4484 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4485 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4486
Kevin Rocarda325aa22018-04-03 09:15:52 -07004487 register_format(out->format, out->supported_formats);
4488 register_channel_mask(out->channel_mask, out->supported_channel_masks);
4489 register_sample_rate(out->sample_rate, out->supported_sample_rates);
4490
Andy Hunga452b0a2017-03-15 14:51:15 -07004491 out->error_log = error_log_create(
4492 ERROR_LOG_ENTRIES,
4493 1000000000 /* aggregate consecutive identical errors within one second in ns */);
4494
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004495 /*
4496 By locking output stream before registering, we allow the callback
4497 to update stream's state only after stream's initial state is set to
4498 adev state.
4499 */
4500 lock_output_stream(out);
4501 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4502 pthread_mutex_lock(&adev->lock);
4503 out->card_status = adev->card_status;
4504 pthread_mutex_unlock(&adev->lock);
4505 pthread_mutex_unlock(&out->lock);
4506
vivek mehta4a824772017-06-08 19:05:49 -07004507 stream_app_type_cfg_init(&out->app_type_cfg);
4508
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004509 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004510
Eric Laurent994a6932013-07-17 11:51:42 -07004511 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004512 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004513
4514error_open:
4515 free(out);
4516 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07004517 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004518 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004519}
4520
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004521static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004522 struct audio_stream_out *stream)
4523{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004524 struct stream_out *out = (struct stream_out *)stream;
4525 struct audio_device *adev = out->dev;
4526
Eric Laurent994a6932013-07-17 11:51:42 -07004527 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004528
4529 // must deregister from sndmonitor first to prevent races
4530 // between the callback and close_stream
4531 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004532 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004533 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
4534 destroy_offload_callback_thread(out);
4535
4536 if (out->compr_config.codec != NULL)
4537 free(out->compr_config.codec);
4538 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004539
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004540 out->a2dp_compress_mute = false;
4541
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004542 if (adev->voice_tx_output == out)
4543 adev->voice_tx_output = NULL;
4544
Andy Hunga452b0a2017-03-15 14:51:15 -07004545 error_log_destroy(out->error_log);
4546 out->error_log = NULL;
4547
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004548 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004549 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004550 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004551 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004552 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004553}
4554
4555static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4556{
4557 struct audio_device *adev = (struct audio_device *)dev;
4558 struct str_parms *parms;
4559 char *str;
4560 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004561 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004562 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07004563 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004564
Joe Onorato188b6222016-03-01 11:02:27 -08004565 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004566
4567 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004568
4569 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004570 status = voice_set_parameters(adev, parms);
4571 if (status != 0) {
4572 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004573 }
4574
4575 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4576 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07004577 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004578 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4579 adev->bluetooth_nrec = true;
4580 else
4581 adev->bluetooth_nrec = false;
4582 }
4583
4584 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4585 if (ret >= 0) {
4586 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4587 adev->screen_off = false;
4588 else
4589 adev->screen_off = true;
4590 }
4591
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004592 ret = str_parms_get_int(parms, "rotation", &val);
4593 if (ret >= 0) {
4594 bool reverse_speakers = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004595 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004596 // FIXME: note that the code below assumes that the speakers are in the correct placement
4597 // relative to the user when the device is rotated 90deg from its default rotation. This
4598 // assumption is device-specific, not platform-specific like this code.
4599 case 270:
4600 reverse_speakers = true;
4601 break;
4602 case 0:
4603 case 90:
4604 case 180:
4605 break;
4606 default:
4607 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07004608 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004609 }
Eric Laurent03f09432014-03-25 18:09:11 -07004610 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004611 // check and set swap
4612 // - check if orientation changed and speaker active
4613 // - set rotation and cache the rotation value
4614 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004615 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004616 }
4617
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004618 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4619 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004620 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004621 }
4622
David Linee3fe402017-03-13 10:00:42 -07004623 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4624 if (ret >= 0) {
4625 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004626 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004627 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4628 if (ret >= 0) {
4629 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004630 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004631 }
Eric Laurent99dab492017-06-17 15:19:08 -07004632 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004633 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4634 if (ret >= 0) {
4635 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004636 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004637 }
4638 }
4639 }
4640
4641 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4642 if (ret >= 0) {
4643 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004644 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004645 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4646 if (ret >= 0) {
4647 const int card = atoi(value);
4648
Eric Laurent99dab492017-06-17 15:19:08 -07004649 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004650 }
Eric Laurent99dab492017-06-17 15:19:08 -07004651 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004652 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4653 if (ret >= 0) {
4654 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004655 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004656 }
4657 }
4658 }
4659
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004660 audio_extn_hfp_set_parameters(adev, parms);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004661 audio_extn_a2dp_set_parameters(parms);
4662 // reconfigure should be done only after updating A2DP state in audio extension
4663 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4664 if (ret >= 0) {
4665 struct audio_usecase *usecase;
4666 struct listnode *node;
4667 list_for_each(node, &adev->usecase_list) {
4668 usecase = node_to_item(node, struct audio_usecase, list);
4669 if ((usecase->type == PCM_PLAYBACK) &&
4670 (usecase->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP)) {
4671 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
4672
4673 pthread_mutex_unlock(&adev->lock);
4674 lock_output_stream(usecase->stream.out);
4675 pthread_mutex_lock(&adev->lock);
4676 audio_extn_a2dp_set_handoff_mode(true);
4677 // force device switch to reconfigure encoder
4678 select_devices(adev, usecase->id);
4679 audio_extn_a2dp_set_handoff_mode(false);
4680 pthread_mutex_unlock(&usecase->stream.out->lock);
4681 break;
4682 }
4683 }
4684 }
4685
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004686done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004687 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004688 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004689 ALOGV("%s: exit with code(%d)", __func__, status);
4690 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004691}
4692
4693static char* adev_get_parameters(const struct audio_hw_device *dev,
4694 const char *keys)
4695{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004696 struct audio_device *adev = (struct audio_device *)dev;
4697 struct str_parms *reply = str_parms_create();
4698 struct str_parms *query = str_parms_create_str(keys);
4699 char *str;
4700
4701 pthread_mutex_lock(&adev->lock);
4702
4703 voice_get_parameters(adev, query, reply);
4704 str = str_parms_to_str(reply);
4705 str_parms_destroy(query);
4706 str_parms_destroy(reply);
4707
4708 pthread_mutex_unlock(&adev->lock);
4709 ALOGV("%s: exit: returns - %s", __func__, str);
4710 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004711}
4712
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004713static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004714{
4715 return 0;
4716}
4717
Haynes Mathew George5191a852013-09-11 14:19:36 -07004718static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4719{
4720 int ret;
4721 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004722
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004723 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4724
Haynes Mathew George5191a852013-09-11 14:19:36 -07004725 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004726 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004727 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004728
Haynes Mathew George5191a852013-09-11 14:19:36 -07004729 return ret;
4730}
4731
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004732static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004733{
4734 return -ENOSYS;
4735}
4736
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004737static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4738 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004739{
4740 return -ENOSYS;
4741}
4742
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004743static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004744{
4745 return -ENOSYS;
4746}
4747
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004748static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004749{
4750 return -ENOSYS;
4751}
4752
4753static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4754{
4755 struct audio_device *adev = (struct audio_device *)dev;
4756
4757 pthread_mutex_lock(&adev->lock);
4758 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004759 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004760 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004761 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4762 voice_is_in_call(adev)) {
4763 voice_stop_call(adev);
4764 adev->current_call_output = NULL;
4765 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004766 }
4767 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004768
4769 audio_extn_extspk_set_mode(adev->extspk, mode);
4770
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004771 return 0;
4772}
4773
4774static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4775{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004776 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004777 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004778
Eric Laurent2bafff12016-03-17 12:17:23 -07004779 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004780 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004781 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4782 ret = audio_extn_hfp_set_mic_mute(adev, state);
4783 } else {
4784 ret = voice_set_mic_mute(adev, state);
4785 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004786 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004787 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004788
4789 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004790}
4791
4792static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4793{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004794 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004795 return 0;
4796}
4797
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004798static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004799 const struct audio_config *config)
4800{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004801 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004802
Eric Laurent74b55762017-07-09 17:04:53 -07004803 /* Don't know if USB HIFI in this context so use true to be conservative */
4804 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4805 true /*is_usb_hifi */) != 0)
4806 return 0;
4807
vivek mehtaa68fea62017-06-08 19:04:02 -07004808 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4809 config->sample_rate, config->format,
4810 channel_count,
4811 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004812}
4813
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004814static bool adev_input_allow_hifi_record(struct audio_device *adev,
4815 audio_devices_t devices,
4816 audio_input_flags_t flags,
4817 audio_source_t source) {
4818 const bool allowed = true;
4819
4820 if (!audio_is_usb_in_device(devices))
4821 return !allowed;
4822
4823 switch (flags) {
4824 case AUDIO_INPUT_FLAG_NONE:
4825 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4826 break;
4827 default:
4828 return !allowed;
4829 }
4830
4831 switch (source) {
4832 case AUDIO_SOURCE_DEFAULT:
4833 case AUDIO_SOURCE_MIC:
4834 case AUDIO_SOURCE_UNPROCESSED:
4835 break;
4836 default:
4837 return !allowed;
4838 }
4839
4840 switch (adev->mode) {
4841 case 0:
4842 break;
4843 default:
4844 return !allowed;
4845 }
4846
4847 return allowed;
4848}
4849
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004850static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004851 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004852 audio_devices_t devices,
4853 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004854 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004855 audio_input_flags_t flags,
4856 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004857 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004858{
4859 struct audio_device *adev = (struct audio_device *)dev;
4860 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004861 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004862 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004863 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004864 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004865 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4866 devices,
4867 flags,
4868 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004869 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004870 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004871
Andy Hungd9653bd2017-08-01 19:31:39 -07004872 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
4873 return -ENOSYS;
4874 }
4875
Eric Laurent74b55762017-07-09 17:04:53 -07004876 if (!(is_usb_dev && may_use_hifi_record)) {
4877 if (config->sample_rate == 0)
4878 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4879 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4880 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4881 if (config->format == AUDIO_FORMAT_DEFAULT)
4882 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004883
Eric Laurent74b55762017-07-09 17:04:53 -07004884 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
4885
4886 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
4887 return -EINVAL;
4888 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004889
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004890 if (audio_extn_tfa_98xx_is_supported() &&
4891 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004892 return -EINVAL;
4893
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004894 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4895
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004896 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004897 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004898
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004899 in->stream.common.get_sample_rate = in_get_sample_rate;
4900 in->stream.common.set_sample_rate = in_set_sample_rate;
4901 in->stream.common.get_buffer_size = in_get_buffer_size;
4902 in->stream.common.get_channels = in_get_channels;
4903 in->stream.common.get_format = in_get_format;
4904 in->stream.common.set_format = in_set_format;
4905 in->stream.common.standby = in_standby;
4906 in->stream.common.dump = in_dump;
4907 in->stream.common.set_parameters = in_set_parameters;
4908 in->stream.common.get_parameters = in_get_parameters;
4909 in->stream.common.add_audio_effect = in_add_audio_effect;
4910 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4911 in->stream.set_gain = in_set_gain;
4912 in->stream.read = in_read;
4913 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08004914 in->stream.get_capture_position = in_get_capture_position;
jiabin8962a4d2018-03-19 18:21:24 -07004915 in->stream.get_active_microphones = in_get_active_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004916
4917 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004918 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004919 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004920 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004921 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004922 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004923
Haynes Mathew George569b7482017-05-08 14:44:27 -07004924 if (is_usb_dev && may_use_hifi_record) {
4925 /* HiFi record selects an appropriate format, channel, rate combo
4926 depending on sink capabilities*/
4927 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
4928 &config->format,
4929 &in->supported_formats[0],
4930 MAX_SUPPORTED_FORMATS,
4931 &config->channel_mask,
4932 &in->supported_channel_masks[0],
4933 MAX_SUPPORTED_CHANNEL_MASKS,
4934 &config->sample_rate,
4935 &in->supported_sample_rates[0],
4936 MAX_SUPPORTED_SAMPLE_RATES);
4937 if (ret != 0) {
4938 ret = -EINVAL;
4939 goto err_open;
4940 }
Eric Laurent74b55762017-07-09 17:04:53 -07004941 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004942 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07004943 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07004944 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
4945 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
4946 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4947 bool ret_error = false;
4948 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4949 from HAL is 8_24
4950 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4951 8_24 return error indicating supported format is 8_24
4952 *> In case of any other source requesting 24 bit or float return error
4953 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07004954
vivek mehta57ff9b52016-04-28 14:13:08 -07004955 on error flinger will retry with supported format passed
4956 */
4957 if (source != AUDIO_SOURCE_UNPROCESSED) {
4958 config->format = AUDIO_FORMAT_PCM_16_BIT;
4959 ret_error = true;
4960 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
4961 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
4962 ret_error = true;
4963 }
4964
4965 if (ret_error) {
4966 ret = -EINVAL;
4967 goto err_open;
4968 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004969 }
4970
vivek mehta57ff9b52016-04-28 14:13:08 -07004971 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07004972 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07004973
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004974 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004975 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
4976 if (config->sample_rate == 0)
4977 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4978 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4979 config->sample_rate != 8000) {
4980 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4981 ret = -EINVAL;
4982 goto err_open;
4983 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004984
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004985 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4986 config->format = AUDIO_FORMAT_PCM_16_BIT;
4987 ret = -EINVAL;
4988 goto err_open;
4989 }
4990
4991 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4992 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07004993 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004994 } else if (is_usb_dev && may_use_hifi_record) {
4995 in->usecase = USECASE_AUDIO_RECORD_HIFI;
4996 in->config = pcm_config_audio_capture;
4997 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004998 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4999 config->sample_rate,
5000 config->format,
5001 channel_count,
5002 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005003 in->config.period_size = buffer_size / frame_size;
5004 in->config.rate = config->sample_rate;
5005 in->af_period_multiplier = 1;
5006 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005007 } else {
5008 in->usecase = USECASE_AUDIO_RECORD;
5009 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08005010 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005011 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07005012#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005013 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07005014#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08005015 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005016 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08005017 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005018 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005019 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5020 config->sample_rate,
5021 config->format,
5022 channel_count,
5023 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005024 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005025 in->config.rate = config->sample_rate;
5026 in->af_period_multiplier = 1;
5027 } else {
5028 // period size is left untouched for rt mode playback
5029 in->config = pcm_config_audio_capture_rt;
5030 in->af_period_multiplier = af_period_multiplier;
5031 }
5032 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
5033 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005034 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08005035 in->usecase = USECASE_AUDIO_RECORD_MMAP;
5036 in->config = pcm_config_mmap_capture;
5037 in->stream.start = in_start;
5038 in->stream.stop = in_stop;
5039 in->stream.create_mmap_buffer = in_create_mmap_buffer;
5040 in->stream.get_mmap_position = in_get_mmap_position;
5041 in->af_period_multiplier = 1;
5042 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07005043 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07005044 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07005045 (config->sample_rate == 8000 ||
5046 config->sample_rate == 16000 ||
5047 config->sample_rate == 32000 ||
5048 config->sample_rate == 48000) &&
5049 channel_count == 1) {
5050 in->usecase = USECASE_AUDIO_RECORD_VOIP;
5051 in->config = pcm_config_audio_capture;
5052 frame_size = audio_stream_in_frame_size(&in->stream);
5053 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
5054 config->sample_rate,
5055 config->format,
5056 channel_count, false /*is_low_latency*/);
5057 in->config.period_size = buffer_size / frame_size;
5058 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
5059 in->config.rate = config->sample_rate;
5060 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005061 } else {
5062 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005063 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005064 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5065 config->sample_rate,
5066 config->format,
5067 channel_count,
5068 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005069 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005070 in->config.rate = config->sample_rate;
5071 in->af_period_multiplier = 1;
5072 }
5073 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
5074 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005075 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08005076
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005077 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07005078 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005079
Kevin Rocarda325aa22018-04-03 09:15:52 -07005080
5081 register_format(in->format, in->supported_formats);
5082 register_channel_mask(in->channel_mask, in->supported_channel_masks);
5083 register_sample_rate(in->sample_rate, in->supported_sample_rates);
5084
Andy Hungd13f0d32017-06-12 13:58:37 -07005085 in->error_log = error_log_create(
5086 ERROR_LOG_ENTRIES,
5087 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
5088
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005089 /* This stream could be for sound trigger lab,
5090 get sound trigger pcm if present */
5091 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005092
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005093 lock_input_stream(in);
5094 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5095 pthread_mutex_lock(&adev->lock);
5096 in->card_status = adev->card_status;
5097 pthread_mutex_unlock(&adev->lock);
5098 pthread_mutex_unlock(&in->lock);
5099
vivek mehta4a824772017-06-08 19:05:49 -07005100 stream_app_type_cfg_init(&in->app_type_cfg);
5101
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005102 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005103 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005104 return 0;
5105
5106err_open:
5107 free(in);
5108 *stream_in = NULL;
5109 return ret;
5110}
5111
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005112static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005113 struct audio_stream_in *stream)
5114{
Andy Hungd13f0d32017-06-12 13:58:37 -07005115 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005116 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005117
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005118 // must deregister from sndmonitor first to prevent races
5119 // between the callback and close_stream
5120 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005121 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07005122
5123 error_log_destroy(in->error_log);
5124 in->error_log = NULL;
5125
Andy Hung0dbb52b2017-08-09 13:51:38 -07005126 pthread_mutex_destroy(&in->pre_lock);
5127 pthread_mutex_destroy(&in->lock);
5128
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005129 free(stream);
5130
5131 return;
5132}
5133
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005134static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005135{
5136 return 0;
5137}
5138
Andy Hung31aca912014-03-20 17:14:59 -07005139/* verifies input and output devices and their capabilities.
5140 *
5141 * This verification is required when enabling extended bit-depth or
5142 * sampling rates, as not all qcom products support it.
5143 *
5144 * Suitable for calling only on initialization such as adev_open().
5145 * It fills the audio_device use_case_table[] array.
5146 *
5147 * Has a side-effect that it needs to configure audio routing / devices
5148 * in order to power up the devices and read the device parameters.
5149 * It does not acquire any hw device lock. Should restore the devices
5150 * back to "normal state" upon completion.
5151 */
5152static int adev_verify_devices(struct audio_device *adev)
5153{
5154 /* enumeration is a bit difficult because one really wants to pull
5155 * the use_case, device id, etc from the hidden pcm_device_table[].
5156 * In this case there are the following use cases and device ids.
5157 *
5158 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
5159 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005160 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07005161 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
5162 * [USECASE_AUDIO_RECORD] = {0, 0},
5163 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
5164 * [USECASE_VOICE_CALL] = {2, 2},
5165 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005166 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07005167 * USECASE_VOICE_CALL omitted, but possible for either input or output.
5168 */
5169
5170 /* should be the usecases enabled in adev_open_input_stream() */
5171 static const int test_in_usecases[] = {
5172 USECASE_AUDIO_RECORD,
5173 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
5174 };
5175 /* should be the usecases enabled in adev_open_output_stream()*/
5176 static const int test_out_usecases[] = {
5177 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
5178 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
5179 };
5180 static const usecase_type_t usecase_type_by_dir[] = {
5181 PCM_PLAYBACK,
5182 PCM_CAPTURE,
5183 };
5184 static const unsigned flags_by_dir[] = {
5185 PCM_OUT,
5186 PCM_IN,
5187 };
5188
5189 size_t i;
5190 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005191 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07005192 char info[512]; /* for possible debug info */
5193
5194 for (dir = 0; dir < 2; ++dir) {
5195 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
5196 const unsigned flags_dir = flags_by_dir[dir];
5197 const size_t testsize =
5198 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
5199 const int *testcases =
5200 dir ? test_in_usecases : test_out_usecases;
5201 const audio_devices_t audio_device =
5202 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
5203
5204 for (i = 0; i < testsize; ++i) {
5205 const audio_usecase_t audio_usecase = testcases[i];
5206 int device_id;
5207 snd_device_t snd_device;
5208 struct pcm_params **pparams;
5209 struct stream_out out;
5210 struct stream_in in;
5211 struct audio_usecase uc_info;
5212 int retval;
5213
5214 pparams = &adev->use_case_table[audio_usecase];
5215 pcm_params_free(*pparams); /* can accept null input */
5216 *pparams = NULL;
5217
5218 /* find the device ID for the use case (signed, for error) */
5219 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
5220 if (device_id < 0)
5221 continue;
5222
5223 /* prepare structures for device probing */
5224 memset(&uc_info, 0, sizeof(uc_info));
5225 uc_info.id = audio_usecase;
5226 uc_info.type = usecase_type;
5227 if (dir) {
5228 adev->active_input = &in;
5229 memset(&in, 0, sizeof(in));
5230 in.device = audio_device;
5231 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
5232 uc_info.stream.in = &in;
5233 } else {
5234 adev->active_input = NULL;
5235 }
5236 memset(&out, 0, sizeof(out));
5237 out.devices = audio_device; /* only field needed in select_devices */
5238 uc_info.stream.out = &out;
5239 uc_info.devices = audio_device;
5240 uc_info.in_snd_device = SND_DEVICE_NONE;
5241 uc_info.out_snd_device = SND_DEVICE_NONE;
5242 list_add_tail(&adev->usecase_list, &uc_info.list);
5243
5244 /* select device - similar to start_(in/out)put_stream() */
5245 retval = select_devices(adev, audio_usecase);
5246 if (retval >= 0) {
5247 *pparams = pcm_params_get(card_id, device_id, flags_dir);
5248#if LOG_NDEBUG == 0
5249 if (*pparams) {
5250 ALOGV("%s: (%s) card %d device %d", __func__,
5251 dir ? "input" : "output", card_id, device_id);
5252 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07005253 } else {
5254 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
5255 }
5256#endif
5257 }
5258
5259 /* deselect device - similar to stop_(in/out)put_stream() */
5260 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07005261 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07005262 /* 2. Disable the rx device */
5263 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07005264 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07005265 list_remove(&uc_info.list);
5266 }
5267 }
5268 adev->active_input = NULL; /* restore adev state */
5269 return 0;
5270}
5271
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005272static int adev_close(hw_device_t *device)
5273{
Andy Hung31aca912014-03-20 17:14:59 -07005274 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005275 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005276
5277 if (!adev)
5278 return 0;
5279
5280 pthread_mutex_lock(&adev_init_lock);
5281
5282 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005283 audio_extn_snd_mon_unregister_listener(adev);
5284 audio_extn_tfa_98xx_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005285 audio_route_free(adev->audio_route);
5286 free(adev->snd_dev_ref_cnt);
5287 platform_deinit(adev->platform);
5288 audio_extn_extspk_deinit(adev->extspk);
5289 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005290 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005291 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
5292 pcm_params_free(adev->use_case_table[i]);
5293 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005294 if (adev->adm_deinit)
5295 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005296 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005297 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07005298 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07005299
5300 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005301
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005302 return 0;
5303}
5304
Glenn Kasten4f993392014-05-14 07:30:48 -07005305/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5306 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5307 * just that it _might_ work.
5308 */
5309static int period_size_is_plausible_for_low_latency(int period_size)
5310{
5311 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005312 case 48:
5313 case 96:
5314 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07005315 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005316 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07005317 case 240:
5318 case 320:
5319 case 480:
5320 return 1;
5321 default:
5322 return 0;
5323 }
5324}
5325
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005326static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
5327{
5328 int card;
5329 card_status_t status;
5330
5331 if (!parms)
5332 return;
5333
5334 if (parse_snd_card_status(parms, &card, &status) < 0)
5335 return;
5336
5337 pthread_mutex_lock(&adev->lock);
5338 bool valid_cb = (card == adev->snd_card);
5339 if (valid_cb) {
5340 if (adev->card_status != status) {
5341 adev->card_status = status;
5342 platform_snd_card_update(adev->platform, status);
5343 }
5344 }
5345 pthread_mutex_unlock(&adev->lock);
5346 return;
5347}
5348
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005349/* out and adev lock held */
5350static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
5351{
5352 struct audio_usecase *uc_info;
5353 float left_p;
5354 float right_p;
5355 audio_devices_t devices;
5356
5357 uc_info = get_usecase_from_list(adev, out->usecase);
5358 if (uc_info == NULL) {
5359 ALOGE("%s: Could not find the usecase (%d) in the list",
5360 __func__, out->usecase);
5361 return -EINVAL;
5362 }
5363
5364 ALOGD("%s: enter: usecase(%d: %s)", __func__,
5365 out->usecase, use_case_table[out->usecase]);
5366
5367 if (restore) {
5368 // restore A2DP device for active usecases and unmute if required
5369 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
5370 !is_a2dp_device(uc_info->out_snd_device)) {
5371 ALOGD("%s: restoring A2DP and unmuting stream", __func__);
5372 select_devices(adev, uc_info->id);
5373 pthread_mutex_lock(&out->compr_mute_lock);
5374 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5375 (out->a2dp_compress_mute)) {
5376 out->a2dp_compress_mute = false;
5377 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5378 }
5379 pthread_mutex_unlock(&out->compr_mute_lock);
5380 }
5381 } else {
5382 // mute compress stream if suspended
5383 pthread_mutex_lock(&out->compr_mute_lock);
5384 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5385 (!out->a2dp_compress_mute)) {
5386 if (!out->standby) {
5387 ALOGD("%s: selecting speaker and muting stream", __func__);
5388 devices = out->devices;
5389 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
5390 left_p = out->volume_l;
5391 right_p = out->volume_r;
5392 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5393 compress_pause(out->compr);
5394 set_compr_volume(&out->stream, 0.0f, 0.0f);
5395 out->a2dp_compress_mute = true;
5396 select_devices(adev, out->usecase);
5397 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5398 compress_resume(out->compr);
5399 out->devices = devices;
5400 out->volume_l = left_p;
5401 out->volume_r = right_p;
5402 }
5403 }
5404 pthread_mutex_unlock(&out->compr_mute_lock);
5405 }
5406 ALOGV("%s: exit", __func__);
5407 return 0;
5408}
5409
5410int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
5411{
5412 int ret = 0;
5413
5414 lock_output_stream(out);
5415 pthread_mutex_lock(&adev->lock);
5416
5417 ret = check_a2dp_restore_l(adev, out, restore);
5418
5419 pthread_mutex_unlock(&adev->lock);
5420 pthread_mutex_unlock(&out->lock);
5421 return ret;
5422}
5423
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005424static int adev_open(const hw_module_t *module, const char *name,
5425 hw_device_t **device)
5426{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005427 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005428
Eric Laurent2bafff12016-03-17 12:17:23 -07005429 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005430 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005431 pthread_mutex_lock(&adev_init_lock);
5432 if (audio_device_ref_count != 0) {
5433 *device = &adev->device.common;
5434 audio_device_ref_count++;
5435 ALOGV("%s: returning existing instance of adev", __func__);
5436 ALOGV("%s: exit", __func__);
5437 pthread_mutex_unlock(&adev_init_lock);
5438 return 0;
5439 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005440 adev = calloc(1, sizeof(struct audio_device));
5441
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005442 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5443
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005444 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5445 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5446 adev->device.common.module = (struct hw_module_t *)module;
5447 adev->device.common.close = adev_close;
5448
5449 adev->device.init_check = adev_init_check;
5450 adev->device.set_voice_volume = adev_set_voice_volume;
5451 adev->device.set_master_volume = adev_set_master_volume;
5452 adev->device.get_master_volume = adev_get_master_volume;
5453 adev->device.set_master_mute = adev_set_master_mute;
5454 adev->device.get_master_mute = adev_get_master_mute;
5455 adev->device.set_mode = adev_set_mode;
5456 adev->device.set_mic_mute = adev_set_mic_mute;
5457 adev->device.get_mic_mute = adev_get_mic_mute;
5458 adev->device.set_parameters = adev_set_parameters;
5459 adev->device.get_parameters = adev_get_parameters;
5460 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5461 adev->device.open_output_stream = adev_open_output_stream;
5462 adev->device.close_output_stream = adev_close_output_stream;
5463 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005464
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005465 adev->device.close_input_stream = adev_close_input_stream;
5466 adev->device.dump = adev_dump;
jiabin8962a4d2018-03-19 18:21:24 -07005467 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005468
5469 /* Set the default route before the PCM stream is opened */
5470 pthread_mutex_lock(&adev->lock);
5471 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005472 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005473 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005474 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005475 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005476 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005477 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005478 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005479 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005480 pthread_mutex_unlock(&adev->lock);
5481
5482 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005483 adev->platform = platform_init(adev);
5484 if (!adev->platform) {
5485 free(adev->snd_dev_ref_cnt);
5486 free(adev);
5487 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5488 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005489 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005490 return -EINVAL;
5491 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05005492 adev->extspk = audio_extn_extspk_init(adev);
5493
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005494 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5495 if (adev->visualizer_lib == NULL) {
5496 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5497 } else {
5498 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5499 adev->visualizer_start_output =
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07005500 (int (*)(audio_io_handle_t, int, int, int))dlsym(adev->visualizer_lib,
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005501 "visualizer_hal_start_output");
5502 adev->visualizer_stop_output =
5503 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5504 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07005505 }
5506
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005507 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5508 if (adev->offload_effects_lib == NULL) {
5509 ALOGW("%s: DLOPEN failed for %s", __func__,
5510 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5511 } else {
5512 ALOGV("%s: DLOPEN successful for %s", __func__,
5513 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5514 adev->offload_effects_start_output =
5515 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5516 "offload_effects_bundle_hal_start_output");
5517 adev->offload_effects_stop_output =
5518 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5519 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07005520 }
5521
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005522 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5523 if (adev->adm_lib == NULL) {
5524 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5525 } else {
5526 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5527 adev->adm_init = (adm_init_t)
5528 dlsym(adev->adm_lib, "adm_init");
5529 adev->adm_deinit = (adm_deinit_t)
5530 dlsym(adev->adm_lib, "adm_deinit");
5531 adev->adm_register_input_stream = (adm_register_input_stream_t)
5532 dlsym(adev->adm_lib, "adm_register_input_stream");
5533 adev->adm_register_output_stream = (adm_register_output_stream_t)
5534 dlsym(adev->adm_lib, "adm_register_output_stream");
5535 adev->adm_deregister_stream = (adm_deregister_stream_t)
5536 dlsym(adev->adm_lib, "adm_deregister_stream");
5537 adev->adm_request_focus = (adm_request_focus_t)
5538 dlsym(adev->adm_lib, "adm_request_focus");
5539 adev->adm_abandon_focus = (adm_abandon_focus_t)
5540 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08005541 adev->adm_set_config = (adm_set_config_t)
5542 dlsym(adev->adm_lib, "adm_set_config");
5543 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5544 dlsym(adev->adm_lib, "adm_request_focus_v2");
5545 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5546 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5547 adev->adm_on_routing_change = (adm_on_routing_change_t)
5548 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005549 }
5550
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005551 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005552 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005553
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005554 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005555
Andy Hung31aca912014-03-20 17:14:59 -07005556 if (k_enable_extended_precision)
5557 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005558
Glenn Kasten4f993392014-05-14 07:30:48 -07005559 char value[PROPERTY_VALUE_MAX];
5560 int trial;
5561 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5562 trial = atoi(value);
5563 if (period_size_is_plausible_for_low_latency(trial)) {
5564 pcm_config_low_latency.period_size = trial;
5565 pcm_config_low_latency.start_threshold = trial / 4;
5566 pcm_config_low_latency.avail_min = trial / 4;
5567 configured_low_latency_capture_period_size = trial;
5568 }
5569 }
5570 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5571 trial = atoi(value);
5572 if (period_size_is_plausible_for_low_latency(trial)) {
5573 configured_low_latency_capture_period_size = trial;
5574 }
5575 }
5576
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005577 // commented as full set of app type cfg is sent from platform
5578 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005579 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005580
5581 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5582 af_period_multiplier = atoi(value);
5583 if (af_period_multiplier < 0) {
5584 af_period_multiplier = 2;
5585 } else if (af_period_multiplier > 4) {
5586 af_period_multiplier = 4;
5587 }
5588 ALOGV("new period_multiplier = %d", af_period_multiplier);
5589 }
5590
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005591 audio_extn_tfa_98xx_init(adev);
5592
vivek mehta1a9b7c02015-06-25 11:49:38 -07005593 pthread_mutex_unlock(&adev_init_lock);
5594
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005595 if (adev->adm_init)
5596 adev->adm_data = adev->adm_init();
5597
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005598 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005599 audio_extn_snd_mon_init();
5600 pthread_mutex_lock(&adev->lock);
5601 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
5602 adev->card_status = CARD_STATUS_ONLINE;
5603 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005604 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005605
Eric Laurent2bafff12016-03-17 12:17:23 -07005606 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005607 return 0;
5608}
5609
5610static struct hw_module_methods_t hal_module_methods = {
5611 .open = adev_open,
5612};
5613
5614struct audio_module HAL_MODULE_INFO_SYM = {
5615 .common = {
5616 .tag = HARDWARE_MODULE_TAG,
5617 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5618 .hal_api_version = HARDWARE_HAL_API_VERSION,
5619 .id = AUDIO_HARDWARE_MODULE_ID,
5620 .name = "QCOM Audio HAL",
5621 .author = "Code Aurora Forum",
5622 .methods = &hal_module_methods,
5623 },
5624};