blob: 231b159a13eebc2fbe51c1b05985a8ab0545c552 [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
2012 if (adev->visualizer_start_output != NULL)
2013 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2014 if (adev->offload_effects_start_output != NULL)
2015 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
2016 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002017 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002018 ALOGE("%s: pcm stream not ready", __func__);
2019 goto error_open;
2020 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002021 ret = pcm_start(out->pcm);
2022 if (ret < 0) {
2023 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2024 goto error_open;
2025 }
2026 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07002027 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002028 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002029
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002030 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2031 flags |= PCM_MMAP | PCM_NOIRQ;
2032 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002033 } else if (out->realtime) {
2034 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07002035 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002036
2037 while (1) {
2038 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2039 flags, &out->config);
2040 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2041 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2042 if (out->pcm != NULL) {
2043 pcm_close(out->pcm);
2044 out->pcm = NULL;
2045 }
2046 if (pcm_open_retry_count-- == 0) {
2047 ret = -EIO;
2048 goto error_open;
2049 }
2050 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2051 continue;
2052 }
2053 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002054 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002055 ALOGV("%s: pcm_prepare", __func__);
2056 if (pcm_is_ready(out->pcm)) {
2057 ret = pcm_prepare(out->pcm);
2058 if (ret < 0) {
2059 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2060 pcm_close(out->pcm);
2061 out->pcm = NULL;
2062 goto error_open;
2063 }
2064 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002065 if (out->realtime) {
2066 ret = pcm_start(out->pcm);
2067 if (ret < 0) {
2068 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
2069 pcm_close(out->pcm);
2070 out->pcm = NULL;
2071 goto error_open;
2072 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002073 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002074 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002075 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08002076 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002077 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002078 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07002079
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002080 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2081 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2082 audio_low_latency_hint_start();
2083 }
2084
vivek mehtae59cfb22017-06-16 15:57:11 -07002085 // consider a scenario where on pause lower layers are tear down.
2086 // so on resume, swap mixer control need to be sent only when
2087 // backend is active, hence rather than sending from enable device
2088 // sending it from start of streamtream
2089
2090 platform_set_swap_channels(adev, true);
2091
Eric Laurent994a6932013-07-17 11:51:42 -07002092 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002093 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002094error_open:
Wei Wangf4837d52017-11-21 14:51:20 -08002095 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002096 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002097 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002098error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002099 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002100}
2101
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002102static int check_input_parameters(uint32_t sample_rate,
2103 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07002104 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002105{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002106 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2107 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002108 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2109 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002110 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2111 return -EINVAL;
2112 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002113
Eric Laurent74b55762017-07-09 17:04:53 -07002114 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2115 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002116 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002117 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002118 return -EINVAL;
2119 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002120
2121 switch (sample_rate) {
2122 case 8000:
2123 case 11025:
2124 case 12000:
2125 case 16000:
2126 case 22050:
2127 case 24000:
2128 case 32000:
2129 case 44100:
2130 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002131 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002132 break;
2133 default:
vivek mehtadae44712015-07-27 14:13:18 -07002134 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002135 return -EINVAL;
2136 }
2137
2138 return 0;
2139}
2140
Kevin Rocarda325aa22018-04-03 09:15:52 -07002141/** Add a value in a list if not already present.
2142 * @return true if value was successfully inserted or already present,
2143 * false if the list is full and does not contain the value.
2144 */
2145static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
2146 for (size_t i = 0; i < list_length; i++) {
2147 if (list[i] == value) return true; // value is already present
2148 if (list[i] == 0) { // no values in this slot
2149 list[i] = value;
2150 return true; // value inserted
2151 }
2152 }
2153 return false; // could not insert value
2154}
2155
2156/** Add channel_mask in supported_channel_masks if not already present.
2157 * @return true if channel_mask was successfully inserted or already present,
2158 * false if supported_channel_masks is full and does not contain channel_mask.
2159 */
2160static void register_channel_mask(audio_channel_mask_t channel_mask,
2161 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
2162 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
2163 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
2164}
2165
2166/** Add format in supported_formats if not already present.
2167 * @return true if format was successfully inserted or already present,
2168 * false if supported_formats is full and does not contain format.
2169 */
2170static void register_format(audio_format_t format,
2171 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
2172 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
2173 "%s: stream can not declare supporting its format %x", __func__, format);
2174}
2175/** Add sample_rate in supported_sample_rates if not already present.
2176 * @return true if sample_rate was successfully inserted or already present,
2177 * false if supported_sample_rates is full and does not contain sample_rate.
2178 */
2179static void register_sample_rate(uint32_t sample_rate,
2180 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
2181 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
2182 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
2183}
2184
vivek mehtaa68fea62017-06-08 19:04:02 -07002185static size_t get_stream_buffer_size(size_t duration_ms,
2186 uint32_t sample_rate,
2187 audio_format_t format,
2188 int channel_count,
2189 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002190{
2191 size_t size = 0;
2192
vivek mehtaa68fea62017-06-08 19:04:02 -07002193 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002194 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002195 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002196
2197 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002198
Glenn Kasten4f993392014-05-14 07:30:48 -07002199 /* make sure the size is multiple of 32 bytes
2200 * At 48 kHz mono 16-bit PCM:
2201 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2202 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2203 */
2204 size += 0x1f;
2205 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002206
2207 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002208}
2209
2210static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2211{
2212 struct stream_out *out = (struct stream_out *)stream;
2213
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002214 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002215}
2216
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002217static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002218{
2219 return -ENOSYS;
2220}
2221
2222static size_t out_get_buffer_size(const struct audio_stream *stream)
2223{
2224 struct stream_out *out = (struct stream_out *)stream;
2225
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002226 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2227 return out->compr_config.fragment_size;
2228 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002229 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002230 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002231}
2232
2233static uint32_t out_get_channels(const struct audio_stream *stream)
2234{
2235 struct stream_out *out = (struct stream_out *)stream;
2236
2237 return out->channel_mask;
2238}
2239
2240static audio_format_t out_get_format(const struct audio_stream *stream)
2241{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002242 struct stream_out *out = (struct stream_out *)stream;
2243
2244 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002245}
2246
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002247static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002248{
2249 return -ENOSYS;
2250}
2251
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002252/* must be called with out->lock locked */
2253static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002254{
2255 struct stream_out *out = (struct stream_out *)stream;
2256 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002257 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002258
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002259 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002260 if (adev->adm_deregister_stream)
2261 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002262 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002263 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002264 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2265 if (out->pcm) {
2266 pcm_close(out->pcm);
2267 out->pcm = NULL;
2268 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002269 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002270 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002271 out->playback_started = false;
2272 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002273 } else {
2274 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002275 out->gapless_mdata.encoder_delay = 0;
2276 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002277 if (out->compr != NULL) {
2278 compress_close(out->compr);
2279 out->compr = NULL;
2280 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002281 }
Phil Burkbc991042017-02-24 08:06:44 -08002282 if (do_stop) {
2283 stop_output_stream(out);
2284 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002285 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002286 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002287 return 0;
2288}
2289
2290static int out_standby(struct audio_stream *stream)
2291{
2292 struct stream_out *out = (struct stream_out *)stream;
2293
2294 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2295 out->usecase, use_case_table[out->usecase]);
2296
2297 lock_output_stream(out);
2298 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002299 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002300 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002301 return 0;
2302}
2303
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002304static int out_on_error(struct audio_stream *stream)
2305{
2306 struct stream_out *out = (struct stream_out *)stream;
2307 struct audio_device *adev = out->dev;
2308 bool do_standby = false;
2309
2310 lock_output_stream(out);
2311 if (!out->standby) {
2312 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2313 stop_compressed_output_l(out);
2314 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2315 } else
2316 do_standby = true;
2317 }
2318 pthread_mutex_unlock(&out->lock);
2319
2320 if (do_standby)
2321 return out_standby(&out->stream.common);
2322
2323 return 0;
2324}
2325
Andy Hung7401c7c2016-09-21 12:41:21 -07002326static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002327{
Andy Hung7401c7c2016-09-21 12:41:21 -07002328 struct stream_out *out = (struct stream_out *)stream;
2329
2330 // We try to get the lock for consistency,
2331 // but it isn't necessary for these variables.
2332 // If we're not in standby, we may be blocked on a write.
2333 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2334 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2335 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2336
2337 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002338 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002339 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002340
2341 // dump error info
2342 (void)error_log_dump(
2343 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002344
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002345 return 0;
2346}
2347
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002348static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2349{
2350 int ret = 0;
2351 char value[32];
2352 struct compr_gapless_mdata tmp_mdata;
2353
2354 if (!out || !parms) {
2355 return -EINVAL;
2356 }
2357
2358 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2359 if (ret >= 0) {
2360 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2361 } else {
2362 return -EINVAL;
2363 }
2364
2365 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2366 if (ret >= 0) {
2367 tmp_mdata.encoder_padding = atoi(value);
2368 } else {
2369 return -EINVAL;
2370 }
2371
2372 out->gapless_mdata = tmp_mdata;
2373 out->send_new_metadata = 1;
2374 ALOGV("%s new encoder delay %u and padding %u", __func__,
2375 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2376
2377 return 0;
2378}
2379
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002380static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2381{
2382 return out == adev->primary_output || out == adev->voice_tx_output;
2383}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002384
Kevin Rocard1e02c882017-08-09 15:26:07 -07002385static int get_alive_usb_card(struct str_parms* parms) {
2386 int card;
2387 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2388 !audio_extn_usb_alive(card)) {
2389 return card;
2390 }
2391 return -ENODEV;
2392}
2393
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002394static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2395{
2396 struct stream_out *out = (struct stream_out *)stream;
2397 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002398 struct audio_usecase *usecase;
2399 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002400 struct str_parms *parms;
2401 char value[32];
2402 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002403 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002404 int status = 0;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002405 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002406
Eric Laurent2e140aa2016-06-30 17:14:46 -07002407 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002408 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002409 parms = str_parms_create_str(kvpairs);
2410 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2411 if (ret >= 0) {
2412 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002413
Eric Laurenta1478072015-09-21 17:21:52 -07002414 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002415
2416 // The usb driver needs to be closed after usb device disconnection
2417 // otherwise audio is no longer played on the new usb devices.
2418 // By forcing the stream in standby, the usb stack refcount drops to 0
2419 // and the driver is closed.
2420 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD && val == AUDIO_DEVICE_NONE &&
2421 audio_is_usb_out_device(out->devices)) {
2422 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2423 out_standby_l(&out->stream.common);
2424 }
2425
Eric Laurent150dbfe2013-02-27 14:31:02 -08002426 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002427
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002428 /*
2429 * When HDMI cable is unplugged the music playback is paused and
2430 * the policy manager sends routing=0. But the audioflinger
2431 * continues to write data until standby time (3sec).
2432 * As the HDMI core is turned off, the write gets blocked.
2433 * Avoid this by routing audio to speaker until standby.
2434 */
2435 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2436 val == AUDIO_DEVICE_NONE) {
2437 val = AUDIO_DEVICE_OUT_SPEAKER;
2438 }
2439
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002440 /*
2441 * When A2DP is disconnected the
2442 * music playback is paused and the policy manager sends routing=0
2443 * But the audioflingercontinues to write data until standby time
2444 * (3sec). As BT is turned off, the write gets blocked.
2445 * Avoid this by routing audio to speaker until standby.
2446 */
2447 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2448 (val == AUDIO_DEVICE_NONE) &&
2449 !audio_extn_a2dp_is_ready()) {
2450 val = AUDIO_DEVICE_OUT_SPEAKER;
2451 }
2452
2453 /* To avoid a2dp to sco overlapping / BT device improper state
2454 * check with BT lib about a2dp streaming support before routing
2455 */
2456 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2457 if (!audio_extn_a2dp_is_ready()) {
2458 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
2459 //combo usecase just by pass a2dp
2460 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2461 bypass_a2dp = true;
2462 } else {
2463 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2464 /* update device to a2dp and don't route as BT returned error
2465 * However it is still possible a2dp routing called because
2466 * of current active device disconnection (like wired headset)
2467 */
2468 out->devices = val;
2469 pthread_mutex_unlock(&out->lock);
2470 pthread_mutex_unlock(&adev->lock);
2471 status = -ENOSYS;
2472 goto routing_fail;
2473 }
2474 }
2475 }
2476
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002477 audio_devices_t new_dev = val;
2478
2479 // Workaround: If routing to an non existing usb device, fail gracefully
2480 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002481 int card;
2482 if (audio_is_usb_out_device(new_dev) &&
2483 (card = get_alive_usb_card(parms)) >= 0) {
2484
2485 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002486 pthread_mutex_unlock(&adev->lock);
2487 pthread_mutex_unlock(&out->lock);
2488 status = -ENOSYS;
2489 goto routing_fail;
2490 }
2491
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002492 /*
2493 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002494 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002495 * the select_devices(). But how do we undo this?
2496 *
2497 * For example, music playback is active on headset (deep-buffer usecase)
2498 * and if we go to ringtones and select a ringtone, low-latency usecase
2499 * will be started on headset+speaker. As we can't enable headset+speaker
2500 * and headset devices at the same time, select_devices() switches the music
2501 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2502 * So when the ringtone playback is completed, how do we undo the same?
2503 *
2504 * We are relying on the out_set_parameters() call on deep-buffer output,
2505 * once the ringtone playback is ended.
2506 * NOTE: We should not check if the current devices are same as new devices.
2507 * Because select_devices() must be called to switch back the music
2508 * playback to headset.
2509 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002510 if (new_dev != AUDIO_DEVICE_NONE) {
2511 bool same_dev = out->devices == new_dev;
2512 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002513
Eric Laurenta7657192014-10-09 21:09:33 -07002514 if (output_drives_call(adev, out)) {
2515 if (!voice_is_in_call(adev)) {
2516 if (adev->mode == AUDIO_MODE_IN_CALL) {
2517 adev->current_call_output = out;
2518 ret = voice_start_call(adev);
2519 }
2520 } else {
2521 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002522 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002523 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002524 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002525
2526 if (!out->standby) {
2527 if (!same_dev) {
2528 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002529 // inform adm before actual routing to prevent glitches.
2530 if (adev->adm_on_routing_change) {
2531 adev->adm_on_routing_change(adev->adm_data,
2532 out->handle);
2533 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002534 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002535 if (!bypass_a2dp) {
2536 select_devices(adev, out->usecase);
2537 } else {
2538 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2539 select_devices(adev, out->usecase);
2540 out->devices = new_dev;
2541 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002542 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002543
2544 // on device switch force swap, lower functions will make sure
2545 // to check if swap is allowed or not.
2546
2547 if (!same_dev)
2548 platform_set_swap_channels(adev, true);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002549
2550 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2551 out->a2dp_compress_mute &&
2552 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
2553 pthread_mutex_lock(&out->compr_mute_lock);
2554 out->a2dp_compress_mute = false;
2555 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
2556 pthread_mutex_unlock(&out->compr_mute_lock);
2557 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002558 }
2559
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002560 }
2561
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002562 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002563 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002564
2565 /*handles device and call state changes*/
2566 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002567 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002568 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002569
2570 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2571 parse_compress_metadata(out, parms);
2572 }
2573
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002574 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002575 ALOGV("%s: exit: code(%d)", __func__, status);
2576 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002577}
2578
Haynes Mathew George569b7482017-05-08 14:44:27 -07002579static bool stream_get_parameter_channels(struct str_parms *query,
2580 struct str_parms *reply,
2581 audio_channel_mask_t *supported_channel_masks) {
2582 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002583 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002584 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002585 size_t i, j;
2586
2587 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2588 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002589 value[0] = '\0';
2590 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002591 while (supported_channel_masks[i] != 0) {
2592 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2593 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002594 if (!first) {
2595 strcat(value, "|");
2596 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002597 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002598 first = false;
2599 break;
2600 }
2601 }
2602 i++;
2603 }
2604 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002605 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002606 return ret >= 0;
2607}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002608
Haynes Mathew George569b7482017-05-08 14:44:27 -07002609static bool stream_get_parameter_formats(struct str_parms *query,
2610 struct str_parms *reply,
2611 audio_format_t *supported_formats) {
2612 int ret = -1;
2613 char value[256];
2614 int i;
2615
2616 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2617 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002618 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002619 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002620 case AUDIO_FORMAT_PCM_16_BIT:
2621 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2622 break;
2623 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2624 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2625 break;
2626 case AUDIO_FORMAT_PCM_32_BIT:
2627 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2628 break;
2629 default:
2630 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002631 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002632 break;
2633 }
2634 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002635 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002636 return ret >= 0;
2637}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002638
Haynes Mathew George569b7482017-05-08 14:44:27 -07002639static bool stream_get_parameter_rates(struct str_parms *query,
2640 struct str_parms *reply,
2641 uint32_t *supported_sample_rates) {
2642
2643 int i;
2644 char value[256];
2645 int ret = -1;
2646 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2647 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002648 value[0] = '\0';
2649 i=0;
2650 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002651 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002652 int avail = sizeof(value) - cursor;
2653 ret = snprintf(value + cursor, avail, "%s%d",
2654 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002655 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002656 if (ret < 0 || ret >= avail) {
2657 // if cursor is at the last element of the array
2658 // overwrite with \0 is duplicate work as
2659 // snprintf already put a \0 in place.
2660 // else
2661 // we had space to write the '|' at value[cursor]
2662 // (which will be overwritten) or no space to fill
2663 // the first element (=> cursor == 0)
2664 value[cursor] = '\0';
2665 break;
2666 }
2667 cursor += ret;
2668 ++i;
2669 }
2670 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2671 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002672 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002673 return ret >= 0;
2674}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002675
Haynes Mathew George569b7482017-05-08 14:44:27 -07002676static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2677{
2678 struct stream_out *out = (struct stream_out *)stream;
2679 struct str_parms *query = str_parms_create_str(keys);
2680 char *str;
2681 struct str_parms *reply = str_parms_create();
2682 bool replied = false;
2683 ALOGV("%s: enter: keys - %s", __func__, keys);
2684
2685 replied |= stream_get_parameter_channels(query, reply,
2686 &out->supported_channel_masks[0]);
2687 replied |= stream_get_parameter_formats(query, reply,
2688 &out->supported_formats[0]);
2689 replied |= stream_get_parameter_rates(query, reply,
2690 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002691 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002692 str = str_parms_to_str(reply);
2693 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002694 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002695 }
2696 str_parms_destroy(query);
2697 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002698 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002699 return str;
2700}
2701
2702static uint32_t out_get_latency(const struct audio_stream_out *stream)
2703{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002704 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002705 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002706 uint32_t latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002707
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002708 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2709 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002710 else if ((out->realtime) ||
2711 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002712 // since the buffer won't be filled up faster than realtime,
2713 // return a smaller number
2714 period_ms = (out->af_period_multiplier * out->config.period_size *
2715 1000) / (out->config.rate);
2716 hw_delay = platform_render_latency(out->usecase)/1000;
2717 return period_ms + hw_delay;
2718 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002719
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002720 latency = (out->config.period_count * out->config.period_size * 1000) /
2721 (out->config.rate);
2722
2723 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
2724 latency += audio_extn_a2dp_get_encoder_latency();
2725
2726 return latency;
2727}
2728
2729static int set_compr_volume(struct audio_stream_out *stream, float left,
2730 float right)
2731{
2732 struct stream_out *out = (struct stream_out *)stream;
2733 int volume[2];
2734 char mixer_ctl_name[128];
2735 struct audio_device *adev = out->dev;
2736 struct mixer_ctl *ctl;
2737 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2738 PCM_PLAYBACK);
2739
2740 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2741 "Compress Playback %d Volume", pcm_device_id);
2742 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2743 if (!ctl) {
2744 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2745 __func__, mixer_ctl_name);
2746 return -EINVAL;
2747 }
2748 ALOGV("%s: ctl for mixer cmd - %s, left %f, right %f",
2749 __func__, mixer_ctl_name, left, right);
2750 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2751 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2752 mixer_ctl_set_array(ctl, volume, sizeof(volume) / sizeof(volume[0]));
2753
2754 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002755}
2756
2757static int out_set_volume(struct audio_stream_out *stream, float left,
2758 float right)
2759{
Eric Laurenta9024de2013-04-04 09:19:12 -07002760 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002761 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002762
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002763 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002764 /* only take left channel into account: the API is for stereo anyway */
2765 out->muted = (left == 0.0f);
2766 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002767 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002768 pthread_mutex_lock(&out->compr_mute_lock);
2769 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
2770 if (!out->a2dp_compress_mute)
2771 ret = set_compr_volume(stream, left, right);
2772 out->volume_l = left;
2773 out->volume_r = right;
2774 pthread_mutex_unlock(&out->compr_mute_lock);
2775 return ret;
vivek mehtaa68fea62017-06-08 19:04:02 -07002776 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002777 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2778 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2779 if (!out->standby) {
2780 // if in standby, cached volume will be sent after stream is opened
2781 audio_extn_utils_send_app_type_gain(out->dev,
2782 out->app_type_cfg.app_type,
2783 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002784 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002785 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002786 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002787
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002788 return -ENOSYS;
2789}
2790
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002791// note: this call is safe only if the stream_cb is
2792// removed first in close_output_stream (as is done now).
2793static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2794{
2795 if (!stream || !parms)
2796 return;
2797
2798 struct stream_out *out = (struct stream_out *)stream;
2799 struct audio_device *adev = out->dev;
2800
2801 card_status_t status;
2802 int card;
2803 if (parse_snd_card_status(parms, &card, &status) < 0)
2804 return;
2805
2806 pthread_mutex_lock(&adev->lock);
2807 bool valid_cb = (card == adev->snd_card);
2808 pthread_mutex_unlock(&adev->lock);
2809
2810 if (!valid_cb)
2811 return;
2812
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002813 lock_output_stream(out);
2814 if (out->card_status != status)
2815 out->card_status = status;
2816 pthread_mutex_unlock(&out->lock);
2817
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002818 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2819 use_case_table[out->usecase],
2820 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2821
2822 if (status == CARD_STATUS_OFFLINE)
2823 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002824
2825 return;
2826}
2827
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002828#ifdef NO_AUDIO_OUT
2829static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002830 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002831{
2832 struct stream_out *out = (struct stream_out *)stream;
2833
2834 /* No Output device supported other than BT for playback.
2835 * Sleep for the amount of buffer duration
2836 */
Eric Laurenta1478072015-09-21 17:21:52 -07002837 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002838 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2839 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002840 out_get_sample_rate(&out->stream.common));
2841 pthread_mutex_unlock(&out->lock);
2842 return bytes;
2843}
2844#endif
2845
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002846static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2847 size_t bytes)
2848{
2849 struct stream_out *out = (struct stream_out *)stream;
2850 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002851 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002852 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002853
Eric Laurenta1478072015-09-21 17:21:52 -07002854 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002855 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07002856 const size_t frame_size = audio_stream_out_frame_size(stream);
2857 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002858
Eric Laurent0e46adf2016-12-16 12:49:24 -08002859 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2860 error_code = ERROR_CODE_WRITE;
2861 goto exit;
2862 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002863
2864 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2865 (audio_extn_a2dp_is_suspended())) {
2866 if (!(out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2867 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2868 ret = -EIO;
2869 goto exit;
2870 }
2871 }
2872 }
2873
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002874 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002875 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002876 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002877 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07002878
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002879 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002880 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002881 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07002882 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002883 goto exit;
2884 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002885
vivek mehta40125092017-08-21 18:48:51 -07002886 // after standby always force set last known cal step
2887 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
2888 ALOGD("%s: retry previous failed cal level set", __func__);
2889 send_gain_dep_calibration_l();
2890 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002891 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002892
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002893 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002894 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002895 if (out->send_new_metadata) {
2896 ALOGVV("send new gapless metadata");
2897 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2898 out->send_new_metadata = 0;
2899 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002900 unsigned int avail;
2901 struct timespec tstamp;
2902 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2903 /* Do not limit write size if the available frames count is unknown */
2904 if (ret != 0) {
2905 avail = bytes;
2906 }
2907 if (avail == 0) {
2908 ret = 0;
2909 } else {
2910 if (avail > bytes) {
2911 avail = bytes;
2912 }
2913 ret = compress_write(out->compr, buffer, avail);
2914 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2915 __func__, avail, ret);
2916 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002917
Eric Laurent6e895242013-09-05 16:10:57 -07002918 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002919 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2920 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002921 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002922 compress_start(out->compr);
2923 out->playback_started = 1;
2924 out->offload_state = OFFLOAD_STATE_PLAYING;
2925 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002926 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002927 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002928 } else {
2929 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002930 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002931 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002932 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002933 return ret;
2934 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002935 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002936 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07002937 size_t bytes_to_write = bytes;
2938
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002939 if (out->muted)
2940 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07002941 // FIXME: this can be removed once audio flinger mixer supports mono output
Nadav Bar3d72cfc2018-01-07 12:19:24 +02002942 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP || out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
Eric Laurentad2dde92017-09-20 18:27:31 -07002943 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
2944 int16_t *src = (int16_t *)buffer;
2945 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002946
Eric Laurentad2dde92017-09-20 18:27:31 -07002947 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
2948 out->format != AUDIO_FORMAT_PCM_16_BIT,
2949 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002950
Eric Laurentad2dde92017-09-20 18:27:31 -07002951 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
2952 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
2953 }
2954 bytes_to_write /= 2;
2955 }
2956 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes_to_write);
2957
Glenn Kasten5a59dff2018-02-22 08:05:35 -08002958 long ns = (frames * (int64_t) NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002959 request_out_focus(out, ns);
2960
2961 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2962 if (use_mmap)
Eric Laurentad2dde92017-09-20 18:27:31 -07002963 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002964 else
Eric Laurentad2dde92017-09-20 18:27:31 -07002965 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002966
Haynes Mathew George03c40102016-01-29 17:57:48 -08002967 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002968 } else {
2969 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002970 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002971 }
2972
2973exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002974 // For PCM we always consume the buffer and return #bytes regardless of ret.
2975 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07002976 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07002977 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002978 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07002979
Andy Hung7401c7c2016-09-21 12:41:21 -07002980 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07002981 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07002982 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2983 ALOGE_IF(out->pcm != NULL,
2984 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07002985 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002986 // usleep not guaranteed for values over 1 second but we don't limit here.
2987 }
2988 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002989
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002990 pthread_mutex_unlock(&out->lock);
2991
2992 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002993 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002994 if (sleeptime_us != 0)
2995 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002996 }
2997 return bytes;
2998}
2999
3000static int out_get_render_position(const struct audio_stream_out *stream,
3001 uint32_t *dsp_frames)
3002{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003003 struct stream_out *out = (struct stream_out *)stream;
3004 *dsp_frames = 0;
3005 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07003006 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003007 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003008 unsigned long frames = 0;
3009 // TODO: check return value
3010 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
3011 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003012 ALOGVV("%s rendered frames %d sample_rate %d",
3013 __func__, *dsp_frames, out->sample_rate);
3014 }
3015 pthread_mutex_unlock(&out->lock);
3016 return 0;
3017 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003018 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003019}
3020
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003021static int out_add_audio_effect(const struct audio_stream *stream __unused,
3022 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003023{
3024 return 0;
3025}
3026
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003027static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3028 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003029{
3030 return 0;
3031}
3032
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003033static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3034 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003035{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003036 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003037}
3038
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003039static int out_get_presentation_position(const struct audio_stream_out *stream,
3040 uint64_t *frames, struct timespec *timestamp)
3041{
3042 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003043 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07003044 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003045
Eric Laurenta1478072015-09-21 17:21:52 -07003046 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003047
Eric Laurent949a0892013-09-20 09:20:13 -07003048 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3049 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003050 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07003051 compress_get_tstamp(out->compr, &dsp_frames,
3052 &out->sample_rate);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003053 // Adjustment accounts for A2DP encoder latency with offload usecases
3054 // Note: Encoder latency is returned in ms.
3055 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3056 unsigned long offset =
3057 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3058 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
3059 }
Eric Laurent949a0892013-09-20 09:20:13 -07003060 ALOGVV("%s rendered frames %ld sample_rate %d",
3061 __func__, dsp_frames, out->sample_rate);
3062 *frames = dsp_frames;
3063 ret = 0;
3064 /* this is the best we can do */
3065 clock_gettime(CLOCK_MONOTONIC, timestamp);
3066 }
3067 } else {
3068 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07003069 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003070 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3071 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003072 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003073 // This adjustment accounts for buffering after app processor.
3074 // It is based on estimated DSP latency per use case, rather than exact.
3075 signed_frames -=
3076 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3077
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003078 // Adjustment accounts for A2DP encoder latency with non-offload usecases
3079 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3080 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3081 signed_frames -=
3082 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3083 }
3084
Eric Laurent949a0892013-09-20 09:20:13 -07003085 // It would be unusual for this value to be negative, but check just in case ...
3086 if (signed_frames >= 0) {
3087 *frames = signed_frames;
3088 ret = 0;
3089 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003090 }
3091 }
3092 }
3093
3094 pthread_mutex_unlock(&out->lock);
3095
3096 return ret;
3097}
3098
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003099static int out_set_callback(struct audio_stream_out *stream,
3100 stream_callback_t callback, void *cookie)
3101{
3102 struct stream_out *out = (struct stream_out *)stream;
3103
3104 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003105 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003106 out->offload_callback = callback;
3107 out->offload_cookie = cookie;
3108 pthread_mutex_unlock(&out->lock);
3109 return 0;
3110}
3111
3112static int out_pause(struct audio_stream_out* stream)
3113{
3114 struct stream_out *out = (struct stream_out *)stream;
3115 int status = -ENOSYS;
3116 ALOGV("%s", __func__);
3117 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003118 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003119 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
3120 status = compress_pause(out->compr);
3121 out->offload_state = OFFLOAD_STATE_PAUSED;
3122 }
3123 pthread_mutex_unlock(&out->lock);
3124 }
3125 return status;
3126}
3127
3128static int out_resume(struct audio_stream_out* stream)
3129{
3130 struct stream_out *out = (struct stream_out *)stream;
3131 int status = -ENOSYS;
3132 ALOGV("%s", __func__);
3133 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3134 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07003135 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003136 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
3137 status = compress_resume(out->compr);
3138 out->offload_state = OFFLOAD_STATE_PLAYING;
3139 }
3140 pthread_mutex_unlock(&out->lock);
3141 }
3142 return status;
3143}
3144
3145static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3146{
3147 struct stream_out *out = (struct stream_out *)stream;
3148 int status = -ENOSYS;
3149 ALOGV("%s", __func__);
3150 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003151 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003152 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3153 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3154 else
3155 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3156 pthread_mutex_unlock(&out->lock);
3157 }
3158 return status;
3159}
3160
3161static int out_flush(struct audio_stream_out* stream)
3162{
3163 struct stream_out *out = (struct stream_out *)stream;
3164 ALOGV("%s", __func__);
3165 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003166 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003167 stop_compressed_output_l(out);
3168 pthread_mutex_unlock(&out->lock);
3169 return 0;
3170 }
3171 return -ENOSYS;
3172}
3173
Eric Laurent0e46adf2016-12-16 12:49:24 -08003174static int out_stop(const struct audio_stream_out* stream)
3175{
3176 struct stream_out *out = (struct stream_out *)stream;
3177 struct audio_device *adev = out->dev;
3178 int ret = -ENOSYS;
3179
3180 ALOGV("%s", __func__);
3181 pthread_mutex_lock(&adev->lock);
3182 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3183 out->playback_started && out->pcm != NULL) {
3184 pcm_stop(out->pcm);
3185 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08003186 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003187 }
3188 pthread_mutex_unlock(&adev->lock);
3189 return ret;
3190}
3191
3192static int out_start(const struct audio_stream_out* stream)
3193{
3194 struct stream_out *out = (struct stream_out *)stream;
3195 struct audio_device *adev = out->dev;
3196 int ret = -ENOSYS;
3197
3198 ALOGV("%s", __func__);
3199 pthread_mutex_lock(&adev->lock);
3200 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3201 !out->playback_started && out->pcm != NULL) {
3202 ret = start_output_stream(out);
3203 if (ret == 0) {
3204 out->playback_started = true;
3205 }
3206 }
3207 pthread_mutex_unlock(&adev->lock);
3208 return ret;
3209}
3210
Phil Burkbc991042017-02-24 08:06:44 -08003211/*
3212 * Modify config->period_count based on min_size_frames
3213 */
3214static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
3215{
3216 int periodCountRequested = (min_size_frames + config->period_size - 1)
3217 / config->period_size;
3218 int periodCount = MMAP_PERIOD_COUNT_MIN;
3219
3220 ALOGV("%s original config.period_size = %d config.period_count = %d",
3221 __func__, config->period_size, config->period_count);
3222
3223 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
3224 periodCount *= 2;
3225 }
3226 config->period_count = periodCount;
3227
3228 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
3229}
3230
Eric Laurent0e46adf2016-12-16 12:49:24 -08003231static int out_create_mmap_buffer(const struct audio_stream_out *stream,
3232 int32_t min_size_frames,
3233 struct audio_mmap_buffer_info *info)
3234{
3235 struct stream_out *out = (struct stream_out *)stream;
3236 struct audio_device *adev = out->dev;
3237 int ret = 0;
3238 unsigned int offset1;
3239 unsigned int frames1;
3240 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003241 uint32_t mmap_size;
3242 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003243
3244 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003245 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003246 pthread_mutex_lock(&adev->lock);
3247
3248 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003249 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003250 ret = -EINVAL;
3251 goto exit;
3252 }
3253 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003254 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003255 ret = -ENOSYS;
3256 goto exit;
3257 }
3258 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3259 if (out->pcm_device_id < 0) {
3260 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3261 __func__, out->pcm_device_id, out->usecase);
3262 ret = -EINVAL;
3263 goto exit;
3264 }
Phil Burkbc991042017-02-24 08:06:44 -08003265
3266 adjust_mmap_period_count(&out->config, min_size_frames);
3267
Eric Laurent0e46adf2016-12-16 12:49:24 -08003268 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3269 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3270 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3271 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3272 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3273 step = "open";
3274 ret = -ENODEV;
3275 goto exit;
3276 }
3277 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3278 if (ret < 0) {
3279 step = "begin";
3280 goto exit;
3281 }
3282 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003283 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003284 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003285 ret = platform_get_mmap_data_fd(adev->platform,
3286 out->pcm_device_id, 0 /*playback*/,
3287 &info->shared_memory_fd,
3288 &mmap_size);
3289 if (ret < 0) {
3290 // Fall back to non exclusive mode
3291 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3292 } else {
3293 if (mmap_size < buffer_size) {
3294 step = "mmap";
3295 goto exit;
3296 }
3297 // FIXME: indicate exclusive mode support by returning a negative buffer size
3298 info->buffer_size_frames *= -1;
3299 }
3300 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003301
3302 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3303 if (ret < 0) {
3304 step = "commit";
3305 goto exit;
3306 }
Phil Burkbc991042017-02-24 08:06:44 -08003307
3308 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003309 ret = 0;
3310
3311 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3312 __func__, info->shared_memory_address, info->buffer_size_frames);
3313
3314exit:
3315 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003316 if (out->pcm == NULL) {
3317 ALOGE("%s: %s - %d", __func__, step, ret);
3318 } else {
3319 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003320 pcm_close(out->pcm);
3321 out->pcm = NULL;
3322 }
3323 }
3324 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003325 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003326 return ret;
3327}
3328
3329static int out_get_mmap_position(const struct audio_stream_out *stream,
3330 struct audio_mmap_position *position)
3331{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003332 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003333 struct stream_out *out = (struct stream_out *)stream;
3334 ALOGVV("%s", __func__);
3335 if (position == NULL) {
3336 return -EINVAL;
3337 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003338 lock_output_stream(out);
3339 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3340 out->pcm == NULL) {
3341 ret = -ENOSYS;
3342 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003343 }
3344
3345 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003346 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003347 if (ret < 0) {
3348 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003349 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003350 }
Andy Hungfc044e12017-03-20 09:24:22 -07003351 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003352exit:
3353 pthread_mutex_unlock(&out->lock);
3354 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003355}
3356
3357
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003358/** audio_stream_in implementation **/
3359static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3360{
3361 struct stream_in *in = (struct stream_in *)stream;
3362
3363 return in->config.rate;
3364}
3365
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003366static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003367{
3368 return -ENOSYS;
3369}
3370
3371static size_t in_get_buffer_size(const struct audio_stream *stream)
3372{
3373 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003374 return in->config.period_size * in->af_period_multiplier *
3375 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003376}
3377
3378static uint32_t in_get_channels(const struct audio_stream *stream)
3379{
3380 struct stream_in *in = (struct stream_in *)stream;
3381
3382 return in->channel_mask;
3383}
3384
vivek mehta4ed66e62016-04-15 23:33:34 -07003385static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003386{
vivek mehta4ed66e62016-04-15 23:33:34 -07003387 struct stream_in *in = (struct stream_in *)stream;
3388 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003389}
3390
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003391static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003392{
3393 return -ENOSYS;
3394}
3395
3396static int in_standby(struct audio_stream *stream)
3397{
3398 struct stream_in *in = (struct stream_in *)stream;
3399 struct audio_device *adev = in->dev;
3400 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003401 bool do_stop = true;
3402
Eric Laurent994a6932013-07-17 11:51:42 -07003403 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003404
3405 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003406
3407 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003408 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003409 audio_extn_sound_trigger_stop_lab(in);
3410 in->standby = true;
3411 }
3412
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003413 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003414 if (adev->adm_deregister_stream)
3415 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3416
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003417 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003418 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003419 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003420 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003421 in->capture_started = false;
3422 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003423 if (in->pcm) {
3424 pcm_close(in->pcm);
3425 in->pcm = NULL;
3426 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003427 adev->enable_voicerx = false;
3428 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003429 if (do_stop) {
3430 status = stop_input_stream(in);
3431 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003432 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003433 }
3434 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003435 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003436 return status;
3437}
3438
Andy Hungd13f0d32017-06-12 13:58:37 -07003439static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003440{
Andy Hungd13f0d32017-06-12 13:58:37 -07003441 struct stream_in *in = (struct stream_in *)stream;
3442
3443 // We try to get the lock for consistency,
3444 // but it isn't necessary for these variables.
3445 // If we're not in standby, we may be blocked on a read.
3446 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3447 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3448 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3449 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3450
3451 if (locked) {
3452 pthread_mutex_unlock(&in->lock);
3453 }
3454
3455 // dump error info
3456 (void)error_log_dump(
3457 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003458 return 0;
3459}
3460
3461static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3462{
3463 struct stream_in *in = (struct stream_in *)stream;
3464 struct audio_device *adev = in->dev;
3465 struct str_parms *parms;
3466 char *str;
3467 char value[32];
3468 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003469 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003470
Eric Laurent994a6932013-07-17 11:51:42 -07003471 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003472 parms = str_parms_create_str(kvpairs);
3473
3474 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3475
Eric Laurenta1478072015-09-21 17:21:52 -07003476 lock_input_stream(in);
3477
Eric Laurent150dbfe2013-02-27 14:31:02 -08003478 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003479 if (ret >= 0) {
3480 val = atoi(value);
3481 /* no audio source uses val == 0 */
3482 if ((in->source != val) && (val != 0)) {
3483 in->source = val;
3484 }
3485 }
3486
3487 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003488
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003489 if (ret >= 0) {
3490 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003491 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003492
3493 // Workaround: If routing to an non existing usb device, fail gracefully
3494 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003495 int card;
3496 if (audio_is_usb_in_device(val) &&
3497 (card = get_alive_usb_card(parms)) >= 0) {
3498
3499 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003500 status = -ENOSYS;
3501 } else {
3502
3503 in->device = val;
3504 /* If recording is in progress, change the tx device to new device */
3505 if (!in->standby) {
3506 ALOGV("update input routing change");
3507 // inform adm before actual routing to prevent glitches.
3508 if (adev->adm_on_routing_change) {
3509 adev->adm_on_routing_change(adev->adm_data,
3510 in->capture_handle);
3511 }
3512 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003513 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003514 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003515 }
3516 }
3517
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003518 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003519 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003520
3521 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003522 ALOGV("%s: exit: status(%d)", __func__, status);
3523 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003524}
3525
Haynes Mathew George569b7482017-05-08 14:44:27 -07003526static char* in_get_parameters(const struct audio_stream *stream,
3527 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003528{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003529 struct stream_in *in = (struct stream_in *)stream;
3530 struct str_parms *query = str_parms_create_str(keys);
3531 char *str;
3532 struct str_parms *reply = str_parms_create();
3533 bool replied = false;
3534
3535 ALOGV("%s: enter: keys - %s", __func__, keys);
3536 replied |= stream_get_parameter_channels(query, reply,
3537 &in->supported_channel_masks[0]);
3538 replied |= stream_get_parameter_formats(query, reply,
3539 &in->supported_formats[0]);
3540 replied |= stream_get_parameter_rates(query, reply,
3541 &in->supported_sample_rates[0]);
3542 if (replied) {
3543 str = str_parms_to_str(reply);
3544 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003545 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003546 }
3547 str_parms_destroy(query);
3548 str_parms_destroy(reply);
3549 ALOGV("%s: exit: returns - %s", __func__, str);
3550 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003551}
3552
Eric Laurent51f3c662018-04-10 18:21:34 -07003553static int in_set_gain(struct audio_stream_in *stream, float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003554{
Eric Laurent51f3c662018-04-10 18:21:34 -07003555 struct stream_in *in = (struct stream_in *)stream;
3556 char mixer_ctl_name[128];
3557 struct mixer_ctl *ctl;
3558 int ctl_value;
3559
3560 ALOGV("%s: gain %f", __func__, gain);
3561
3562 if (stream == NULL)
3563 return -EINVAL;
3564
3565 /* in_set_gain() only used to silence MMAP capture for now */
3566 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
3567 return -ENOSYS;
3568
3569 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
3570
3571 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
3572 if (!ctl) {
3573 ALOGW("%s: Could not get ctl for mixer cmd - %s",
3574 __func__, mixer_ctl_name);
3575 return -ENOSYS;
3576 }
3577
3578 if (gain < RECORD_GAIN_MIN)
3579 gain = RECORD_GAIN_MIN;
3580 else if (gain > RECORD_GAIN_MAX)
3581 gain = RECORD_GAIN_MAX;
3582 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
3583
3584 mixer_ctl_set_value(ctl, 0, ctl_value);
3585 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003586}
3587
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003588static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3589{
3590 if (!stream || !parms)
3591 return;
3592
3593 struct stream_in *in = (struct stream_in *)stream;
3594 struct audio_device *adev = in->dev;
3595
3596 card_status_t status;
3597 int card;
3598 if (parse_snd_card_status(parms, &card, &status) < 0)
3599 return;
3600
3601 pthread_mutex_lock(&adev->lock);
3602 bool valid_cb = (card == adev->snd_card);
3603 pthread_mutex_unlock(&adev->lock);
3604
3605 if (!valid_cb)
3606 return;
3607
3608 lock_input_stream(in);
3609 if (in->card_status != status)
3610 in->card_status = status;
3611 pthread_mutex_unlock(&in->lock);
3612
3613 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3614 use_case_table[in->usecase],
3615 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3616
3617 // a better solution would be to report error back to AF and let
3618 // it put the stream to standby
3619 if (status == CARD_STATUS_OFFLINE)
3620 in_standby(&in->stream.common);
3621
3622 return;
3623}
3624
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003625static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3626 size_t bytes)
3627{
3628 struct stream_in *in = (struct stream_in *)stream;
3629 struct audio_device *adev = in->dev;
3630 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003631 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003632 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003633
Eric Laurenta1478072015-09-21 17:21:52 -07003634 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003635 const size_t frame_size = audio_stream_in_frame_size(stream);
3636 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003637
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003638 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003639 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003640 /* Read from sound trigger HAL */
3641 audio_extn_sound_trigger_read(in, buffer, bytes);
3642 pthread_mutex_unlock(&in->lock);
3643 return bytes;
3644 }
3645
Eric Laurent0e46adf2016-12-16 12:49:24 -08003646 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3647 ret = -ENOSYS;
3648 goto exit;
3649 }
3650
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003651 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003652 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003653 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003654 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003655 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003656 goto exit;
3657 }
3658 in->standby = 0;
3659 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003660
Andy Hungd13f0d32017-06-12 13:58:37 -07003661 // errors that occur here are read errors.
3662 error_code = ERROR_CODE_READ;
3663
Haynes Mathew George03c40102016-01-29 17:57:48 -08003664 //what's the duration requested by the client?
3665 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3666 in->config.rate;
3667 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003668
Haynes Mathew George03c40102016-01-29 17:57:48 -08003669 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003670 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003671 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003672 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003673 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003674 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003675 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003676 if (ret < 0) {
3677 ALOGE("Failed to read w/err %s", strerror(errno));
3678 ret = -errno;
3679 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003680 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3681 if (bytes % 4 == 0) {
3682 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3683 int_buf_stream = buffer;
3684 for (size_t itt=0; itt < bytes/4 ; itt++) {
3685 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003686 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003687 } else {
3688 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3689 ret = -EINVAL;
3690 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003691 }
3692 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003693 }
3694
Haynes Mathew George03c40102016-01-29 17:57:48 -08003695 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003696
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003697 /*
3698 * Instead of writing zeroes here, we could trust the hardware
3699 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003700 * 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 -08003701 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08003702 if (ret == 0 && adev->mic_muted &&
3703 !voice_is_in_call_rec_stream(in) &&
3704 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003705 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07003706 in->frames_muted += frames;
3707 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003708
3709exit:
3710 pthread_mutex_unlock(&in->lock);
3711
3712 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07003713 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003714 in_standby(&in->stream.common);
3715 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003716 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003717 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07003718 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08003719 }
3720 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003721 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003722 }
3723 return bytes;
3724}
3725
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003726static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003727{
3728 return 0;
3729}
3730
Andy Hung6ebe5962016-01-15 17:46:57 -08003731static int in_get_capture_position(const struct audio_stream_in *stream,
3732 int64_t *frames, int64_t *time)
3733{
3734 if (stream == NULL || frames == NULL || time == NULL) {
3735 return -EINVAL;
3736 }
3737 struct stream_in *in = (struct stream_in *)stream;
3738 int ret = -ENOSYS;
3739
3740 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003741 // note: ST sessions do not close the alsa pcm driver synchronously
3742 // on standby. Therefore, we may return an error even though the
3743 // pcm stream is still opened.
3744 if (in->standby) {
3745 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
3746 "%s stream in standby but pcm not NULL for non ST session", __func__);
3747 goto exit;
3748 }
Andy Hung6ebe5962016-01-15 17:46:57 -08003749 if (in->pcm) {
3750 struct timespec timestamp;
3751 unsigned int avail;
3752 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3753 *frames = in->frames_read + avail;
3754 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3755 ret = 0;
3756 }
3757 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003758exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08003759 pthread_mutex_unlock(&in->lock);
3760 return ret;
3761}
3762
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003763static int add_remove_audio_effect(const struct audio_stream *stream,
3764 effect_handle_t effect,
3765 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003766{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003767 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003768 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003769 int status = 0;
3770 effect_descriptor_t desc;
3771
3772 status = (*effect)->get_descriptor(effect, &desc);
3773 if (status != 0)
3774 return status;
3775
Eric Laurenta1478072015-09-21 17:21:52 -07003776 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003777 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003778 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003779 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003780 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003781 in->enable_aec != enable &&
3782 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3783 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003784 if (!enable)
3785 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003786 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3787 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3788 adev->enable_voicerx = enable;
3789 struct audio_usecase *usecase;
3790 struct listnode *node;
3791 list_for_each(node, &adev->usecase_list) {
3792 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07003793 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07003794 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05003795 }
3796 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003797 if (!in->standby)
3798 select_devices(in->dev, in->usecase);
3799 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003800 if (in->enable_ns != enable &&
3801 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3802 in->enable_ns = enable;
3803 if (!in->standby)
3804 select_devices(in->dev, in->usecase);
3805 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003806 pthread_mutex_unlock(&in->dev->lock);
3807 pthread_mutex_unlock(&in->lock);
3808
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003809 return 0;
3810}
3811
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003812static int in_add_audio_effect(const struct audio_stream *stream,
3813 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003814{
Eric Laurent994a6932013-07-17 11:51:42 -07003815 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003816 return add_remove_audio_effect(stream, effect, true);
3817}
3818
3819static int in_remove_audio_effect(const struct audio_stream *stream,
3820 effect_handle_t effect)
3821{
Eric Laurent994a6932013-07-17 11:51:42 -07003822 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003823 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003824}
3825
Eric Laurent0e46adf2016-12-16 12:49:24 -08003826static int in_stop(const struct audio_stream_in* stream)
3827{
3828 struct stream_in *in = (struct stream_in *)stream;
3829 struct audio_device *adev = in->dev;
3830
3831 int ret = -ENOSYS;
3832 ALOGV("%s", __func__);
3833 pthread_mutex_lock(&adev->lock);
3834 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3835 in->capture_started && in->pcm != NULL) {
3836 pcm_stop(in->pcm);
3837 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003838 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003839 }
3840 pthread_mutex_unlock(&adev->lock);
3841 return ret;
3842}
3843
3844static int in_start(const struct audio_stream_in* stream)
3845{
3846 struct stream_in *in = (struct stream_in *)stream;
3847 struct audio_device *adev = in->dev;
3848 int ret = -ENOSYS;
3849
3850 ALOGV("%s in %p", __func__, in);
3851 pthread_mutex_lock(&adev->lock);
3852 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3853 !in->capture_started && in->pcm != NULL) {
3854 if (!in->capture_started) {
3855 ret = start_input_stream(in);
3856 if (ret == 0) {
3857 in->capture_started = true;
3858 }
3859 }
3860 }
3861 pthread_mutex_unlock(&adev->lock);
3862 return ret;
3863}
3864
3865static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3866 int32_t min_size_frames,
3867 struct audio_mmap_buffer_info *info)
3868{
3869 struct stream_in *in = (struct stream_in *)stream;
3870 struct audio_device *adev = in->dev;
3871 int ret = 0;
3872 unsigned int offset1;
3873 unsigned int frames1;
3874 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003875 uint32_t mmap_size;
3876 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003877
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003878 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003879 pthread_mutex_lock(&adev->lock);
3880 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003881
Eric Laurent0e46adf2016-12-16 12:49:24 -08003882 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003883 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003884 ret = -EINVAL;
3885 goto exit;
3886 }
3887 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003888 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003889 ALOGV("%s in %p", __func__, in);
3890 ret = -ENOSYS;
3891 goto exit;
3892 }
3893 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3894 if (in->pcm_device_id < 0) {
3895 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3896 __func__, in->pcm_device_id, in->usecase);
3897 ret = -EINVAL;
3898 goto exit;
3899 }
Phil Burkbc991042017-02-24 08:06:44 -08003900
3901 adjust_mmap_period_count(&in->config, min_size_frames);
3902
Eric Laurent0e46adf2016-12-16 12:49:24 -08003903 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3904 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3905 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3906 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3907 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3908 step = "open";
3909 ret = -ENODEV;
3910 goto exit;
3911 }
3912
3913 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3914 if (ret < 0) {
3915 step = "begin";
3916 goto exit;
3917 }
3918 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003919 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003920 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003921 ret = platform_get_mmap_data_fd(adev->platform,
3922 in->pcm_device_id, 1 /*capture*/,
3923 &info->shared_memory_fd,
3924 &mmap_size);
3925 if (ret < 0) {
3926 // Fall back to non exclusive mode
3927 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3928 } else {
3929 if (mmap_size < buffer_size) {
3930 step = "mmap";
3931 goto exit;
3932 }
3933 // FIXME: indicate exclusive mode support by returning a negative buffer size
3934 info->buffer_size_frames *= -1;
3935 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08003936
Haynes Mathew George96483a22017-03-28 14:52:47 -07003937 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003938
3939 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3940 if (ret < 0) {
3941 step = "commit";
3942 goto exit;
3943 }
3944
Phil Burkbc991042017-02-24 08:06:44 -08003945 in->standby = false;
3946 ret = 0;
3947
Eric Laurent0e46adf2016-12-16 12:49:24 -08003948 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3949 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003950
3951exit:
3952 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003953 if (in->pcm == NULL) {
3954 ALOGE("%s: %s - %d", __func__, step, ret);
3955 } else {
3956 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003957 pcm_close(in->pcm);
3958 in->pcm = NULL;
3959 }
3960 }
3961 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003962 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003963 return ret;
3964}
3965
3966static int in_get_mmap_position(const struct audio_stream_in *stream,
3967 struct audio_mmap_position *position)
3968{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003969 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003970 struct stream_in *in = (struct stream_in *)stream;
3971 ALOGVV("%s", __func__);
3972 if (position == NULL) {
3973 return -EINVAL;
3974 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003975 lock_input_stream(in);
3976 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
3977 in->pcm == NULL) {
3978 ret = -ENOSYS;
3979 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003980 }
3981 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003982 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003983 if (ret < 0) {
3984 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003985 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003986 }
Andy Hungfc044e12017-03-20 09:24:22 -07003987 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003988exit:
3989 pthread_mutex_unlock(&in->lock);
3990 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003991}
3992
jiabin8962a4d2018-03-19 18:21:24 -07003993static int in_get_active_microphones(const struct audio_stream_in *stream,
3994 struct audio_microphone_characteristic_t *mic_array,
3995 size_t *mic_count) {
3996 struct stream_in *in = (struct stream_in *)stream;
3997 struct audio_device *adev = in->dev;
3998 ALOGVV("%s", __func__);
3999
4000 lock_input_stream(in);
4001 pthread_mutex_lock(&adev->lock);
4002 int ret = platform_get_active_microphones(adev->platform, in->device,
4003 audio_channel_count_from_in_mask(in->channel_mask),
4004 in->source, in->usecase, mic_array, mic_count);
4005 pthread_mutex_unlock(&adev->lock);
4006 pthread_mutex_unlock(&in->lock);
4007
4008 return ret;
4009}
4010
4011static int adev_get_microphones(const struct audio_hw_device *dev,
4012 struct audio_microphone_characteristic_t *mic_array,
4013 size_t *mic_count) {
4014 struct audio_device *adev = (struct audio_device *)dev;
4015 ALOGVV("%s", __func__);
4016
4017 pthread_mutex_lock(&adev->lock);
4018 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
4019 pthread_mutex_unlock(&adev->lock);
4020
4021 return ret;
4022}
Eric Laurent0e46adf2016-12-16 12:49:24 -08004023
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004024static int adev_open_output_stream(struct audio_hw_device *dev,
4025 audio_io_handle_t handle,
4026 audio_devices_t devices,
4027 audio_output_flags_t flags,
4028 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07004029 struct audio_stream_out **stream_out,
4030 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004031{
4032 struct audio_device *adev = (struct audio_device *)dev;
4033 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004034 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004035 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
4036 bool is_usb_dev = audio_is_usb_out_device(devices) &&
4037 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004038
Andy Hungd9653bd2017-08-01 19:31:39 -07004039 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
4040 return -ENOSYS;
4041 }
4042
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004043 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
4044 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004045 *stream_out = NULL;
4046 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4047
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004048 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
4049
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004050 if (devices == AUDIO_DEVICE_NONE)
4051 devices = AUDIO_DEVICE_OUT_SPEAKER;
4052
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004053 out->flags = flags;
4054 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004055 out->dev = adev;
Eric Laurentc4aef752013-09-12 17:45:53 -07004056 out->handle = handle;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004057 out->a2dp_compress_mute = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004058
4059 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004060 if ((is_hdmi || is_usb_dev) &&
4061 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
4062 (flags == AUDIO_OUTPUT_FLAG_NONE ||
4063 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Eric Laurentab805ee2018-03-30 12:20:38 -07004064 audio_format_t req_format = config->format;
4065 audio_channel_mask_t req_channel_mask = config->channel_mask;
4066 uint32_t req_sample_rate = config->sample_rate;
4067
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004068 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004069 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004070 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004071 if (config->sample_rate == 0)
4072 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Eric Laurentab805ee2018-03-30 12:20:38 -07004073 if (config->channel_mask == AUDIO_CHANNEL_NONE)
Haynes Mathew George569b7482017-05-08 14:44:27 -07004074 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
4075 if (config->format == AUDIO_FORMAT_DEFAULT)
4076 config->format = AUDIO_FORMAT_PCM_16_BIT;
4077 } else if (is_usb_dev) {
4078 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
4079 &config->format,
4080 &out->supported_formats[0],
4081 MAX_SUPPORTED_FORMATS,
4082 &config->channel_mask,
4083 &out->supported_channel_masks[0],
4084 MAX_SUPPORTED_CHANNEL_MASKS,
4085 &config->sample_rate,
4086 &out->supported_sample_rates[0],
4087 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004088 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004089 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004090 pthread_mutex_unlock(&adev->lock);
Eric Laurentab805ee2018-03-30 12:20:38 -07004091 if (ret != 0) {
4092 // For MMAP NO IRQ, allow conversions in ADSP
4093 if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
4094 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004095
Eric Laurentab805ee2018-03-30 12:20:38 -07004096 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
4097 config->sample_rate = req_sample_rate;
4098 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
4099 config->channel_mask = req_channel_mask;
4100 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
4101 config->format = req_format;
4102 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004103
Haynes Mathew George569b7482017-05-08 14:44:27 -07004104 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004105 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004106 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004107 if (is_hdmi) {
4108 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4109 out->config = pcm_config_hdmi_multi;
4110 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
4111 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4112 out->config = pcm_config_mmap_playback;
4113 out->stream.start = out_start;
4114 out->stream.stop = out_stop;
4115 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4116 out->stream.get_mmap_position = out_get_mmap_position;
4117 } else {
4118 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4119 out->config = pcm_config_hifi;
4120 }
4121
4122 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004123 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004124 if (is_hdmi) {
4125 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
4126 audio_bytes_per_sample(out->format));
4127 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004128 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004129 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07004130 pthread_mutex_lock(&adev->lock);
4131 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4132 pthread_mutex_unlock(&adev->lock);
4133
4134 // reject offload during card offline to allow
4135 // fallback to s/w paths
4136 if (offline) {
4137 ret = -ENODEV;
4138 goto error_open;
4139 }
4140
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004141 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4142 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4143 ALOGE("%s: Unsupported Offload information", __func__);
4144 ret = -EINVAL;
4145 goto error_open;
4146 }
4147 if (!is_supported_format(config->offload_info.format)) {
4148 ALOGE("%s: Unsupported audio format", __func__);
4149 ret = -EINVAL;
4150 goto error_open;
4151 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004152 out->sample_rate = config->offload_info.sample_rate;
4153 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
4154 out->channel_mask = config->offload_info.channel_mask;
4155 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
4156 out->channel_mask = config->channel_mask;
4157 else
4158 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4159
4160 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004161
4162 out->compr_config.codec = (struct snd_codec *)
4163 calloc(1, sizeof(struct snd_codec));
4164
4165 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004166
4167 out->stream.set_callback = out_set_callback;
4168 out->stream.pause = out_pause;
4169 out->stream.resume = out_resume;
4170 out->stream.drain = out_drain;
4171 out->stream.flush = out_flush;
4172
4173 out->compr_config.codec->id =
4174 get_snd_codec_id(config->offload_info.format);
4175 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
4176 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004177 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004178 out->compr_config.codec->bit_rate =
4179 config->offload_info.bit_rate;
4180 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004181 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004182 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
4183
4184 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4185 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004186
4187 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004188 create_offload_callback_thread(out);
4189 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4190 __func__, config->offload_info.version,
4191 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02004192 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4193 switch (config->sample_rate) {
4194 case 0:
4195 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4196 break;
4197 case 8000:
4198 case 16000:
4199 case 48000:
4200 out->sample_rate = config->sample_rate;
4201 break;
4202 default:
4203 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
4204 config->sample_rate);
4205 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4206 ret = -EINVAL;
4207 goto error_open;
4208 }
4209 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4210 switch (config->channel_mask) {
4211 case AUDIO_CHANNEL_NONE:
4212 case AUDIO_CHANNEL_OUT_STEREO:
4213 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4214 break;
4215 default:
4216 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
4217 config->channel_mask);
4218 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4219 ret = -EINVAL;
4220 goto error_open;
4221 }
4222 switch (config->format) {
4223 case AUDIO_FORMAT_DEFAULT:
4224 case AUDIO_FORMAT_PCM_16_BIT:
4225 out->format = AUDIO_FORMAT_PCM_16_BIT;
4226 break;
4227 default:
4228 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
4229 config->format);
4230 config->format = AUDIO_FORMAT_PCM_16_BIT;
4231 ret = -EINVAL;
4232 goto error_open;
4233 }
4234
4235 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004236 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004237 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004238 case 0:
4239 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
4240 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07004241 case 8000:
4242 case 16000:
4243 case 48000:
4244 out->sample_rate = config->sample_rate;
4245 break;
4246 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004247 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
4248 config->sample_rate);
4249 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4250 ret = -EINVAL;
4251 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004252 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004253 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4254 switch (config->channel_mask) {
4255 case AUDIO_CHANNEL_NONE:
4256 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4257 break;
4258 case AUDIO_CHANNEL_OUT_STEREO:
4259 out->channel_mask = config->channel_mask;
4260 break;
4261 default:
4262 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
4263 config->channel_mask);
4264 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4265 ret = -EINVAL;
4266 break;
4267 }
4268 switch (config->format) {
4269 case AUDIO_FORMAT_DEFAULT:
4270 out->format = AUDIO_FORMAT_PCM_16_BIT;
4271 break;
4272 case AUDIO_FORMAT_PCM_16_BIT:
4273 out->format = config->format;
4274 break;
4275 default:
4276 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
4277 config->format);
4278 config->format = AUDIO_FORMAT_PCM_16_BIT;
4279 ret = -EINVAL;
4280 break;
4281 }
4282 if (ret != 0)
4283 goto error_open;
4284
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004285 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4286 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004287 out->config.rate = out->sample_rate;
4288 out->config.channels =
4289 audio_channel_count_from_out_mask(out->channel_mask);
4290 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004291 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004292 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
4293 switch (config->sample_rate) {
4294 case 0:
4295 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4296 break;
4297 case 8000:
4298 case 16000:
4299 case 32000:
4300 case 48000:
4301 out->sample_rate = config->sample_rate;
4302 break;
4303 default:
4304 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
4305 config->sample_rate);
4306 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4307 ret = -EINVAL;
4308 break;
4309 }
Eric Laurentad2dde92017-09-20 18:27:31 -07004310 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004311 switch (config->channel_mask) {
4312 case AUDIO_CHANNEL_NONE:
4313 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4314 break;
4315 case AUDIO_CHANNEL_OUT_STEREO:
4316 out->channel_mask = config->channel_mask;
4317 break;
4318 default:
4319 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
4320 config->channel_mask);
4321 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4322 ret = -EINVAL;
4323 break;
4324 }
4325 switch (config->format) {
4326 case AUDIO_FORMAT_DEFAULT:
4327 out->format = AUDIO_FORMAT_PCM_16_BIT;
4328 break;
4329 case AUDIO_FORMAT_PCM_16_BIT:
4330 out->format = config->format;
4331 break;
4332 default:
4333 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
4334 config->format);
4335 config->format = AUDIO_FORMAT_PCM_16_BIT;
4336 ret = -EINVAL;
4337 break;
4338 }
4339 if (ret != 0)
4340 goto error_open;
4341
vivek mehtaa68fea62017-06-08 19:04:02 -07004342 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07004343 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4344 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004345 out->config.rate = out->sample_rate;
4346 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07004347 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004348 out->sample_rate,
4349 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07004350 out->config.channels,
4351 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004352 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07004353 out->config.period_size = buffer_size / frame_size;
4354 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
4355 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004356 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004357 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07004358 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4359 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004360 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07004361 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
4362 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004363 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07004364 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004365 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004366 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004367 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004368 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4369 out->config = pcm_config_mmap_playback;
4370 out->stream.start = out_start;
4371 out->stream.stop = out_stop;
4372 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4373 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004374 } else {
4375 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4376 out->config = pcm_config_low_latency;
4377 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004378
4379 if (config->sample_rate == 0) {
4380 out->sample_rate = out->config.rate;
4381 } else {
4382 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004383 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004384 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
4385 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
4386 } else {
4387 out->channel_mask = config->channel_mask;
4388 }
4389 if (config->format == AUDIO_FORMAT_DEFAULT)
4390 out->format = audio_format_from_pcm_format(out->config.format);
4391 else if (!audio_is_linear_pcm(config->format)) {
4392 config->format = AUDIO_FORMAT_PCM_16_BIT;
4393 ret = -EINVAL;
4394 goto error_open;
4395 } else {
4396 out->format = config->format;
4397 }
4398
4399 out->config.rate = out->sample_rate;
4400 out->config.channels =
4401 audio_channel_count_from_out_mask(out->channel_mask);
4402 if (out->format != audio_format_from_pcm_format(out->config.format)) {
4403 out->config.format = pcm_format_from_audio_format(out->format);
4404 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004405 }
Kevin Rocard50eff892017-05-02 16:52:05 -07004406
4407 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
4408 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004409 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004410 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
4411 __func__, config->sample_rate, config->format, config->channel_mask);
4412 config->sample_rate = out->sample_rate;
4413 config->format = out->format;
4414 config->channel_mask = out->channel_mask;
4415 ret = -EINVAL;
4416 goto error_open;
4417 }
4418
Andy Hung6fcba9c2014-03-18 11:53:32 -07004419 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
4420 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004421
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004422 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004423 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004424 adev->primary_output = out;
4425 else {
4426 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004427 ret = -EEXIST;
4428 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004429 }
4430 }
4431
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004432 /* Check if this usecase is already existing */
4433 pthread_mutex_lock(&adev->lock);
4434 if (get_usecase_from_list(adev, out->usecase) != NULL) {
4435 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004436 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004437 ret = -EEXIST;
4438 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004439 }
4440 pthread_mutex_unlock(&adev->lock);
4441
4442 out->stream.common.get_sample_rate = out_get_sample_rate;
4443 out->stream.common.set_sample_rate = out_set_sample_rate;
4444 out->stream.common.get_buffer_size = out_get_buffer_size;
4445 out->stream.common.get_channels = out_get_channels;
4446 out->stream.common.get_format = out_get_format;
4447 out->stream.common.set_format = out_set_format;
4448 out->stream.common.standby = out_standby;
4449 out->stream.common.dump = out_dump;
4450 out->stream.common.set_parameters = out_set_parameters;
4451 out->stream.common.get_parameters = out_get_parameters;
4452 out->stream.common.add_audio_effect = out_add_audio_effect;
4453 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4454 out->stream.get_latency = out_get_latency;
4455 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004456#ifdef NO_AUDIO_OUT
4457 out->stream.write = out_write_for_no_output;
4458#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004459 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004460#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004461 out->stream.get_render_position = out_get_render_position;
4462 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004463 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004464
Eric Laurent0e46adf2016-12-16 12:49:24 -08004465 if (out->realtime)
4466 out->af_period_multiplier = af_period_multiplier;
4467 else
4468 out->af_period_multiplier = 1;
4469
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004470 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004471 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004472 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004473
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004474 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004475 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004476 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4477
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004478 config->format = out->stream.common.get_format(&out->stream.common);
4479 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4480 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4481
Kevin Rocarda325aa22018-04-03 09:15:52 -07004482 register_format(out->format, out->supported_formats);
4483 register_channel_mask(out->channel_mask, out->supported_channel_masks);
4484 register_sample_rate(out->sample_rate, out->supported_sample_rates);
4485
Andy Hunga452b0a2017-03-15 14:51:15 -07004486 out->error_log = error_log_create(
4487 ERROR_LOG_ENTRIES,
4488 1000000000 /* aggregate consecutive identical errors within one second in ns */);
4489
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004490 /*
4491 By locking output stream before registering, we allow the callback
4492 to update stream's state only after stream's initial state is set to
4493 adev state.
4494 */
4495 lock_output_stream(out);
4496 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4497 pthread_mutex_lock(&adev->lock);
4498 out->card_status = adev->card_status;
4499 pthread_mutex_unlock(&adev->lock);
4500 pthread_mutex_unlock(&out->lock);
4501
vivek mehta4a824772017-06-08 19:05:49 -07004502 stream_app_type_cfg_init(&out->app_type_cfg);
4503
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004504 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004505
Eric Laurent994a6932013-07-17 11:51:42 -07004506 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004507 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004508
4509error_open:
4510 free(out);
4511 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07004512 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004513 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004514}
4515
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004516static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004517 struct audio_stream_out *stream)
4518{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004519 struct stream_out *out = (struct stream_out *)stream;
4520 struct audio_device *adev = out->dev;
4521
Eric Laurent994a6932013-07-17 11:51:42 -07004522 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004523
4524 // must deregister from sndmonitor first to prevent races
4525 // between the callback and close_stream
4526 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004527 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004528 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
4529 destroy_offload_callback_thread(out);
4530
4531 if (out->compr_config.codec != NULL)
4532 free(out->compr_config.codec);
4533 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004534
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004535 out->a2dp_compress_mute = false;
4536
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004537 if (adev->voice_tx_output == out)
4538 adev->voice_tx_output = NULL;
4539
Andy Hunga452b0a2017-03-15 14:51:15 -07004540 error_log_destroy(out->error_log);
4541 out->error_log = NULL;
4542
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004543 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004544 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004545 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004546 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004547 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004548}
4549
4550static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4551{
4552 struct audio_device *adev = (struct audio_device *)dev;
4553 struct str_parms *parms;
4554 char *str;
4555 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004556 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004557 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07004558 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004559
Joe Onorato188b6222016-03-01 11:02:27 -08004560 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004561
4562 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004563
4564 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004565 status = voice_set_parameters(adev, parms);
4566 if (status != 0) {
4567 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004568 }
4569
4570 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4571 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07004572 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004573 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4574 adev->bluetooth_nrec = true;
4575 else
4576 adev->bluetooth_nrec = false;
4577 }
4578
4579 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4580 if (ret >= 0) {
4581 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4582 adev->screen_off = false;
4583 else
4584 adev->screen_off = true;
4585 }
4586
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004587 ret = str_parms_get_int(parms, "rotation", &val);
4588 if (ret >= 0) {
4589 bool reverse_speakers = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004590 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004591 // FIXME: note that the code below assumes that the speakers are in the correct placement
4592 // relative to the user when the device is rotated 90deg from its default rotation. This
4593 // assumption is device-specific, not platform-specific like this code.
4594 case 270:
4595 reverse_speakers = true;
4596 break;
4597 case 0:
4598 case 90:
4599 case 180:
4600 break;
4601 default:
4602 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07004603 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004604 }
Eric Laurent03f09432014-03-25 18:09:11 -07004605 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004606 // check and set swap
4607 // - check if orientation changed and speaker active
4608 // - set rotation and cache the rotation value
4609 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004610 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004611 }
4612
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004613 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4614 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004615 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004616 }
4617
David Linee3fe402017-03-13 10:00:42 -07004618 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4619 if (ret >= 0) {
4620 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004621 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004622 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4623 if (ret >= 0) {
4624 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004625 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004626 }
Eric Laurent99dab492017-06-17 15:19:08 -07004627 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004628 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4629 if (ret >= 0) {
4630 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004631 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004632 }
4633 }
4634 }
4635
4636 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4637 if (ret >= 0) {
4638 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004639 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004640 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4641 if (ret >= 0) {
4642 const int card = atoi(value);
4643
Eric Laurent99dab492017-06-17 15:19:08 -07004644 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004645 }
Eric Laurent99dab492017-06-17 15:19:08 -07004646 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004647 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4648 if (ret >= 0) {
4649 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004650 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004651 }
4652 }
4653 }
4654
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004655 audio_extn_hfp_set_parameters(adev, parms);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004656 audio_extn_a2dp_set_parameters(parms);
4657 // reconfigure should be done only after updating A2DP state in audio extension
4658 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4659 if (ret >= 0) {
4660 struct audio_usecase *usecase;
4661 struct listnode *node;
4662 list_for_each(node, &adev->usecase_list) {
4663 usecase = node_to_item(node, struct audio_usecase, list);
4664 if ((usecase->type == PCM_PLAYBACK) &&
4665 (usecase->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP)) {
4666 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
4667
4668 pthread_mutex_unlock(&adev->lock);
4669 lock_output_stream(usecase->stream.out);
4670 pthread_mutex_lock(&adev->lock);
4671 audio_extn_a2dp_set_handoff_mode(true);
4672 // force device switch to reconfigure encoder
4673 select_devices(adev, usecase->id);
4674 audio_extn_a2dp_set_handoff_mode(false);
4675 pthread_mutex_unlock(&usecase->stream.out->lock);
4676 break;
4677 }
4678 }
4679 }
4680
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004681done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004682 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004683 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004684 ALOGV("%s: exit with code(%d)", __func__, status);
4685 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004686}
4687
4688static char* adev_get_parameters(const struct audio_hw_device *dev,
4689 const char *keys)
4690{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004691 struct audio_device *adev = (struct audio_device *)dev;
4692 struct str_parms *reply = str_parms_create();
4693 struct str_parms *query = str_parms_create_str(keys);
4694 char *str;
4695
4696 pthread_mutex_lock(&adev->lock);
4697
4698 voice_get_parameters(adev, query, reply);
4699 str = str_parms_to_str(reply);
4700 str_parms_destroy(query);
4701 str_parms_destroy(reply);
4702
4703 pthread_mutex_unlock(&adev->lock);
4704 ALOGV("%s: exit: returns - %s", __func__, str);
4705 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004706}
4707
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004708static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004709{
4710 return 0;
4711}
4712
Haynes Mathew George5191a852013-09-11 14:19:36 -07004713static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4714{
4715 int ret;
4716 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004717
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004718 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4719
Haynes Mathew George5191a852013-09-11 14:19:36 -07004720 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004721 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004722 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004723
Haynes Mathew George5191a852013-09-11 14:19:36 -07004724 return ret;
4725}
4726
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004727static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004728{
4729 return -ENOSYS;
4730}
4731
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004732static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4733 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004734{
4735 return -ENOSYS;
4736}
4737
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004738static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __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_get_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
4748static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4749{
4750 struct audio_device *adev = (struct audio_device *)dev;
4751
4752 pthread_mutex_lock(&adev->lock);
4753 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004754 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004755 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004756 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4757 voice_is_in_call(adev)) {
4758 voice_stop_call(adev);
4759 adev->current_call_output = NULL;
4760 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004761 }
4762 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004763
4764 audio_extn_extspk_set_mode(adev->extspk, mode);
4765
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004766 return 0;
4767}
4768
4769static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4770{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004771 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004772 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004773
Eric Laurent2bafff12016-03-17 12:17:23 -07004774 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004775 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004776 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4777 ret = audio_extn_hfp_set_mic_mute(adev, state);
4778 } else {
4779 ret = voice_set_mic_mute(adev, state);
4780 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004781 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004782 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004783
4784 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004785}
4786
4787static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4788{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004789 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004790 return 0;
4791}
4792
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004793static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004794 const struct audio_config *config)
4795{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004796 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004797
Eric Laurent74b55762017-07-09 17:04:53 -07004798 /* Don't know if USB HIFI in this context so use true to be conservative */
4799 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4800 true /*is_usb_hifi */) != 0)
4801 return 0;
4802
vivek mehtaa68fea62017-06-08 19:04:02 -07004803 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4804 config->sample_rate, config->format,
4805 channel_count,
4806 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004807}
4808
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004809static bool adev_input_allow_hifi_record(struct audio_device *adev,
4810 audio_devices_t devices,
4811 audio_input_flags_t flags,
4812 audio_source_t source) {
4813 const bool allowed = true;
4814
4815 if (!audio_is_usb_in_device(devices))
4816 return !allowed;
4817
4818 switch (flags) {
4819 case AUDIO_INPUT_FLAG_NONE:
4820 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4821 break;
4822 default:
4823 return !allowed;
4824 }
4825
4826 switch (source) {
4827 case AUDIO_SOURCE_DEFAULT:
4828 case AUDIO_SOURCE_MIC:
4829 case AUDIO_SOURCE_UNPROCESSED:
4830 break;
4831 default:
4832 return !allowed;
4833 }
4834
4835 switch (adev->mode) {
4836 case 0:
4837 break;
4838 default:
4839 return !allowed;
4840 }
4841
4842 return allowed;
4843}
4844
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004845static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004846 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004847 audio_devices_t devices,
4848 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004849 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004850 audio_input_flags_t flags,
4851 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004852 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004853{
4854 struct audio_device *adev = (struct audio_device *)dev;
4855 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004856 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004857 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004858 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004859 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004860 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4861 devices,
4862 flags,
4863 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004864 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004865 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004866
Andy Hungd9653bd2017-08-01 19:31:39 -07004867 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
4868 return -ENOSYS;
4869 }
4870
Eric Laurent74b55762017-07-09 17:04:53 -07004871 if (!(is_usb_dev && may_use_hifi_record)) {
4872 if (config->sample_rate == 0)
4873 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4874 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4875 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4876 if (config->format == AUDIO_FORMAT_DEFAULT)
4877 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004878
Eric Laurent74b55762017-07-09 17:04:53 -07004879 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
4880
4881 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
4882 return -EINVAL;
4883 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004884
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004885 if (audio_extn_tfa_98xx_is_supported() &&
4886 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004887 return -EINVAL;
4888
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004889 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4890
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004891 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004892 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004893
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004894 in->stream.common.get_sample_rate = in_get_sample_rate;
4895 in->stream.common.set_sample_rate = in_set_sample_rate;
4896 in->stream.common.get_buffer_size = in_get_buffer_size;
4897 in->stream.common.get_channels = in_get_channels;
4898 in->stream.common.get_format = in_get_format;
4899 in->stream.common.set_format = in_set_format;
4900 in->stream.common.standby = in_standby;
4901 in->stream.common.dump = in_dump;
4902 in->stream.common.set_parameters = in_set_parameters;
4903 in->stream.common.get_parameters = in_get_parameters;
4904 in->stream.common.add_audio_effect = in_add_audio_effect;
4905 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4906 in->stream.set_gain = in_set_gain;
4907 in->stream.read = in_read;
4908 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08004909 in->stream.get_capture_position = in_get_capture_position;
jiabin8962a4d2018-03-19 18:21:24 -07004910 in->stream.get_active_microphones = in_get_active_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004911
4912 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004913 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004914 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004915 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004916 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004917 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004918
Haynes Mathew George569b7482017-05-08 14:44:27 -07004919 if (is_usb_dev && may_use_hifi_record) {
4920 /* HiFi record selects an appropriate format, channel, rate combo
4921 depending on sink capabilities*/
4922 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
4923 &config->format,
4924 &in->supported_formats[0],
4925 MAX_SUPPORTED_FORMATS,
4926 &config->channel_mask,
4927 &in->supported_channel_masks[0],
4928 MAX_SUPPORTED_CHANNEL_MASKS,
4929 &config->sample_rate,
4930 &in->supported_sample_rates[0],
4931 MAX_SUPPORTED_SAMPLE_RATES);
4932 if (ret != 0) {
4933 ret = -EINVAL;
4934 goto err_open;
4935 }
Eric Laurent74b55762017-07-09 17:04:53 -07004936 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004937 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07004938 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07004939 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
4940 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
4941 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4942 bool ret_error = false;
4943 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4944 from HAL is 8_24
4945 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4946 8_24 return error indicating supported format is 8_24
4947 *> In case of any other source requesting 24 bit or float return error
4948 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07004949
vivek mehta57ff9b52016-04-28 14:13:08 -07004950 on error flinger will retry with supported format passed
4951 */
4952 if (source != AUDIO_SOURCE_UNPROCESSED) {
4953 config->format = AUDIO_FORMAT_PCM_16_BIT;
4954 ret_error = true;
4955 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
4956 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
4957 ret_error = true;
4958 }
4959
4960 if (ret_error) {
4961 ret = -EINVAL;
4962 goto err_open;
4963 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004964 }
4965
vivek mehta57ff9b52016-04-28 14:13:08 -07004966 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07004967 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07004968
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004969 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004970 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
4971 if (config->sample_rate == 0)
4972 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4973 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4974 config->sample_rate != 8000) {
4975 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4976 ret = -EINVAL;
4977 goto err_open;
4978 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004979
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004980 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4981 config->format = AUDIO_FORMAT_PCM_16_BIT;
4982 ret = -EINVAL;
4983 goto err_open;
4984 }
4985
4986 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4987 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07004988 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004989 } else if (is_usb_dev && may_use_hifi_record) {
4990 in->usecase = USECASE_AUDIO_RECORD_HIFI;
4991 in->config = pcm_config_audio_capture;
4992 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004993 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4994 config->sample_rate,
4995 config->format,
4996 channel_count,
4997 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004998 in->config.period_size = buffer_size / frame_size;
4999 in->config.rate = config->sample_rate;
5000 in->af_period_multiplier = 1;
5001 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005002 } else {
5003 in->usecase = USECASE_AUDIO_RECORD;
5004 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08005005 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005006 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07005007#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005008 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07005009#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08005010 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005011 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08005012 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005013 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005014 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5015 config->sample_rate,
5016 config->format,
5017 channel_count,
5018 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005019 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005020 in->config.rate = config->sample_rate;
5021 in->af_period_multiplier = 1;
5022 } else {
5023 // period size is left untouched for rt mode playback
5024 in->config = pcm_config_audio_capture_rt;
5025 in->af_period_multiplier = af_period_multiplier;
5026 }
5027 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
5028 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005029 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08005030 in->usecase = USECASE_AUDIO_RECORD_MMAP;
5031 in->config = pcm_config_mmap_capture;
5032 in->stream.start = in_start;
5033 in->stream.stop = in_stop;
5034 in->stream.create_mmap_buffer = in_create_mmap_buffer;
5035 in->stream.get_mmap_position = in_get_mmap_position;
5036 in->af_period_multiplier = 1;
5037 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07005038 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07005039 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07005040 (config->sample_rate == 8000 ||
5041 config->sample_rate == 16000 ||
5042 config->sample_rate == 32000 ||
5043 config->sample_rate == 48000) &&
5044 channel_count == 1) {
5045 in->usecase = USECASE_AUDIO_RECORD_VOIP;
5046 in->config = pcm_config_audio_capture;
5047 frame_size = audio_stream_in_frame_size(&in->stream);
5048 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
5049 config->sample_rate,
5050 config->format,
5051 channel_count, false /*is_low_latency*/);
5052 in->config.period_size = buffer_size / frame_size;
5053 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
5054 in->config.rate = config->sample_rate;
5055 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005056 } else {
5057 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005058 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005059 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5060 config->sample_rate,
5061 config->format,
5062 channel_count,
5063 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005064 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005065 in->config.rate = config->sample_rate;
5066 in->af_period_multiplier = 1;
5067 }
5068 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
5069 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005070 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08005071
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005072 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07005073 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005074
Kevin Rocarda325aa22018-04-03 09:15:52 -07005075
5076 register_format(in->format, in->supported_formats);
5077 register_channel_mask(in->channel_mask, in->supported_channel_masks);
5078 register_sample_rate(in->sample_rate, in->supported_sample_rates);
5079
Andy Hungd13f0d32017-06-12 13:58:37 -07005080 in->error_log = error_log_create(
5081 ERROR_LOG_ENTRIES,
5082 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
5083
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005084 /* This stream could be for sound trigger lab,
5085 get sound trigger pcm if present */
5086 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005087
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005088 lock_input_stream(in);
5089 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5090 pthread_mutex_lock(&adev->lock);
5091 in->card_status = adev->card_status;
5092 pthread_mutex_unlock(&adev->lock);
5093 pthread_mutex_unlock(&in->lock);
5094
vivek mehta4a824772017-06-08 19:05:49 -07005095 stream_app_type_cfg_init(&in->app_type_cfg);
5096
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005097 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005098 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005099 return 0;
5100
5101err_open:
5102 free(in);
5103 *stream_in = NULL;
5104 return ret;
5105}
5106
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005107static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005108 struct audio_stream_in *stream)
5109{
Andy Hungd13f0d32017-06-12 13:58:37 -07005110 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005111 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005112
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005113 // must deregister from sndmonitor first to prevent races
5114 // between the callback and close_stream
5115 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005116 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07005117
5118 error_log_destroy(in->error_log);
5119 in->error_log = NULL;
5120
Andy Hung0dbb52b2017-08-09 13:51:38 -07005121 pthread_mutex_destroy(&in->pre_lock);
5122 pthread_mutex_destroy(&in->lock);
5123
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005124 free(stream);
5125
5126 return;
5127}
5128
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005129static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005130{
5131 return 0;
5132}
5133
Andy Hung31aca912014-03-20 17:14:59 -07005134/* verifies input and output devices and their capabilities.
5135 *
5136 * This verification is required when enabling extended bit-depth or
5137 * sampling rates, as not all qcom products support it.
5138 *
5139 * Suitable for calling only on initialization such as adev_open().
5140 * It fills the audio_device use_case_table[] array.
5141 *
5142 * Has a side-effect that it needs to configure audio routing / devices
5143 * in order to power up the devices and read the device parameters.
5144 * It does not acquire any hw device lock. Should restore the devices
5145 * back to "normal state" upon completion.
5146 */
5147static int adev_verify_devices(struct audio_device *adev)
5148{
5149 /* enumeration is a bit difficult because one really wants to pull
5150 * the use_case, device id, etc from the hidden pcm_device_table[].
5151 * In this case there are the following use cases and device ids.
5152 *
5153 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
5154 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005155 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07005156 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
5157 * [USECASE_AUDIO_RECORD] = {0, 0},
5158 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
5159 * [USECASE_VOICE_CALL] = {2, 2},
5160 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005161 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07005162 * USECASE_VOICE_CALL omitted, but possible for either input or output.
5163 */
5164
5165 /* should be the usecases enabled in adev_open_input_stream() */
5166 static const int test_in_usecases[] = {
5167 USECASE_AUDIO_RECORD,
5168 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
5169 };
5170 /* should be the usecases enabled in adev_open_output_stream()*/
5171 static const int test_out_usecases[] = {
5172 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
5173 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
5174 };
5175 static const usecase_type_t usecase_type_by_dir[] = {
5176 PCM_PLAYBACK,
5177 PCM_CAPTURE,
5178 };
5179 static const unsigned flags_by_dir[] = {
5180 PCM_OUT,
5181 PCM_IN,
5182 };
5183
5184 size_t i;
5185 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005186 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07005187 char info[512]; /* for possible debug info */
5188
5189 for (dir = 0; dir < 2; ++dir) {
5190 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
5191 const unsigned flags_dir = flags_by_dir[dir];
5192 const size_t testsize =
5193 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
5194 const int *testcases =
5195 dir ? test_in_usecases : test_out_usecases;
5196 const audio_devices_t audio_device =
5197 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
5198
5199 for (i = 0; i < testsize; ++i) {
5200 const audio_usecase_t audio_usecase = testcases[i];
5201 int device_id;
5202 snd_device_t snd_device;
5203 struct pcm_params **pparams;
5204 struct stream_out out;
5205 struct stream_in in;
5206 struct audio_usecase uc_info;
5207 int retval;
5208
5209 pparams = &adev->use_case_table[audio_usecase];
5210 pcm_params_free(*pparams); /* can accept null input */
5211 *pparams = NULL;
5212
5213 /* find the device ID for the use case (signed, for error) */
5214 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
5215 if (device_id < 0)
5216 continue;
5217
5218 /* prepare structures for device probing */
5219 memset(&uc_info, 0, sizeof(uc_info));
5220 uc_info.id = audio_usecase;
5221 uc_info.type = usecase_type;
5222 if (dir) {
5223 adev->active_input = &in;
5224 memset(&in, 0, sizeof(in));
5225 in.device = audio_device;
5226 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
5227 uc_info.stream.in = &in;
5228 } else {
5229 adev->active_input = NULL;
5230 }
5231 memset(&out, 0, sizeof(out));
5232 out.devices = audio_device; /* only field needed in select_devices */
5233 uc_info.stream.out = &out;
5234 uc_info.devices = audio_device;
5235 uc_info.in_snd_device = SND_DEVICE_NONE;
5236 uc_info.out_snd_device = SND_DEVICE_NONE;
5237 list_add_tail(&adev->usecase_list, &uc_info.list);
5238
5239 /* select device - similar to start_(in/out)put_stream() */
5240 retval = select_devices(adev, audio_usecase);
5241 if (retval >= 0) {
5242 *pparams = pcm_params_get(card_id, device_id, flags_dir);
5243#if LOG_NDEBUG == 0
5244 if (*pparams) {
5245 ALOGV("%s: (%s) card %d device %d", __func__,
5246 dir ? "input" : "output", card_id, device_id);
5247 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07005248 } else {
5249 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
5250 }
5251#endif
5252 }
5253
5254 /* deselect device - similar to stop_(in/out)put_stream() */
5255 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07005256 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07005257 /* 2. Disable the rx device */
5258 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07005259 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07005260 list_remove(&uc_info.list);
5261 }
5262 }
5263 adev->active_input = NULL; /* restore adev state */
5264 return 0;
5265}
5266
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005267static int adev_close(hw_device_t *device)
5268{
Andy Hung31aca912014-03-20 17:14:59 -07005269 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005270 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005271
5272 if (!adev)
5273 return 0;
5274
5275 pthread_mutex_lock(&adev_init_lock);
5276
5277 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005278 audio_extn_snd_mon_unregister_listener(adev);
5279 audio_extn_tfa_98xx_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005280 audio_route_free(adev->audio_route);
5281 free(adev->snd_dev_ref_cnt);
5282 platform_deinit(adev->platform);
5283 audio_extn_extspk_deinit(adev->extspk);
5284 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005285 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005286 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
5287 pcm_params_free(adev->use_case_table[i]);
5288 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005289 if (adev->adm_deinit)
5290 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005291 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005292 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07005293 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07005294
5295 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005296
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005297 return 0;
5298}
5299
Glenn Kasten4f993392014-05-14 07:30:48 -07005300/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5301 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5302 * just that it _might_ work.
5303 */
5304static int period_size_is_plausible_for_low_latency(int period_size)
5305{
5306 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005307 case 48:
5308 case 96:
5309 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07005310 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005311 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07005312 case 240:
5313 case 320:
5314 case 480:
5315 return 1;
5316 default:
5317 return 0;
5318 }
5319}
5320
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005321static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
5322{
5323 int card;
5324 card_status_t status;
5325
5326 if (!parms)
5327 return;
5328
5329 if (parse_snd_card_status(parms, &card, &status) < 0)
5330 return;
5331
5332 pthread_mutex_lock(&adev->lock);
5333 bool valid_cb = (card == adev->snd_card);
5334 if (valid_cb) {
5335 if (adev->card_status != status) {
5336 adev->card_status = status;
5337 platform_snd_card_update(adev->platform, status);
5338 }
5339 }
5340 pthread_mutex_unlock(&adev->lock);
5341 return;
5342}
5343
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005344/* out and adev lock held */
5345static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
5346{
5347 struct audio_usecase *uc_info;
5348 float left_p;
5349 float right_p;
5350 audio_devices_t devices;
5351
5352 uc_info = get_usecase_from_list(adev, out->usecase);
5353 if (uc_info == NULL) {
5354 ALOGE("%s: Could not find the usecase (%d) in the list",
5355 __func__, out->usecase);
5356 return -EINVAL;
5357 }
5358
5359 ALOGD("%s: enter: usecase(%d: %s)", __func__,
5360 out->usecase, use_case_table[out->usecase]);
5361
5362 if (restore) {
5363 // restore A2DP device for active usecases and unmute if required
5364 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
5365 !is_a2dp_device(uc_info->out_snd_device)) {
5366 ALOGD("%s: restoring A2DP and unmuting stream", __func__);
5367 select_devices(adev, uc_info->id);
5368 pthread_mutex_lock(&out->compr_mute_lock);
5369 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5370 (out->a2dp_compress_mute)) {
5371 out->a2dp_compress_mute = false;
5372 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5373 }
5374 pthread_mutex_unlock(&out->compr_mute_lock);
5375 }
5376 } else {
5377 // mute compress stream if suspended
5378 pthread_mutex_lock(&out->compr_mute_lock);
5379 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5380 (!out->a2dp_compress_mute)) {
5381 if (!out->standby) {
5382 ALOGD("%s: selecting speaker and muting stream", __func__);
5383 devices = out->devices;
5384 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
5385 left_p = out->volume_l;
5386 right_p = out->volume_r;
5387 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5388 compress_pause(out->compr);
5389 set_compr_volume(&out->stream, 0.0f, 0.0f);
5390 out->a2dp_compress_mute = true;
5391 select_devices(adev, out->usecase);
5392 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5393 compress_resume(out->compr);
5394 out->devices = devices;
5395 out->volume_l = left_p;
5396 out->volume_r = right_p;
5397 }
5398 }
5399 pthread_mutex_unlock(&out->compr_mute_lock);
5400 }
5401 ALOGV("%s: exit", __func__);
5402 return 0;
5403}
5404
5405int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
5406{
5407 int ret = 0;
5408
5409 lock_output_stream(out);
5410 pthread_mutex_lock(&adev->lock);
5411
5412 ret = check_a2dp_restore_l(adev, out, restore);
5413
5414 pthread_mutex_unlock(&adev->lock);
5415 pthread_mutex_unlock(&out->lock);
5416 return ret;
5417}
5418
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005419static int adev_open(const hw_module_t *module, const char *name,
5420 hw_device_t **device)
5421{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005422 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005423
Eric Laurent2bafff12016-03-17 12:17:23 -07005424 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005425 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005426 pthread_mutex_lock(&adev_init_lock);
5427 if (audio_device_ref_count != 0) {
5428 *device = &adev->device.common;
5429 audio_device_ref_count++;
5430 ALOGV("%s: returning existing instance of adev", __func__);
5431 ALOGV("%s: exit", __func__);
5432 pthread_mutex_unlock(&adev_init_lock);
5433 return 0;
5434 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005435 adev = calloc(1, sizeof(struct audio_device));
5436
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005437 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5438
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005439 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5440 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5441 adev->device.common.module = (struct hw_module_t *)module;
5442 adev->device.common.close = adev_close;
5443
5444 adev->device.init_check = adev_init_check;
5445 adev->device.set_voice_volume = adev_set_voice_volume;
5446 adev->device.set_master_volume = adev_set_master_volume;
5447 adev->device.get_master_volume = adev_get_master_volume;
5448 adev->device.set_master_mute = adev_set_master_mute;
5449 adev->device.get_master_mute = adev_get_master_mute;
5450 adev->device.set_mode = adev_set_mode;
5451 adev->device.set_mic_mute = adev_set_mic_mute;
5452 adev->device.get_mic_mute = adev_get_mic_mute;
5453 adev->device.set_parameters = adev_set_parameters;
5454 adev->device.get_parameters = adev_get_parameters;
5455 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5456 adev->device.open_output_stream = adev_open_output_stream;
5457 adev->device.close_output_stream = adev_close_output_stream;
5458 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005459
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005460 adev->device.close_input_stream = adev_close_input_stream;
5461 adev->device.dump = adev_dump;
jiabin8962a4d2018-03-19 18:21:24 -07005462 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005463
5464 /* Set the default route before the PCM stream is opened */
5465 pthread_mutex_lock(&adev->lock);
5466 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005467 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005468 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005469 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005470 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005471 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005472 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005473 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005474 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005475 pthread_mutex_unlock(&adev->lock);
5476
5477 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005478 adev->platform = platform_init(adev);
5479 if (!adev->platform) {
5480 free(adev->snd_dev_ref_cnt);
5481 free(adev);
5482 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5483 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005484 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005485 return -EINVAL;
5486 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05005487 adev->extspk = audio_extn_extspk_init(adev);
5488
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005489 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5490 if (adev->visualizer_lib == NULL) {
5491 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5492 } else {
5493 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5494 adev->visualizer_start_output =
5495 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5496 "visualizer_hal_start_output");
5497 adev->visualizer_stop_output =
5498 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5499 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07005500 }
5501
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005502 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5503 if (adev->offload_effects_lib == NULL) {
5504 ALOGW("%s: DLOPEN failed for %s", __func__,
5505 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5506 } else {
5507 ALOGV("%s: DLOPEN successful for %s", __func__,
5508 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5509 adev->offload_effects_start_output =
5510 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5511 "offload_effects_bundle_hal_start_output");
5512 adev->offload_effects_stop_output =
5513 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5514 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07005515 }
5516
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005517 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5518 if (adev->adm_lib == NULL) {
5519 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5520 } else {
5521 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5522 adev->adm_init = (adm_init_t)
5523 dlsym(adev->adm_lib, "adm_init");
5524 adev->adm_deinit = (adm_deinit_t)
5525 dlsym(adev->adm_lib, "adm_deinit");
5526 adev->adm_register_input_stream = (adm_register_input_stream_t)
5527 dlsym(adev->adm_lib, "adm_register_input_stream");
5528 adev->adm_register_output_stream = (adm_register_output_stream_t)
5529 dlsym(adev->adm_lib, "adm_register_output_stream");
5530 adev->adm_deregister_stream = (adm_deregister_stream_t)
5531 dlsym(adev->adm_lib, "adm_deregister_stream");
5532 adev->adm_request_focus = (adm_request_focus_t)
5533 dlsym(adev->adm_lib, "adm_request_focus");
5534 adev->adm_abandon_focus = (adm_abandon_focus_t)
5535 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08005536 adev->adm_set_config = (adm_set_config_t)
5537 dlsym(adev->adm_lib, "adm_set_config");
5538 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5539 dlsym(adev->adm_lib, "adm_request_focus_v2");
5540 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5541 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5542 adev->adm_on_routing_change = (adm_on_routing_change_t)
5543 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005544 }
5545
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005546 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005547 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005548
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005549 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005550
Andy Hung31aca912014-03-20 17:14:59 -07005551 if (k_enable_extended_precision)
5552 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005553
Glenn Kasten4f993392014-05-14 07:30:48 -07005554 char value[PROPERTY_VALUE_MAX];
5555 int trial;
5556 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5557 trial = atoi(value);
5558 if (period_size_is_plausible_for_low_latency(trial)) {
5559 pcm_config_low_latency.period_size = trial;
5560 pcm_config_low_latency.start_threshold = trial / 4;
5561 pcm_config_low_latency.avail_min = trial / 4;
5562 configured_low_latency_capture_period_size = trial;
5563 }
5564 }
5565 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5566 trial = atoi(value);
5567 if (period_size_is_plausible_for_low_latency(trial)) {
5568 configured_low_latency_capture_period_size = trial;
5569 }
5570 }
5571
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005572 // commented as full set of app type cfg is sent from platform
5573 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005574 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005575
5576 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5577 af_period_multiplier = atoi(value);
5578 if (af_period_multiplier < 0) {
5579 af_period_multiplier = 2;
5580 } else if (af_period_multiplier > 4) {
5581 af_period_multiplier = 4;
5582 }
5583 ALOGV("new period_multiplier = %d", af_period_multiplier);
5584 }
5585
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005586 audio_extn_tfa_98xx_init(adev);
5587
vivek mehta1a9b7c02015-06-25 11:49:38 -07005588 pthread_mutex_unlock(&adev_init_lock);
5589
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005590 if (adev->adm_init)
5591 adev->adm_data = adev->adm_init();
5592
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005593 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005594 audio_extn_snd_mon_init();
5595 pthread_mutex_lock(&adev->lock);
5596 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
5597 adev->card_status = CARD_STATUS_ONLINE;
5598 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005599 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005600
Eric Laurent2bafff12016-03-17 12:17:23 -07005601 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005602 return 0;
5603}
5604
5605static struct hw_module_methods_t hal_module_methods = {
5606 .open = adev_open,
5607};
5608
5609struct audio_module HAL_MODULE_INFO_SYM = {
5610 .common = {
5611 .tag = HARDWARE_MODULE_TAG,
5612 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5613 .hal_api_version = HARDWARE_HAL_API_VERSION,
5614 .id = AUDIO_HARDWARE_MODULE_ID,
5615 .name = "QCOM Audio HAL",
5616 .author = "Code Aurora Forum",
5617 .methods = &hal_module_methods,
5618 },
5619};