blob: 34ad014ab9dccfe8c1c495a897714451931fac8b [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
vivek mehtaa51fd402016-02-04 19:49:33 -08002 * Copyright (C) 2013-2016 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "audio_hw_primary"
Haynes Mathew George03c40102016-01-29 17:57:48 -080018#define ATRACE_TAG ATRACE_TAG_AUDIO
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080019/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070020/*#define VERY_VERY_VERBOSE_LOGGING*/
21#ifdef VERY_VERY_VERBOSE_LOGGING
22#define ALOGVV ALOGV
23#else
24#define ALOGVV(a...) do { } while(0)
25#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080026
27#include <errno.h>
28#include <pthread.h>
29#include <stdint.h>
30#include <sys/time.h>
31#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080032#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070033#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070034#include <sys/resource.h>
35#include <sys/prctl.h>
Kevin Rocardb5c28192017-05-02 15:30:20 -070036#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080037
Haynes Mathew Georgee6e2d442018-02-22 18:51:56 -080038#include <log/log.h>
Haynes Mathew George03c40102016-01-29 17:57:48 -080039#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040#include <cutils/str_parms.h>
41#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070042#include <cutils/atomic.h>
43#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080044
Eric Laurentb23d5282013-05-14 15:27:20 -070045#include <hardware/audio_effect.h>
Andy Hung31aca912014-03-20 17:14:59 -070046#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070047#include <system/thread_defs.h>
Phil Burkbc991042017-02-24 08:06:44 -080048#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070049#include <audio_effects/effect_aec.h>
50#include <audio_effects/effect_ns.h>
Andy Hungfc044e12017-03-20 09:24:22 -070051#include <audio_utils/clock.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052#include "audio_hw.h"
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -080053#include "audio_extn.h"
Wei Wangf4837d52017-11-21 14:51:20 -080054#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070055#include "platform_api.h"
56#include <platform.h>
Vineeta Srivastava4b89e372014-06-19 14:21:42 -070057#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080058
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070059#include "sound/compress_params.h"
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -080060#include "audio_extn/tfa_98xx.h"
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070061
Eric Laurent397db572016-05-11 11:31:47 -070062/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
63 * COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
Marco Nelissen32093f52015-04-08 15:14:02 -070064#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070065// 2 buffers causes problems with high bitrate files
66#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070067/* ToDo: Check and update a proper value in msec */
68#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
vivek mehta4a824772017-06-08 19:05:49 -070069/* treat as unsigned Q1.13 */
70#define APP_TYPE_GAIN_DEFAULT 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070071#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
vivek mehta4a824772017-06-08 19:05:49 -070072
73/* treat as unsigned Q1.13 */
vivek mehtaa68fea62017-06-08 19:04:02 -070074#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070075
Eric Laurent51f3c662018-04-10 18:21:34 -070076#define RECORD_GAIN_MIN 0.0f
77#define RECORD_GAIN_MAX 1.0f
78#define RECORD_VOLUME_CTL_MAX 0x2000
79
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070080#define PROXY_OPEN_RETRY_COUNT 100
81#define PROXY_OPEN_WAIT_TIME 20
82
vivek mehtadae44712015-07-27 14:13:18 -070083#define MIN_CHANNEL_COUNT 1
84#define DEFAULT_CHANNEL_COUNT 2
85
Jean-Michel Trivic0750692015-10-12 12:12:32 -070086#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
87#define MAX_CHANNEL_COUNT 1
88#else
vivek mehtadae44712015-07-27 14:13:18 -070089#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
90#define XSTR(x) STR(x)
91#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070092#endif
Eric Laurent74b55762017-07-09 17:04:53 -070093#define MAX_HIFI_CHANNEL_COUNT 8
vivek mehtadae44712015-07-27 14:13:18 -070094
Haynes Mathew George03c40102016-01-29 17:57:48 -080095#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
96
Glenn Kasten4f993392014-05-14 07:30:48 -070097static unsigned int configured_low_latency_capture_period_size =
98 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
99
Eric Laurent0e46adf2016-12-16 12:49:24 -0800100
101#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Phil Burkbc991042017-02-24 08:06:44 -0800102#define MMAP_PERIOD_COUNT_MIN 32
103#define MMAP_PERIOD_COUNT_MAX 512
104#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
Eric Laurent0e46adf2016-12-16 12:49:24 -0800105
Andy Hung31aca912014-03-20 17:14:59 -0700106/* This constant enables extended precision handling.
107 * TODO The flag is off until more testing is done.
108 */
109static const bool k_enable_extended_precision = false;
110
Eric Laurentb23d5282013-05-14 15:27:20 -0700111struct pcm_config pcm_config_deep_buffer = {
vivek mehtadae44712015-07-27 14:13:18 -0700112 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700113 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
114 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
115 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
116 .format = PCM_FORMAT_S16_LE,
117 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
118 .stop_threshold = INT_MAX,
119 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
120};
121
122struct pcm_config pcm_config_low_latency = {
vivek mehtadae44712015-07-27 14:13:18 -0700123 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700124 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
125 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
126 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
127 .format = PCM_FORMAT_S16_LE,
128 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
129 .stop_threshold = INT_MAX,
130 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
131};
132
Haynes Mathew George03c40102016-01-29 17:57:48 -0800133static int af_period_multiplier = 4;
134struct pcm_config pcm_config_rt = {
135 .channels = DEFAULT_CHANNEL_COUNT,
136 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
137 .period_size = ULL_PERIOD_SIZE, //1 ms
138 .period_count = 512, //=> buffer size is 512ms
139 .format = PCM_FORMAT_S16_LE,
140 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
141 .stop_threshold = INT_MAX,
142 .silence_threshold = 0,
143 .silence_size = 0,
144 .avail_min = ULL_PERIOD_SIZE, //1 ms
145};
146
Eric Laurentb23d5282013-05-14 15:27:20 -0700147struct pcm_config pcm_config_hdmi_multi = {
148 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
149 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
150 .period_size = HDMI_MULTI_PERIOD_SIZE,
151 .period_count = HDMI_MULTI_PERIOD_COUNT,
152 .format = PCM_FORMAT_S16_LE,
153 .start_threshold = 0,
154 .stop_threshold = INT_MAX,
155 .avail_min = 0,
156};
157
Eric Laurent0e46adf2016-12-16 12:49:24 -0800158struct pcm_config pcm_config_mmap_playback = {
159 .channels = DEFAULT_CHANNEL_COUNT,
160 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
161 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800162 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800163 .format = PCM_FORMAT_S16_LE,
164 .start_threshold = MMAP_PERIOD_SIZE*8,
165 .stop_threshold = INT32_MAX,
166 .silence_threshold = 0,
167 .silence_size = 0,
168 .avail_min = MMAP_PERIOD_SIZE, //1 ms
169};
170
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800171struct pcm_config pcm_config_hifi = {
172 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
173 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
174 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
175 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
176 .format = PCM_FORMAT_S24_3LE,
177 .start_threshold = 0,
178 .stop_threshold = INT_MAX,
179 .avail_min = 0,
180};
181
Eric Laurentb23d5282013-05-14 15:27:20 -0700182struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700183 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700184 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
185 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700186 .stop_threshold = INT_MAX,
187 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700188};
189
Haynes Mathew George03c40102016-01-29 17:57:48 -0800190struct pcm_config pcm_config_audio_capture_rt = {
191 .channels = DEFAULT_CHANNEL_COUNT,
192 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
193 .period_size = ULL_PERIOD_SIZE,
194 .period_count = 512,
195 .format = PCM_FORMAT_S16_LE,
196 .start_threshold = 0,
197 .stop_threshold = INT_MAX,
198 .silence_threshold = 0,
199 .silence_size = 0,
200 .avail_min = ULL_PERIOD_SIZE, //1 ms
201};
202
Eric Laurent0e46adf2016-12-16 12:49:24 -0800203struct pcm_config pcm_config_mmap_capture = {
204 .channels = DEFAULT_CHANNEL_COUNT,
205 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
206 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800207 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800208 .format = PCM_FORMAT_S16_LE,
209 .start_threshold = 0,
210 .stop_threshold = INT_MAX,
211 .silence_threshold = 0,
212 .silence_size = 0,
213 .avail_min = MMAP_PERIOD_SIZE, //1 ms
214};
215
vivek mehtaa68fea62017-06-08 19:04:02 -0700216struct pcm_config pcm_config_voip = {
217 .channels = 1,
218 .period_count = 2,
219 .format = PCM_FORMAT_S16_LE,
220 .stop_threshold = INT_MAX,
221 .avail_min = 0,
222};
223
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700224#define AFE_PROXY_CHANNEL_COUNT 2
225#define AFE_PROXY_SAMPLING_RATE 48000
226
227#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
228#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
229
230struct pcm_config pcm_config_afe_proxy_playback = {
231 .channels = AFE_PROXY_CHANNEL_COUNT,
232 .rate = AFE_PROXY_SAMPLING_RATE,
233 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
234 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
235 .format = PCM_FORMAT_S16_LE,
236 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
237 .stop_threshold = INT_MAX,
238 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
239};
240
241#define AFE_PROXY_RECORD_PERIOD_SIZE 768
242#define AFE_PROXY_RECORD_PERIOD_COUNT 4
243
244struct pcm_config pcm_config_afe_proxy_record = {
245 .channels = AFE_PROXY_CHANNEL_COUNT,
246 .rate = AFE_PROXY_SAMPLING_RATE,
247 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
248 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
249 .format = PCM_FORMAT_S16_LE,
250 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
251 .stop_threshold = INT_MAX,
252 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
253};
254
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700255const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700256 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
257 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800258 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700259 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700260 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700261 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800262 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700263
Eric Laurentb23d5282013-05-14 15:27:20 -0700264 [USECASE_AUDIO_RECORD] = "audio-record",
265 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800266 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George569b7482017-05-08 14:44:27 -0700267 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700268
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800269 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
270 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700271
Eric Laurentb23d5282013-05-14 15:27:20 -0700272 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700273 [USECASE_VOICE2_CALL] = "voice2-call",
274 [USECASE_VOLTE_CALL] = "volte-call",
275 [USECASE_QCHAT_CALL] = "qchat-call",
276 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800277 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
278 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700279
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700280 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
281 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
282
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700283 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
284 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
vivek mehta781065c2017-04-04 12:55:01 -0700285
286 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
287 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
288 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
289
vivek mehtaa68fea62017-06-08 19:04:02 -0700290 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
291 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Nadav Bar3d72cfc2018-01-07 12:19:24 +0200292
293 [USECASE_INCALL_MUSIC_UPLINK] = "incall-music-uplink",
Aniket Kumar Lata99546312018-03-19 21:38:38 -0700294
295 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700296};
297
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800298
299#define STRING_TO_ENUM(string) { #string, string }
300
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800301struct string_to_enum {
302 const char *name;
303 uint32_t value;
304};
305
Haynes Mathew George569b7482017-05-08 14:44:27 -0700306static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800307 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
308 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
309 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Eric Laurent74b55762017-07-09 17:04:53 -0700310 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
Haynes Mathew George569b7482017-05-08 14:44:27 -0700311 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
Eric Laurent74b55762017-07-09 17:04:53 -0700312 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
313 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
314 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
315 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
316 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
317 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
318 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
319 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
320 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800321};
322
Haynes Mathew George5191a852013-09-11 14:19:36 -0700323static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700324static struct audio_device *adev = NULL;
Andy Hung9e737de2017-05-22 10:51:22 -0700325static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700326static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700327//cache last MBDRC cal step level
328static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700329
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800330static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
331static int set_compr_volume(struct audio_stream_out *stream, float left, float right);
332
Haynes Mathew George03c40102016-01-29 17:57:48 -0800333static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
334 int flags __unused)
335{
336 int dir = 0;
337 switch (uc_id) {
338 case USECASE_AUDIO_RECORD_LOW_LATENCY:
339 dir = 1;
340 case USECASE_AUDIO_PLAYBACK_ULL:
341 break;
342 default:
343 return false;
344 }
345
346 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
347 PCM_PLAYBACK : PCM_CAPTURE);
348 if (adev->adm_is_noirq_avail)
349 return adev->adm_is_noirq_avail(adev->adm_data,
350 adev->snd_card, dev_id, dir);
351 return false;
352}
353
354static void register_out_stream(struct stream_out *out)
355{
356 struct audio_device *adev = out->dev;
357 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
358 return;
359
360 if (!adev->adm_register_output_stream)
361 return;
362
363 adev->adm_register_output_stream(adev->adm_data,
364 out->handle,
365 out->flags);
366
367 if (!adev->adm_set_config)
368 return;
369
370 if (out->realtime) {
371 adev->adm_set_config(adev->adm_data,
372 out->handle,
373 out->pcm, &out->config);
374 }
375}
376
377static void register_in_stream(struct stream_in *in)
378{
379 struct audio_device *adev = in->dev;
380 if (!adev->adm_register_input_stream)
381 return;
382
383 adev->adm_register_input_stream(adev->adm_data,
384 in->capture_handle,
385 in->flags);
386
387 if (!adev->adm_set_config)
388 return;
389
390 if (in->realtime) {
391 adev->adm_set_config(adev->adm_data,
392 in->capture_handle,
393 in->pcm,
394 &in->config);
395 }
396}
397
398static void request_out_focus(struct stream_out *out, long ns)
399{
400 struct audio_device *adev = out->dev;
401
Haynes Mathew George03c40102016-01-29 17:57:48 -0800402 if (adev->adm_request_focus_v2) {
403 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
404 } else if (adev->adm_request_focus) {
405 adev->adm_request_focus(adev->adm_data, out->handle);
406 }
407}
408
409static void request_in_focus(struct stream_in *in, long ns)
410{
411 struct audio_device *adev = in->dev;
412
Haynes Mathew George03c40102016-01-29 17:57:48 -0800413 if (adev->adm_request_focus_v2) {
414 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
415 } else if (adev->adm_request_focus) {
416 adev->adm_request_focus(adev->adm_data, in->capture_handle);
417 }
418}
419
420static void release_out_focus(struct stream_out *out, long ns __unused)
421{
422 struct audio_device *adev = out->dev;
423
424 if (adev->adm_abandon_focus)
425 adev->adm_abandon_focus(adev->adm_data, out->handle);
426}
427
428static void release_in_focus(struct stream_in *in, long ns __unused)
429{
430 struct audio_device *adev = in->dev;
431 if (adev->adm_abandon_focus)
432 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
433}
434
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700435static int parse_snd_card_status(struct str_parms * parms, int * card,
436 card_status_t * status)
437{
438 char value[32]={0};
439 char state[32]={0};
440
441 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
442
443 if (ret < 0)
444 return -1;
445
446 // sscanf should be okay as value is of max length 32.
447 // same as sizeof state.
448 if (sscanf(value, "%d,%s", card, state) < 2)
449 return -1;
450
451 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
452 CARD_STATUS_OFFLINE;
453 return 0;
454}
455
vivek mehta40125092017-08-21 18:48:51 -0700456// always call with adev lock held
457void send_gain_dep_calibration_l() {
458 if (last_known_cal_step >= 0)
459 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
460}
461
vivek mehta1a9b7c02015-06-25 11:49:38 -0700462__attribute__ ((visibility ("default")))
463bool audio_hw_send_gain_dep_calibration(int level) {
464 bool ret_val = false;
465 ALOGV("%s: enter ... ", __func__);
466
467 pthread_mutex_lock(&adev_init_lock);
468
469 if (adev != NULL && adev->platform != NULL) {
470 pthread_mutex_lock(&adev->lock);
vivek mehta40125092017-08-21 18:48:51 -0700471 last_known_cal_step = level;
472 send_gain_dep_calibration_l();
vivek mehta1a9b7c02015-06-25 11:49:38 -0700473 pthread_mutex_unlock(&adev->lock);
474 } else {
475 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
476 }
477
478 pthread_mutex_unlock(&adev_init_lock);
479
480 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
481 return ret_val;
482}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700483
vivek mehtaa8d7c922016-05-25 14:40:44 -0700484__attribute__ ((visibility ("default")))
485int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
486 int table_size) {
487 int ret_val = 0;
488 ALOGV("%s: enter ... ", __func__);
489
490 pthread_mutex_lock(&adev_init_lock);
491 if (adev == NULL) {
492 ALOGW("%s: adev is NULL .... ", __func__);
493 goto done;
494 }
495
496 pthread_mutex_lock(&adev->lock);
497 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
498 pthread_mutex_unlock(&adev->lock);
499done:
500 pthread_mutex_unlock(&adev_init_lock);
501 ALOGV("%s: exit ... ", __func__);
502 return ret_val;
503}
504
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700505static bool is_supported_format(audio_format_t format)
506{
Eric Laurent8251ac82014-07-23 11:00:25 -0700507 switch (format) {
508 case AUDIO_FORMAT_MP3:
509 case AUDIO_FORMAT_AAC_LC:
510 case AUDIO_FORMAT_AAC_HE_V1:
511 case AUDIO_FORMAT_AAC_HE_V2:
512 return true;
513 default:
514 break;
515 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700516 return false;
517}
518
Haynes Mathew George03c40102016-01-29 17:57:48 -0800519static inline bool is_mmap_usecase(audio_usecase_t uc_id)
520{
521 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
522 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
523}
524
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700525static int get_snd_codec_id(audio_format_t format)
526{
527 int id = 0;
528
Eric Laurent8251ac82014-07-23 11:00:25 -0700529 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700530 case AUDIO_FORMAT_MP3:
531 id = SND_AUDIOCODEC_MP3;
532 break;
533 case AUDIO_FORMAT_AAC:
534 id = SND_AUDIOCODEC_AAC;
535 break;
536 default:
537 ALOGE("%s: Unsupported audio format", __func__);
538 }
539
540 return id;
541}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800542
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800543static int audio_ssr_status(struct audio_device *adev)
544{
545 int ret = 0;
546 struct mixer_ctl *ctl;
547 const char *mixer_ctl_name = "Audio SSR Status";
548
549 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
550 ret = mixer_ctl_get_value(ctl, 0);
551 ALOGD("%s: value: %d", __func__, ret);
552 return ret;
553}
554
vivek mehta4a824772017-06-08 19:05:49 -0700555static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
556{
557 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
558}
559
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800560static bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
561{
562 return out_snd_device == SND_DEVICE_OUT_BT_SCO ||
563 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
564 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
565 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
566 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
567 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC;
568
569}
570
571static bool is_a2dp_device(snd_device_t out_snd_device)
572{
573 return out_snd_device == SND_DEVICE_OUT_BT_A2DP;
574}
575
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800576int enable_audio_route(struct audio_device *adev,
577 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800578{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700579 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800580 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800581
582 if (usecase == NULL)
583 return -EINVAL;
584
585 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
586
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800587 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700588 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800589 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700590 snd_device = usecase->out_snd_device;
Yamit Mehtae3b99562016-09-16 22:44:00 +0530591 audio_extn_utils_send_app_type_cfg(adev, usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800592 audio_extn_utils_send_audio_calibration(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800593 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500594 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000595 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700596 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700597 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800598
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800599 ALOGV("%s: exit", __func__);
600 return 0;
601}
602
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800603int disable_audio_route(struct audio_device *adev,
604 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800605{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700606 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800607 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800608
609 if (usecase == NULL)
610 return -EINVAL;
611
612 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700613 if (usecase->type == PCM_CAPTURE)
614 snd_device = usecase->in_snd_device;
615 else
616 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800617 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500618 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700619 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700620 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000621 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800622
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800623 ALOGV("%s: exit", __func__);
624 return 0;
625}
626
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800627int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700628 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800629{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700630 int i, num_devices = 0;
631 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800632 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800633 if (snd_device < SND_DEVICE_MIN ||
634 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800635 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800636 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800637 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700638
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700639 platform_send_audio_calibration(adev->platform, snd_device);
640
vivek mehtade4849c2016-03-03 17:23:38 -0800641 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700642 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700643 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800644 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700645 }
646
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700647 /* due to the possibility of calibration overwrite between listen
648 and audio, notify sound trigger hal before audio calibration is sent */
649 audio_extn_sound_trigger_update_device_status(snd_device,
650 ST_EVENT_SND_DEVICE_BUSY);
651
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700652 if (audio_extn_spkr_prot_is_enabled())
653 audio_extn_spkr_prot_calib_cancel(adev);
654
zhaoyang yin4211fad2015-06-04 21:13:25 +0800655 audio_extn_dsm_feedback_enable(adev, snd_device, true);
656
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800657 if (is_a2dp_device(snd_device) &&
658 (audio_extn_a2dp_start_playback() < 0)) {
659 ALOGE("%s: failed to configure A2DP control path", __func__);
660 goto on_error;
661 }
662
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700663 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800664 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700665 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
666 audio_extn_spkr_prot_is_enabled()) {
Aniket Kumar Lata9d6679a2018-04-11 18:13:23 -0700667 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800668 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700669 }
670 if (audio_extn_spkr_prot_start_processing(snd_device)) {
671 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800672 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700673 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700674 } else if (platform_can_split_snd_device(snd_device,
675 &num_devices,
676 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700677 for (i = 0; i < num_devices; i++) {
678 enable_snd_device(adev, new_snd_devices[i]);
679 }
vivek mehtab6506412015-08-07 16:55:17 -0700680 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700681 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800682 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
683 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
684 ALOGE(" %s: Invalid sound device returned", __func__);
685 goto on_error;
686 }
Ed Tam70b5c142016-03-21 19:14:29 -0700687
Eric Laurent2e140aa2016-06-30 17:14:46 -0700688 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800689 audio_route_apply_and_update_path(adev->audio_route, device_name);
690 }
691on_success:
692 adev->snd_dev_ref_cnt[snd_device]++;
693 ret_val = 0;
694on_error:
695 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800696}
697
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800698int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700699 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800700{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700701 int i, num_devices = 0;
702 snd_device_t new_snd_devices[2];
703
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800704 if (snd_device < SND_DEVICE_MIN ||
705 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800706 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800707 return -EINVAL;
708 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700709 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
710 ALOGE("%s: device ref cnt is already 0", __func__);
711 return -EINVAL;
712 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800713 audio_extn_tfa_98xx_disable_speaker(snd_device);
714
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700715 adev->snd_dev_ref_cnt[snd_device]--;
716 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800717 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800718
719 if (is_a2dp_device(snd_device))
720 audio_extn_a2dp_stop_playback();
721
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700722 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800723 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700724 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700725 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
726 audio_extn_spkr_prot_is_enabled()) {
727 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700728
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700729 // FIXME b/65363602: bullhead is the only Nexus with audio_extn_spkr_prot_is_enabled()
730 // and does not use speaker swap. As this code causes a problem with device enable ref
731 // counting we remove it for now.
vivek mehtae59cfb22017-06-16 15:57:11 -0700732 // when speaker device is disabled, reset swap.
733 // will be renabled on usecase start
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700734 // platform_set_swap_channels(adev, false);
vivek mehtae59cfb22017-06-16 15:57:11 -0700735
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700736 } else if (platform_can_split_snd_device(snd_device,
737 &num_devices,
738 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700739 for (i = 0; i < num_devices; i++) {
740 disable_snd_device(adev, new_snd_devices[i]);
741 }
vivek mehtab6506412015-08-07 16:55:17 -0700742 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700743 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800744 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
745 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
746 ALOGE(" %s: Invalid sound device returned", __func__);
747 return -EINVAL;
748 }
749
Eric Laurent2e140aa2016-06-30 17:14:46 -0700750 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800751 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700752 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700753 audio_extn_sound_trigger_update_device_status(snd_device,
754 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700755 }
vivek mehtab6506412015-08-07 16:55:17 -0700756
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800757 return 0;
758}
759
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700760/*
761 legend:
762 uc - existing usecase
763 new_uc - new usecase
764 d1, d11, d2 - SND_DEVICE enums
765 a1, a2 - corresponding ANDROID device enums
766 B, B1, B2 - backend strings
767
768case 1
769 uc->dev d1 (a1) B1
770 new_uc->dev d1 (a1), d2 (a2) B1, B2
771
772 resolution: disable and enable uc->dev on d1
773
774case 2
775 uc->dev d1 (a1) B1
776 new_uc->dev d11 (a1) B1
777
778 resolution: need to switch uc since d1 and d11 are related
779 (e.g. speaker and voice-speaker)
780 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
781
782case 3
783 uc->dev d1 (a1) B1
784 new_uc->dev d2 (a2) B2
785
786 resolution: no need to switch uc
787
788case 4
789 uc->dev d1 (a1) B
790 new_uc->dev d2 (a2) B
791
792 resolution: disable enable uc-dev on d2 since backends match
793 we cannot enable two streams on two different devices if they
794 share the same backend. e.g. if offload is on speaker device using
795 QUAD_MI2S backend and a low-latency stream is started on voice-handset
796 using the same backend, offload must also be switched to voice-handset.
797
798case 5
799 uc->dev d1 (a1) B
800 new_uc->dev d1 (a1), d2 (a2) B
801
802 resolution: disable enable uc-dev on d2 since backends match
803 we cannot enable two streams on two different devices if they
804 share the same backend.
805
806case 6
807 uc->dev d1 a1 B1
808 new_uc->dev d2 a1 B2
809
810 resolution: no need to switch
811
812case 7
813
814 uc->dev d1 (a1), d2 (a2) B1, B2
815 new_uc->dev d1 B1
816
817 resolution: no need to switch
818
819*/
820static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
821 struct audio_usecase *new_uc,
822 snd_device_t new_snd_device)
823{
824 audio_devices_t a1 = uc->stream.out->devices;
825 audio_devices_t a2 = new_uc->stream.out->devices;
826
827 snd_device_t d1 = uc->out_snd_device;
828 snd_device_t d2 = new_snd_device;
829
830 // Treat as a special case when a1 and a2 are not disjoint
831 if ((a1 != a2) && (a1 & a2)) {
832 snd_device_t d3[2];
833 int num_devices = 0;
834 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
835 &num_devices,
836 d3);
837 if (ret < 0) {
838 if (ret != -ENOSYS) {
839 ALOGW("%s failed to split snd_device %d",
840 __func__,
841 popcount(a1) > 1 ? d1 : d2);
842 }
843 goto end;
844 }
845
846 // NB: case 7 is hypothetical and isn't a practical usecase yet.
847 // But if it does happen, we need to give priority to d2 if
848 // the combo devices active on the existing usecase share a backend.
849 // This is because we cannot have a usecase active on a combo device
850 // and a new usecase requests one device in this combo pair.
851 if (platform_check_backends_match(d3[0], d3[1])) {
852 return d2; // case 5
853 } else {
854 return d1; // case 1
855 }
856 } else {
857 if (platform_check_backends_match(d1, d2)) {
858 return d2; // case 2, 4
859 } else {
860 return d1; // case 6, 3
861 }
862 }
863
864end:
865 return d2; // return whatever was calculated before.
866}
867
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700868static void check_and_route_playback_usecases(struct audio_device *adev,
869 struct audio_usecase *uc_info,
870 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700871{
872 struct listnode *node;
873 struct audio_usecase *usecase;
874 bool switch_device[AUDIO_USECASE_MAX];
875 int i, num_uc_to_switch = 0;
876
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700877 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
878 uc_info,
879 snd_device);
David Linee3fe402017-03-13 10:00:42 -0700880
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800881 /* For a2dp device reconfigure all active sessions
882 * with new AFE encoder format based on a2dp state
883 */
884 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
885 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
886 audio_extn_a2dp_is_force_device_switch()) {
887 force_routing = true;
888 }
889
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700890 /*
891 * This function is to make sure that all the usecases that are active on
892 * the hardware codec backend are always routed to any one device that is
893 * handled by the hardware codec.
894 * For example, if low-latency and deep-buffer usecases are currently active
895 * on speaker and out_set_parameters(headset) is received on low-latency
896 * output, then we have to make sure deep-buffer is also switched to headset,
897 * because of the limitation that both the devices cannot be enabled
898 * at the same time as they share the same backend.
899 */
900 /* Disable all the usecases on the shared backend other than the
901 specified usecase */
902 for (i = 0; i < AUDIO_USECASE_MAX; i++)
903 switch_device[i] = false;
904
905 list_for_each(node, &adev->usecase_list) {
906 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700907 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
908 continue;
909
910 if (force_routing ||
911 (usecase->out_snd_device != snd_device &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -0700912 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
913 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700914 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700915 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
916 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700917 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700918 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700919 switch_device[usecase->id] = true;
920 num_uc_to_switch++;
921 }
922 }
923
924 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700925 list_for_each(node, &adev->usecase_list) {
926 usecase = node_to_item(node, struct audio_usecase, list);
927 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700928 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900929 }
930 }
931
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700932 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900933 list_for_each(node, &adev->usecase_list) {
934 usecase = node_to_item(node, struct audio_usecase, list);
935 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700936 d_device = derive_playback_snd_device(usecase, uc_info,
937 snd_device);
938 enable_snd_device(adev, d_device);
939 /* Update the out_snd_device before enabling the audio route */
940 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700941 }
942 }
943
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700944 /* Re-route all the usecases on the shared backend other than the
945 specified usecase to new snd devices */
946 list_for_each(node, &adev->usecase_list) {
947 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700948 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700949 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700950 }
951 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700952 }
953}
954
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700955static void check_and_route_capture_usecases(struct audio_device *adev,
956 struct audio_usecase *uc_info,
957 snd_device_t snd_device)
958{
959 struct listnode *node;
960 struct audio_usecase *usecase;
961 bool switch_device[AUDIO_USECASE_MAX];
962 int i, num_uc_to_switch = 0;
963
vivek mehta4ed66e62016-04-15 23:33:34 -0700964 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
965
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700966 /*
967 * This function is to make sure that all the active capture usecases
968 * are always routed to the same input sound device.
969 * For example, if audio-record and voice-call usecases are currently
970 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
971 * is received for voice call then we have to make sure that audio-record
972 * usecase is also switched to earpiece i.e. voice-dmic-ef,
973 * because of the limitation that two devices cannot be enabled
974 * at the same time if they share the same backend.
975 */
976 for (i = 0; i < AUDIO_USECASE_MAX; i++)
977 switch_device[i] = false;
978
979 list_for_each(node, &adev->usecase_list) {
980 usecase = node_to_item(node, struct audio_usecase, list);
981 if (usecase->type != PCM_PLAYBACK &&
982 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700983 usecase->in_snd_device != snd_device &&
984 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700985 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
986 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700987 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700988 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700989 switch_device[usecase->id] = true;
990 num_uc_to_switch++;
991 }
992 }
993
994 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700995 list_for_each(node, &adev->usecase_list) {
996 usecase = node_to_item(node, struct audio_usecase, list);
997 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700998 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700999 }
1000 }
1001
1002 list_for_each(node, &adev->usecase_list) {
1003 usecase = node_to_item(node, struct audio_usecase, list);
1004 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001005 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001006 }
1007 }
1008
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001009 /* Re-route all the usecases on the shared backend other than the
1010 specified usecase to new snd devices */
1011 list_for_each(node, &adev->usecase_list) {
1012 usecase = node_to_item(node, struct audio_usecase, list);
1013 /* Update the in_snd_device only before enabling the audio route */
1014 if (switch_device[usecase->id] ) {
1015 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001016 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001017 }
1018 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001019 }
1020}
1021
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001022/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001023static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001024{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001025 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001026 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001027
1028 switch (channels) {
1029 /*
1030 * Do not handle stereo output in Multi-channel cases
1031 * Stereo case is handled in normal playback path
1032 */
1033 case 6:
1034 ALOGV("%s: HDMI supports 5.1", __func__);
1035 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1036 break;
1037 case 8:
1038 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
1039 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1040 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
1041 break;
1042 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001043 ALOGE("HDMI does not support multi channel playback");
1044 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001045 break;
1046 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001047 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001048}
1049
Andy Hung18859412017-08-09 11:47:21 -07001050static ssize_t read_usb_sup_sample_rates(bool is_playback,
1051 uint32_t *supported_sample_rates,
1052 uint32_t max_rates)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001053{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001054 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1055 supported_sample_rates,
1056 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001057#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001058 for (ssize_t i=0; i<count; i++) {
1059 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1060 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001061 }
1062#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001063 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001064}
1065
Haynes Mathew George569b7482017-05-08 14:44:27 -07001066static int read_usb_sup_channel_masks(bool is_playback,
1067 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001068 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001069{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001070 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001071 int channel_count;
1072 uint32_t num_masks = 0;
1073 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1074 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001075 }
Eric Laurent74b55762017-07-09 17:04:53 -07001076 if (is_playback) {
Andy Hung6c1afb12017-12-22 11:34:41 -08001077 // start from 2 channels as framework currently doesn't support mono.
1078 // TODO: consider only supporting channel index masks beyond stereo here.
1079 for (channel_count = FCC_2;
1080 channel_count <= channels && num_masks < max_masks;
1081 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001082 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1083 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001084 for (channel_count = FCC_2;
1085 channel_count <= channels && num_masks < max_masks;
1086 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001087 supported_channel_masks[num_masks++] =
1088 audio_channel_mask_for_index_assignment_from_count(channel_count);
1089 }
1090 } else {
1091 // For capture we report all supported channel masks from 1 channel up.
1092 channel_count = MIN_CHANNEL_COUNT;
1093 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1094 // indexed mask
1095 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1096 supported_channel_masks[num_masks++] =
1097 audio_channel_in_mask_from_count(channel_count);
1098 }
1099 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001100#ifdef NDEBUG
1101 for (size_t i = 0; i < num_masks; ++i) {
1102 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1103 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
1104 }
1105#endif
Eric Laurent74b55762017-07-09 17:04:53 -07001106 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001107}
1108
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001109static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001110 audio_format_t *supported_formats,
1111 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001112{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001113 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001114 switch (bitwidth) {
1115 case 24:
1116 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001117 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001118 break;
1119 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001120 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001121 break;
1122 case 16:
1123 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001124 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001125 break;
1126 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001127 ALOGV("%s: %s supported format %d", __func__,
1128 is_playback ? "P" : "C", bitwidth);
1129 return 1;
1130}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001131
Haynes Mathew George569b7482017-05-08 14:44:27 -07001132static int read_usb_sup_params_and_compare(bool is_playback,
1133 audio_format_t *format,
1134 audio_format_t *supported_formats,
1135 uint32_t max_formats,
1136 audio_channel_mask_t *mask,
1137 audio_channel_mask_t *supported_channel_masks,
1138 uint32_t max_masks,
1139 uint32_t *rate,
1140 uint32_t *supported_sample_rates,
1141 uint32_t max_rates) {
1142 int ret = 0;
1143 int num_formats;
1144 int num_masks;
1145 int num_rates;
1146 int i;
1147
1148 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1149 max_formats);
1150 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1151 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001152
Haynes Mathew George569b7482017-05-08 14:44:27 -07001153 num_rates = read_usb_sup_sample_rates(is_playback,
1154 supported_sample_rates, max_rates);
1155
1156#define LUT(table, len, what, dflt) \
1157 for (i=0; i<len && (table[i] != what); i++); \
1158 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1159
1160 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1161 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1162 LUT(supported_sample_rates, num_rates, *rate, 0);
1163
1164#undef LUT
1165 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001166}
1167
Andy Hungd9653bd2017-08-01 19:31:39 -07001168static bool is_usb_ready(struct audio_device *adev, bool is_playback)
1169{
1170 // Check if usb is ready.
1171 // The usb device may have been removed quickly after insertion and hence
1172 // no longer available. This will show up as empty channel masks, or rates.
1173
1174 pthread_mutex_lock(&adev->lock);
1175 uint32_t supported_sample_rate;
1176
1177 // we consider usb ready if we can fetch at least one sample rate.
1178 const bool ready = read_usb_sup_sample_rates(
1179 is_playback, &supported_sample_rate, 1 /* max_rates */) > 0;
1180 pthread_mutex_unlock(&adev->lock);
1181 return ready;
1182}
1183
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001184static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1185{
1186 struct audio_usecase *usecase;
1187 struct listnode *node;
1188
1189 list_for_each(node, &adev->usecase_list) {
1190 usecase = node_to_item(node, struct audio_usecase, list);
1191 if (usecase->type == VOICE_CALL) {
1192 ALOGV("%s: usecase id %d", __func__, usecase->id);
1193 return usecase->id;
1194 }
1195 }
1196 return USECASE_INVALID;
1197}
1198
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001199struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1200 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001201{
1202 struct audio_usecase *usecase;
1203 struct listnode *node;
1204
1205 list_for_each(node, &adev->usecase_list) {
1206 usecase = node_to_item(node, struct audio_usecase, list);
1207 if (usecase->id == uc_id)
1208 return usecase;
1209 }
1210 return NULL;
1211}
1212
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001213static bool force_device_switch(struct audio_usecase *usecase)
1214{
1215 if (usecase->stream.out == NULL) {
1216 ALOGE("%s: stream.out is NULL", __func__);
1217 return false;
1218 }
1219
1220 // Force all A2DP output devices to reconfigure for proper AFE encode format
1221 // Also handle a case where in earlier A2DP start failed as A2DP stream was
1222 // in suspended state, hence try to trigger a retry when we again get a routing request.
1223 if ((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
1224 audio_extn_a2dp_is_force_device_switch()) {
1225 ALOGD("%s: Force A2DP device switch to update new encoder config", __func__);
1226 return true;
1227 }
1228
1229 return false;
1230}
1231
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001232int select_devices(struct audio_device *adev,
1233 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001234{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001235 snd_device_t out_snd_device = SND_DEVICE_NONE;
1236 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001237 struct audio_usecase *usecase = NULL;
1238 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001239 struct audio_usecase *hfp_usecase = NULL;
1240 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001241 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001242 int status = 0;
Eric Laurentf4520b02017-09-20 18:31:58 -07001243 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1244 USECASE_AUDIO_PLAYBACK_VOIP);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001245
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001246 usecase = get_usecase_from_list(adev, uc_id);
1247 if (usecase == NULL) {
1248 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1249 return -EINVAL;
1250 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001251
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001252 if ((usecase->type == VOICE_CALL) ||
1253 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001254 out_snd_device = platform_get_output_snd_device(adev->platform,
1255 usecase->stream.out->devices);
1256 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001257 usecase->devices = usecase->stream.out->devices;
1258 } else {
1259 /*
1260 * If the voice call is active, use the sound devices of voice call usecase
1261 * so that it would not result any device switch. All the usecases will
1262 * be switched to new device when select_devices() is called for voice call
1263 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001264 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001265 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001266 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001267 vc_usecase = get_usecase_from_list(adev,
1268 get_voice_usecase_id_from_list(adev));
1269 if ((vc_usecase != NULL) &&
1270 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1271 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001272 in_snd_device = vc_usecase->in_snd_device;
1273 out_snd_device = vc_usecase->out_snd_device;
1274 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001275 } else if (audio_extn_hfp_is_active(adev)) {
1276 hfp_ucid = audio_extn_hfp_get_usecase();
1277 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1278 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1279 in_snd_device = hfp_usecase->in_snd_device;
1280 out_snd_device = hfp_usecase->out_snd_device;
1281 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001282 }
1283 if (usecase->type == PCM_PLAYBACK) {
1284 usecase->devices = usecase->stream.out->devices;
1285 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001286 if (out_snd_device == SND_DEVICE_NONE) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001287 struct stream_out *voip_out = adev->primary_output;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001288
Eric Laurentb23d5282013-05-14 15:27:20 -07001289 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001290 usecase->stream.out->devices);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001291
1292 if (voip_usecase)
1293 voip_out = voip_usecase->stream.out;
1294
1295 if (usecase->stream.out == voip_out &&
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001296 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001297 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001298 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001299 select_devices(adev, adev->active_input->usecase);
1300 }
1301 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001302 } else if (usecase->type == PCM_CAPTURE) {
1303 usecase->devices = usecase->stream.in->device;
1304 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001305 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001306 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001307 if (adev->active_input &&
1308 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1309 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001310
1311 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1312 USECASE_AUDIO_PLAYBACK_VOIP);
1313
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001314 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001315 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1316 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001317 } else if (voip_usecase) {
1318 out_device = voip_usecase->stream.out->devices;
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001319 } else if (adev->primary_output) {
1320 out_device = adev->primary_output->devices;
1321 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001322 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001323 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001324 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001325 }
1326 }
1327
1328 if (out_snd_device == usecase->out_snd_device &&
1329 in_snd_device == usecase->in_snd_device) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001330 if (!force_device_switch(usecase))
1331 return 0;
1332 }
1333
1334 if (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready()) {
1335 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1336 return 0;
1337 }
1338
1339 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP) &&
1340 (!audio_extn_a2dp_is_ready())) {
1341 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
1342 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001343 }
1344
Eric Laurent2bafff12016-03-17 12:17:23 -07001345 if (out_snd_device != SND_DEVICE_NONE &&
1346 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1347 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1348 __func__,
1349 use_case_table[uc_id],
1350 adev->last_logged_snd_device[uc_id][0],
1351 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1352 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1353 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1354 -1,
1355 out_snd_device,
1356 platform_get_snd_device_name(out_snd_device),
1357 platform_get_snd_device_acdb_id(out_snd_device));
1358 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1359 }
1360 if (in_snd_device != SND_DEVICE_NONE &&
1361 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1362 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1363 __func__,
1364 use_case_table[uc_id],
1365 adev->last_logged_snd_device[uc_id][1],
1366 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1367 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1368 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1369 -1,
1370 in_snd_device,
1371 platform_get_snd_device_name(in_snd_device),
1372 platform_get_snd_device_acdb_id(in_snd_device));
1373 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1374 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001375
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001376 /*
1377 * Limitation: While in call, to do a device switch we need to disable
1378 * and enable both RX and TX devices though one of them is same as current
1379 * device.
1380 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001381 if ((usecase->type == VOICE_CALL) &&
1382 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1383 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001384 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001385 /* Disable sidetone only if voice call already exists */
1386 if (voice_is_call_state_active(adev))
1387 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001388 }
1389
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001390 /* Disable current sound devices */
1391 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001392 disable_audio_route(adev, usecase);
1393 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001394 }
1395
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001396 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001397 disable_audio_route(adev, usecase);
1398 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001399 }
1400
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001401 /* Applicable only on the targets that has external modem.
1402 * New device information should be sent to modem before enabling
1403 * the devices to reduce in-call device switch time.
1404 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001405 if ((usecase->type == VOICE_CALL) &&
1406 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1407 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001408 status = platform_switch_voice_call_enable_device_config(adev->platform,
1409 out_snd_device,
1410 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001411 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001412
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001413 /* Enable new sound devices */
1414 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001415 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001416 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) ||
1417 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001418 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001419 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001420 }
1421
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001422 if (in_snd_device != SND_DEVICE_NONE) {
1423 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001424 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001425 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001426
Eric Laurentb23d5282013-05-14 15:27:20 -07001427 if (usecase->type == VOICE_CALL)
1428 status = platform_switch_voice_call_device_post(adev->platform,
1429 out_snd_device,
1430 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001431
sangwoo170731f2013-06-08 15:36:36 +09001432 usecase->in_snd_device = in_snd_device;
1433 usecase->out_snd_device = out_snd_device;
1434
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001435 audio_extn_tfa_98xx_set_mode();
1436
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001437 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001438
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001439 /* Applicable only on the targets that has external modem.
1440 * Enable device command should be sent to modem only after
1441 * enabling voice call mixer controls
1442 */
vivek mehta765eb642015-08-07 19:46:06 -07001443 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001444 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1445 out_snd_device,
1446 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001447 /* Enable sidetone only if voice call already exists */
1448 if (voice_is_call_state_active(adev))
1449 voice_set_sidetone(adev, out_snd_device, true);
1450 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001451
Eric Laurentf4520b02017-09-20 18:31:58 -07001452 if (usecase == voip_usecase) {
1453 struct stream_out *voip_out = voip_usecase->stream.out;
1454 audio_extn_utils_send_app_type_gain(adev,
1455 voip_out->app_type_cfg.app_type,
1456 &voip_out->app_type_cfg.gain[0]);
1457 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001458 return status;
1459}
1460
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001461static int stop_input_stream(struct stream_in *in)
1462{
1463 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001464 struct audio_usecase *uc_info;
1465 struct audio_device *adev = in->dev;
1466
Eric Laurent994a6932013-07-17 11:51:42 -07001467 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001468 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001469
1470 if (adev->active_input) {
1471 if (adev->active_input->usecase == in->usecase) {
1472 adev->active_input = NULL;
1473 } else {
1474 ALOGW("%s adev->active_input->usecase %s, v/s in->usecase %s",
1475 __func__,
1476 use_case_table[adev->active_input->usecase],
1477 use_case_table[in->usecase]);
1478 }
1479 }
1480
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001481 uc_info = get_usecase_from_list(adev, in->usecase);
1482 if (uc_info == NULL) {
1483 ALOGE("%s: Could not find the usecase (%d) in the list",
1484 __func__, in->usecase);
1485 return -EINVAL;
1486 }
1487
vivek mehta781065c2017-04-04 12:55:01 -07001488 /* Close in-call recording streams */
1489 voice_check_and_stop_incall_rec_usecase(adev, in);
1490
Eric Laurent150dbfe2013-02-27 14:31:02 -08001491 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001492 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001493
1494 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001495 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001496
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001497 list_remove(&uc_info->list);
1498 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001499
Eric Laurent994a6932013-07-17 11:51:42 -07001500 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001501 return ret;
1502}
1503
1504int start_input_stream(struct stream_in *in)
1505{
1506 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001507 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001508 struct audio_usecase *uc_info;
1509 struct audio_device *adev = in->dev;
1510
Eric Laurent994a6932013-07-17 11:51:42 -07001511 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001512
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001513 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1514 return -EIO;
1515
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001516 if (in->card_status == CARD_STATUS_OFFLINE ||
1517 adev->card_status == CARD_STATUS_OFFLINE) {
1518 ALOGW("in->card_status or adev->card_status offline, try again");
1519 ret = -EAGAIN;
1520 goto error_config;
1521 }
1522
vivek mehta781065c2017-04-04 12:55:01 -07001523 /* Check if source matches incall recording usecase criteria */
1524 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1525 if (ret)
1526 goto error_config;
1527 else
1528 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1529
Eric Laurentb23d5282013-05-14 15:27:20 -07001530 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001531 if (in->pcm_device_id < 0) {
1532 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1533 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001534 ret = -EINVAL;
1535 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001536 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001537
1538 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001539 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1540 uc_info->id = in->usecase;
1541 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001542 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001543 uc_info->devices = in->device;
1544 uc_info->in_snd_device = SND_DEVICE_NONE;
1545 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001546
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001547 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001548
Wei Wangf4837d52017-11-21 14:51:20 -08001549 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001550 audio_extn_perf_lock_acquire();
1551
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001552 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001553
Eric Laurent0e46adf2016-12-16 12:49:24 -08001554 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001555 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001556 ALOGE("%s: pcm stream not ready", __func__);
1557 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001558 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001559 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001560 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001561 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1562 goto error_open;
1563 }
1564 } else {
1565 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1566 unsigned int pcm_open_retry_count = 0;
1567
1568 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1569 flags |= PCM_MMAP | PCM_NOIRQ;
1570 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1571 } else if (in->realtime) {
1572 flags |= PCM_MMAP | PCM_NOIRQ;
1573 }
1574
1575 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1576 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1577
1578 while (1) {
1579 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1580 flags, &in->config);
1581 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1582 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1583 if (in->pcm != NULL) {
1584 pcm_close(in->pcm);
1585 in->pcm = NULL;
1586 }
1587 if (pcm_open_retry_count-- == 0) {
1588 ret = -EIO;
1589 goto error_open;
1590 }
1591 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1592 continue;
1593 }
1594 break;
1595 }
1596
1597 ALOGV("%s: pcm_prepare", __func__);
1598 ret = pcm_prepare(in->pcm);
1599 if (ret < 0) {
1600 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001601 pcm_close(in->pcm);
1602 in->pcm = NULL;
1603 goto error_open;
1604 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001605 if (in->realtime) {
1606 ret = pcm_start(in->pcm);
1607 if (ret < 0) {
1608 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1609 pcm_close(in->pcm);
1610 in->pcm = NULL;
1611 goto error_open;
1612 }
1613 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001614 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001615 register_in_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001616 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001617 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001618 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001619
Eric Laurent0e46adf2016-12-16 12:49:24 -08001620 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001621
1622error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001623 stop_input_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001624 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001625 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001626
1627error_config:
1628 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001629 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001630 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001631}
1632
Eric Laurenta1478072015-09-21 17:21:52 -07001633void lock_input_stream(struct stream_in *in)
1634{
1635 pthread_mutex_lock(&in->pre_lock);
1636 pthread_mutex_lock(&in->lock);
1637 pthread_mutex_unlock(&in->pre_lock);
1638}
1639
1640void lock_output_stream(struct stream_out *out)
1641{
1642 pthread_mutex_lock(&out->pre_lock);
1643 pthread_mutex_lock(&out->lock);
1644 pthread_mutex_unlock(&out->pre_lock);
1645}
1646
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001647/* must be called with out->lock locked */
1648static int send_offload_cmd_l(struct stream_out* out, int command)
1649{
1650 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1651
1652 ALOGVV("%s %d", __func__, command);
1653
1654 cmd->cmd = command;
1655 list_add_tail(&out->offload_cmd_list, &cmd->node);
1656 pthread_cond_signal(&out->offload_cond);
1657 return 0;
1658}
1659
1660/* must be called iwth out->lock locked */
1661static void stop_compressed_output_l(struct stream_out *out)
1662{
1663 out->offload_state = OFFLOAD_STATE_IDLE;
1664 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001665 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001666 if (out->compr != NULL) {
1667 compress_stop(out->compr);
1668 while (out->offload_thread_blocked) {
1669 pthread_cond_wait(&out->cond, &out->lock);
1670 }
1671 }
1672}
1673
1674static void *offload_thread_loop(void *context)
1675{
1676 struct stream_out *out = (struct stream_out *) context;
1677 struct listnode *item;
1678
1679 out->offload_state = OFFLOAD_STATE_IDLE;
1680 out->playback_started = 0;
1681
1682 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1683 set_sched_policy(0, SP_FOREGROUND);
1684 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1685
1686 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001687 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001688 for (;;) {
1689 struct offload_cmd *cmd = NULL;
1690 stream_callback_event_t event;
1691 bool send_callback = false;
1692
1693 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1694 __func__, list_empty(&out->offload_cmd_list),
1695 out->offload_state);
1696 if (list_empty(&out->offload_cmd_list)) {
1697 ALOGV("%s SLEEPING", __func__);
1698 pthread_cond_wait(&out->offload_cond, &out->lock);
1699 ALOGV("%s RUNNING", __func__);
1700 continue;
1701 }
1702
1703 item = list_head(&out->offload_cmd_list);
1704 cmd = node_to_item(item, struct offload_cmd, node);
1705 list_remove(item);
1706
1707 ALOGVV("%s STATE %d CMD %d out->compr %p",
1708 __func__, out->offload_state, cmd->cmd, out->compr);
1709
1710 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1711 free(cmd);
1712 break;
1713 }
1714
1715 if (out->compr == NULL) {
1716 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001717 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001718 pthread_cond_signal(&out->cond);
1719 continue;
1720 }
1721 out->offload_thread_blocked = true;
1722 pthread_mutex_unlock(&out->lock);
1723 send_callback = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001724 switch (cmd->cmd) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001725 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1726 compress_wait(out->compr, -1);
1727 send_callback = true;
1728 event = STREAM_CBK_EVENT_WRITE_READY;
1729 break;
1730 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001731 compress_next_track(out->compr);
1732 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001733 send_callback = true;
1734 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001735 /* Resend the metadata for next iteration */
1736 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001737 break;
1738 case OFFLOAD_CMD_DRAIN:
1739 compress_drain(out->compr);
1740 send_callback = true;
1741 event = STREAM_CBK_EVENT_DRAIN_READY;
1742 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001743 case OFFLOAD_CMD_ERROR:
1744 send_callback = true;
1745 event = STREAM_CBK_EVENT_ERROR;
1746 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001747 default:
1748 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1749 break;
1750 }
Eric Laurenta1478072015-09-21 17:21:52 -07001751 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001752 out->offload_thread_blocked = false;
1753 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001754 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001755 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001756 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001757 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001758 free(cmd);
1759 }
1760
1761 pthread_cond_signal(&out->cond);
1762 while (!list_empty(&out->offload_cmd_list)) {
1763 item = list_head(&out->offload_cmd_list);
1764 list_remove(item);
1765 free(node_to_item(item, struct offload_cmd, node));
1766 }
1767 pthread_mutex_unlock(&out->lock);
1768
1769 return NULL;
1770}
1771
1772static int create_offload_callback_thread(struct stream_out *out)
1773{
1774 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1775 list_init(&out->offload_cmd_list);
1776 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1777 offload_thread_loop, out);
1778 return 0;
1779}
1780
1781static int destroy_offload_callback_thread(struct stream_out *out)
1782{
Eric Laurenta1478072015-09-21 17:21:52 -07001783 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001784 stop_compressed_output_l(out);
1785 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1786
1787 pthread_mutex_unlock(&out->lock);
1788 pthread_join(out->offload_thread, (void **) NULL);
1789 pthread_cond_destroy(&out->offload_cond);
1790
1791 return 0;
1792}
1793
Eric Laurent07eeafd2013-10-06 12:52:49 -07001794static bool allow_hdmi_channel_config(struct audio_device *adev)
1795{
1796 struct listnode *node;
1797 struct audio_usecase *usecase;
1798 bool ret = true;
1799
1800 list_for_each(node, &adev->usecase_list) {
1801 usecase = node_to_item(node, struct audio_usecase, list);
1802 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1803 /*
1804 * If voice call is already existing, do not proceed further to avoid
1805 * disabling/enabling both RX and TX devices, CSD calls, etc.
1806 * Once the voice call done, the HDMI channels can be configured to
1807 * max channels of remaining use cases.
1808 */
1809 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001810 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001811 __func__);
1812 ret = false;
1813 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001814 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1815 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001816 "no change in HDMI channels", __func__);
1817 ret = false;
1818 break;
1819 }
1820 }
1821 }
1822 return ret;
1823}
1824
1825static int check_and_set_hdmi_channels(struct audio_device *adev,
1826 unsigned int channels)
1827{
1828 struct listnode *node;
1829 struct audio_usecase *usecase;
1830
1831 /* Check if change in HDMI channel config is allowed */
1832 if (!allow_hdmi_channel_config(adev))
1833 return 0;
1834
1835 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001836 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001837 return 0;
1838 }
1839
1840 platform_set_hdmi_channels(adev->platform, channels);
1841 adev->cur_hdmi_channels = channels;
1842
1843 /*
1844 * Deroute all the playback streams routed to HDMI so that
1845 * the back end is deactivated. Note that backend will not
1846 * be deactivated if any one stream is connected to it.
1847 */
1848 list_for_each(node, &adev->usecase_list) {
1849 usecase = node_to_item(node, struct audio_usecase, list);
1850 if (usecase->type == PCM_PLAYBACK &&
1851 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001852 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001853 }
1854 }
1855
1856 /*
1857 * Enable all the streams disabled above. Now the HDMI backend
1858 * will be activated with new channel configuration
1859 */
1860 list_for_each(node, &adev->usecase_list) {
1861 usecase = node_to_item(node, struct audio_usecase, list);
1862 if (usecase->type == PCM_PLAYBACK &&
1863 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001864 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001865 }
1866 }
1867
1868 return 0;
1869}
1870
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001871static int stop_output_stream(struct stream_out *out)
1872{
1873 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001874 struct audio_usecase *uc_info;
1875 struct audio_device *adev = out->dev;
1876
Eric Laurent994a6932013-07-17 11:51:42 -07001877 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001878 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001879 uc_info = get_usecase_from_list(adev, out->usecase);
1880 if (uc_info == NULL) {
1881 ALOGE("%s: Could not find the usecase (%d) in the list",
1882 __func__, out->usecase);
1883 return -EINVAL;
1884 }
1885
Haynes Mathew George41f86652014-06-17 14:22:15 -07001886 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1887 if (adev->visualizer_stop_output != NULL)
1888 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1889 if (adev->offload_effects_stop_output != NULL)
1890 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08001891 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
1892 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
1893 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07001894 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001895
Eric Laurent150dbfe2013-02-27 14:31:02 -08001896 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001897 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001898
1899 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001900 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001901
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001902 list_remove(&uc_info->list);
1903 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001904
Eric Laurent0499d4f2014-08-25 22:39:29 -05001905 audio_extn_extspk_update(adev->extspk);
1906
Eric Laurent07eeafd2013-10-06 12:52:49 -07001907 /* Must be called after removing the usecase from list */
1908 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1909 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07001910 else if (out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
1911 struct listnode *node;
1912 struct audio_usecase *usecase;
1913 list_for_each(node, &adev->usecase_list) {
1914 usecase = node_to_item(node, struct audio_usecase, list);
1915 if (usecase->devices & AUDIO_DEVICE_OUT_SPEAKER)
1916 select_devices(adev, usecase->id);
1917 }
1918 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001919
Eric Laurent994a6932013-07-17 11:51:42 -07001920 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001921 return ret;
1922}
1923
1924int start_output_stream(struct stream_out *out)
1925{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001926 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001927 struct audio_usecase *uc_info;
1928 struct audio_device *adev = out->dev;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001929 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001930
Eric Laurent994a6932013-07-17 11:51:42 -07001931 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001932 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001933
1934 if (out->card_status == CARD_STATUS_OFFLINE ||
1935 adev->card_status == CARD_STATUS_OFFLINE) {
1936 ALOGW("out->card_status or adev->card_status offline, try again");
1937 ret = -EAGAIN;
1938 goto error_config;
1939 }
1940
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001941 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
1942 if (!audio_extn_a2dp_is_ready()) {
1943 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
1944 a2dp_combo = true;
1945 } else {
1946 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
1947 ALOGE("%s: A2DP profile is not ready, return error", __func__);
1948 ret = -EAGAIN;
1949 goto error_config;
1950 }
1951 }
1952 }
1953 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001954 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001955 if (out->pcm_device_id < 0) {
1956 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1957 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001958 ret = -EINVAL;
1959 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001960 }
1961
1962 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1963 uc_info->id = out->usecase;
1964 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001965 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001966 uc_info->devices = out->devices;
1967 uc_info->in_snd_device = SND_DEVICE_NONE;
1968 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001969
Eric Laurent07eeafd2013-10-06 12:52:49 -07001970 /* This must be called before adding this usecase to the list */
1971 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1972 check_and_set_hdmi_channels(adev, out->config.channels);
1973
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001974 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001975
Wei Wangf4837d52017-11-21 14:51:20 -08001976 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001977 audio_extn_perf_lock_acquire();
1978
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001979 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
1980 (!audio_extn_a2dp_is_ready())) {
1981 if (!a2dp_combo) {
1982 check_a2dp_restore_l(adev, out, false);
1983 } else {
1984 audio_devices_t dev = out->devices;
1985 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
1986 select_devices(adev, out->usecase);
1987 out->devices = dev;
1988 }
1989 } else {
1990 select_devices(adev, out->usecase);
1991 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001992
Eric Laurent0499d4f2014-08-25 22:39:29 -05001993 audio_extn_extspk_update(adev->extspk);
1994
Andy Hung31aca912014-03-20 17:14:59 -07001995 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001996 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001997 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1998 out->pcm = NULL;
1999 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
2000 COMPRESS_IN, &out->compr_config);
2001 if (out->compr && !is_compress_ready(out->compr)) {
2002 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2003 compress_close(out->compr);
2004 out->compr = NULL;
2005 ret = -EIO;
2006 goto error_open;
2007 }
2008 if (out->offload_callback)
2009 compress_nonblock(out->compr, out->non_blocking);
2010
2011 if (adev->visualizer_start_output != NULL)
2012 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2013 if (adev->offload_effects_start_output != NULL)
2014 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
2015 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002016 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002017 ALOGE("%s: pcm stream not ready", __func__);
2018 goto error_open;
2019 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002020 ret = pcm_start(out->pcm);
2021 if (ret < 0) {
2022 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2023 goto error_open;
2024 }
2025 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07002026 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002027 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002028
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002029 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2030 flags |= PCM_MMAP | PCM_NOIRQ;
2031 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002032 } else if (out->realtime) {
2033 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07002034 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002035
2036 while (1) {
2037 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2038 flags, &out->config);
2039 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2040 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2041 if (out->pcm != NULL) {
2042 pcm_close(out->pcm);
2043 out->pcm = NULL;
2044 }
2045 if (pcm_open_retry_count-- == 0) {
2046 ret = -EIO;
2047 goto error_open;
2048 }
2049 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2050 continue;
2051 }
2052 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002053 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002054 ALOGV("%s: pcm_prepare", __func__);
2055 if (pcm_is_ready(out->pcm)) {
2056 ret = pcm_prepare(out->pcm);
2057 if (ret < 0) {
2058 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2059 pcm_close(out->pcm);
2060 out->pcm = NULL;
2061 goto error_open;
2062 }
2063 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002064 if (out->realtime) {
2065 ret = pcm_start(out->pcm);
2066 if (ret < 0) {
2067 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
2068 pcm_close(out->pcm);
2069 out->pcm = NULL;
2070 goto error_open;
2071 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002072 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002073 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002074 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08002075 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002076 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002077 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07002078
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002079 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2080 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2081 audio_low_latency_hint_start();
2082 }
2083
vivek mehtae59cfb22017-06-16 15:57:11 -07002084 // consider a scenario where on pause lower layers are tear down.
2085 // so on resume, swap mixer control need to be sent only when
2086 // backend is active, hence rather than sending from enable device
2087 // sending it from start of streamtream
2088
2089 platform_set_swap_channels(adev, true);
2090
Eric Laurent994a6932013-07-17 11:51:42 -07002091 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002092 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002093error_open:
Wei Wangf4837d52017-11-21 14:51:20 -08002094 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002095 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002096 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002097error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002098 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002099}
2100
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002101static int check_input_parameters(uint32_t sample_rate,
2102 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07002103 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002104{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002105 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2106 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002107 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2108 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002109 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2110 return -EINVAL;
2111 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002112
Eric Laurent74b55762017-07-09 17:04:53 -07002113 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2114 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002115 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002116 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002117 return -EINVAL;
2118 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002119
2120 switch (sample_rate) {
2121 case 8000:
2122 case 11025:
2123 case 12000:
2124 case 16000:
2125 case 22050:
2126 case 24000:
2127 case 32000:
2128 case 44100:
2129 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002130 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002131 break;
2132 default:
vivek mehtadae44712015-07-27 14:13:18 -07002133 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002134 return -EINVAL;
2135 }
2136
2137 return 0;
2138}
2139
Kevin Rocarda325aa22018-04-03 09:15:52 -07002140/** Add a value in a list if not already present.
2141 * @return true if value was successfully inserted or already present,
2142 * false if the list is full and does not contain the value.
2143 */
2144static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
2145 for (size_t i = 0; i < list_length; i++) {
2146 if (list[i] == value) return true; // value is already present
2147 if (list[i] == 0) { // no values in this slot
2148 list[i] = value;
2149 return true; // value inserted
2150 }
2151 }
2152 return false; // could not insert value
2153}
2154
2155/** Add channel_mask in supported_channel_masks if not already present.
2156 * @return true if channel_mask was successfully inserted or already present,
2157 * false if supported_channel_masks is full and does not contain channel_mask.
2158 */
2159static void register_channel_mask(audio_channel_mask_t channel_mask,
2160 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
2161 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
2162 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
2163}
2164
2165/** Add format in supported_formats if not already present.
2166 * @return true if format was successfully inserted or already present,
2167 * false if supported_formats is full and does not contain format.
2168 */
2169static void register_format(audio_format_t format,
2170 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
2171 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
2172 "%s: stream can not declare supporting its format %x", __func__, format);
2173}
2174/** Add sample_rate in supported_sample_rates if not already present.
2175 * @return true if sample_rate was successfully inserted or already present,
2176 * false if supported_sample_rates is full and does not contain sample_rate.
2177 */
2178static void register_sample_rate(uint32_t sample_rate,
2179 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
2180 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
2181 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
2182}
2183
vivek mehtaa68fea62017-06-08 19:04:02 -07002184static size_t get_stream_buffer_size(size_t duration_ms,
2185 uint32_t sample_rate,
2186 audio_format_t format,
2187 int channel_count,
2188 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002189{
2190 size_t size = 0;
2191
vivek mehtaa68fea62017-06-08 19:04:02 -07002192 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002193 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002194 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002195
2196 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002197
Glenn Kasten4f993392014-05-14 07:30:48 -07002198 /* make sure the size is multiple of 32 bytes
2199 * At 48 kHz mono 16-bit PCM:
2200 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2201 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2202 */
2203 size += 0x1f;
2204 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002205
2206 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002207}
2208
2209static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2210{
2211 struct stream_out *out = (struct stream_out *)stream;
2212
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002213 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002214}
2215
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002216static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002217{
2218 return -ENOSYS;
2219}
2220
2221static size_t out_get_buffer_size(const struct audio_stream *stream)
2222{
2223 struct stream_out *out = (struct stream_out *)stream;
2224
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002225 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2226 return out->compr_config.fragment_size;
2227 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002228 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002229 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002230}
2231
2232static uint32_t out_get_channels(const struct audio_stream *stream)
2233{
2234 struct stream_out *out = (struct stream_out *)stream;
2235
2236 return out->channel_mask;
2237}
2238
2239static audio_format_t out_get_format(const struct audio_stream *stream)
2240{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002241 struct stream_out *out = (struct stream_out *)stream;
2242
2243 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002244}
2245
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002246static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002247{
2248 return -ENOSYS;
2249}
2250
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002251/* must be called with out->lock locked */
2252static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002253{
2254 struct stream_out *out = (struct stream_out *)stream;
2255 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002256 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002257
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002258 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002259 if (adev->adm_deregister_stream)
2260 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002261 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002262 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002263 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2264 if (out->pcm) {
2265 pcm_close(out->pcm);
2266 out->pcm = NULL;
2267 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002268 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002269 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002270 out->playback_started = false;
2271 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002272 } else {
2273 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002274 out->gapless_mdata.encoder_delay = 0;
2275 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002276 if (out->compr != NULL) {
2277 compress_close(out->compr);
2278 out->compr = NULL;
2279 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002280 }
Phil Burkbc991042017-02-24 08:06:44 -08002281 if (do_stop) {
2282 stop_output_stream(out);
2283 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002284 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002285 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002286 return 0;
2287}
2288
2289static int out_standby(struct audio_stream *stream)
2290{
2291 struct stream_out *out = (struct stream_out *)stream;
2292
2293 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2294 out->usecase, use_case_table[out->usecase]);
2295
2296 lock_output_stream(out);
2297 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002298 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002299 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002300 return 0;
2301}
2302
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002303static int out_on_error(struct audio_stream *stream)
2304{
2305 struct stream_out *out = (struct stream_out *)stream;
2306 struct audio_device *adev = out->dev;
2307 bool do_standby = false;
2308
2309 lock_output_stream(out);
2310 if (!out->standby) {
2311 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2312 stop_compressed_output_l(out);
2313 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2314 } else
2315 do_standby = true;
2316 }
2317 pthread_mutex_unlock(&out->lock);
2318
2319 if (do_standby)
2320 return out_standby(&out->stream.common);
2321
2322 return 0;
2323}
2324
Andy Hung7401c7c2016-09-21 12:41:21 -07002325static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002326{
Andy Hung7401c7c2016-09-21 12:41:21 -07002327 struct stream_out *out = (struct stream_out *)stream;
2328
2329 // We try to get the lock for consistency,
2330 // but it isn't necessary for these variables.
2331 // If we're not in standby, we may be blocked on a write.
2332 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2333 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2334 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2335
2336 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002337 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002338 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002339
2340 // dump error info
2341 (void)error_log_dump(
2342 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002343
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002344 return 0;
2345}
2346
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002347static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2348{
2349 int ret = 0;
2350 char value[32];
2351 struct compr_gapless_mdata tmp_mdata;
2352
2353 if (!out || !parms) {
2354 return -EINVAL;
2355 }
2356
2357 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2358 if (ret >= 0) {
2359 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2360 } else {
2361 return -EINVAL;
2362 }
2363
2364 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2365 if (ret >= 0) {
2366 tmp_mdata.encoder_padding = atoi(value);
2367 } else {
2368 return -EINVAL;
2369 }
2370
2371 out->gapless_mdata = tmp_mdata;
2372 out->send_new_metadata = 1;
2373 ALOGV("%s new encoder delay %u and padding %u", __func__,
2374 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2375
2376 return 0;
2377}
2378
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002379static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2380{
2381 return out == adev->primary_output || out == adev->voice_tx_output;
2382}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002383
Kevin Rocard1e02c882017-08-09 15:26:07 -07002384static int get_alive_usb_card(struct str_parms* parms) {
2385 int card;
2386 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2387 !audio_extn_usb_alive(card)) {
2388 return card;
2389 }
2390 return -ENODEV;
2391}
2392
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002393static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2394{
2395 struct stream_out *out = (struct stream_out *)stream;
2396 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002397 struct audio_usecase *usecase;
2398 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002399 struct str_parms *parms;
2400 char value[32];
2401 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002402 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002403 int status = 0;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002404 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002405
Eric Laurent2e140aa2016-06-30 17:14:46 -07002406 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002407 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002408 parms = str_parms_create_str(kvpairs);
2409 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2410 if (ret >= 0) {
2411 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002412
Eric Laurenta1478072015-09-21 17:21:52 -07002413 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002414
2415 // The usb driver needs to be closed after usb device disconnection
2416 // otherwise audio is no longer played on the new usb devices.
2417 // By forcing the stream in standby, the usb stack refcount drops to 0
2418 // and the driver is closed.
2419 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD && val == AUDIO_DEVICE_NONE &&
2420 audio_is_usb_out_device(out->devices)) {
2421 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2422 out_standby_l(&out->stream.common);
2423 }
2424
Eric Laurent150dbfe2013-02-27 14:31:02 -08002425 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002426
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002427 /*
2428 * When HDMI cable is unplugged the music playback is paused and
2429 * the policy manager sends routing=0. But the audioflinger
2430 * continues to write data until standby time (3sec).
2431 * As the HDMI core is turned off, the write gets blocked.
2432 * Avoid this by routing audio to speaker until standby.
2433 */
2434 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2435 val == AUDIO_DEVICE_NONE) {
2436 val = AUDIO_DEVICE_OUT_SPEAKER;
2437 }
2438
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002439 /*
2440 * When A2DP is disconnected the
2441 * music playback is paused and the policy manager sends routing=0
2442 * But the audioflingercontinues to write data until standby time
2443 * (3sec). As BT is turned off, the write gets blocked.
2444 * Avoid this by routing audio to speaker until standby.
2445 */
2446 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2447 (val == AUDIO_DEVICE_NONE) &&
2448 !audio_extn_a2dp_is_ready()) {
2449 val = AUDIO_DEVICE_OUT_SPEAKER;
2450 }
2451
2452 /* To avoid a2dp to sco overlapping / BT device improper state
2453 * check with BT lib about a2dp streaming support before routing
2454 */
2455 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2456 if (!audio_extn_a2dp_is_ready()) {
2457 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
2458 //combo usecase just by pass a2dp
2459 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2460 bypass_a2dp = true;
2461 } else {
2462 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2463 /* update device to a2dp and don't route as BT returned error
2464 * However it is still possible a2dp routing called because
2465 * of current active device disconnection (like wired headset)
2466 */
2467 out->devices = val;
2468 pthread_mutex_unlock(&out->lock);
2469 pthread_mutex_unlock(&adev->lock);
2470 status = -ENOSYS;
2471 goto routing_fail;
2472 }
2473 }
2474 }
2475
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002476 audio_devices_t new_dev = val;
2477
2478 // Workaround: If routing to an non existing usb device, fail gracefully
2479 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002480 int card;
2481 if (audio_is_usb_out_device(new_dev) &&
2482 (card = get_alive_usb_card(parms)) >= 0) {
2483
2484 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002485 pthread_mutex_unlock(&adev->lock);
2486 pthread_mutex_unlock(&out->lock);
2487 status = -ENOSYS;
2488 goto routing_fail;
2489 }
2490
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002491 /*
2492 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002493 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002494 * the select_devices(). But how do we undo this?
2495 *
2496 * For example, music playback is active on headset (deep-buffer usecase)
2497 * and if we go to ringtones and select a ringtone, low-latency usecase
2498 * will be started on headset+speaker. As we can't enable headset+speaker
2499 * and headset devices at the same time, select_devices() switches the music
2500 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2501 * So when the ringtone playback is completed, how do we undo the same?
2502 *
2503 * We are relying on the out_set_parameters() call on deep-buffer output,
2504 * once the ringtone playback is ended.
2505 * NOTE: We should not check if the current devices are same as new devices.
2506 * Because select_devices() must be called to switch back the music
2507 * playback to headset.
2508 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002509 if (new_dev != AUDIO_DEVICE_NONE) {
2510 bool same_dev = out->devices == new_dev;
2511 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002512
Eric Laurenta7657192014-10-09 21:09:33 -07002513 if (output_drives_call(adev, out)) {
2514 if (!voice_is_in_call(adev)) {
2515 if (adev->mode == AUDIO_MODE_IN_CALL) {
2516 adev->current_call_output = out;
2517 ret = voice_start_call(adev);
2518 }
2519 } else {
2520 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002521 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002522 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002523 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002524
2525 if (!out->standby) {
2526 if (!same_dev) {
2527 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002528 // inform adm before actual routing to prevent glitches.
2529 if (adev->adm_on_routing_change) {
2530 adev->adm_on_routing_change(adev->adm_data,
2531 out->handle);
2532 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002533 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002534 if (!bypass_a2dp) {
2535 select_devices(adev, out->usecase);
2536 } else {
2537 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2538 select_devices(adev, out->usecase);
2539 out->devices = new_dev;
2540 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002541 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002542
2543 // on device switch force swap, lower functions will make sure
2544 // to check if swap is allowed or not.
2545
2546 if (!same_dev)
2547 platform_set_swap_channels(adev, true);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002548
2549 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2550 out->a2dp_compress_mute &&
2551 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
2552 pthread_mutex_lock(&out->compr_mute_lock);
2553 out->a2dp_compress_mute = false;
2554 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
2555 pthread_mutex_unlock(&out->compr_mute_lock);
2556 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002557 }
2558
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002559 }
2560
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002561 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002562 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002563
2564 /*handles device and call state changes*/
2565 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002566 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002567 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002568
2569 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2570 parse_compress_metadata(out, parms);
2571 }
2572
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002573 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002574 ALOGV("%s: exit: code(%d)", __func__, status);
2575 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002576}
2577
Haynes Mathew George569b7482017-05-08 14:44:27 -07002578static bool stream_get_parameter_channels(struct str_parms *query,
2579 struct str_parms *reply,
2580 audio_channel_mask_t *supported_channel_masks) {
2581 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002582 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002583 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002584 size_t i, j;
2585
2586 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2587 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002588 value[0] = '\0';
2589 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002590 while (supported_channel_masks[i] != 0) {
2591 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2592 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002593 if (!first) {
2594 strcat(value, "|");
2595 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002596 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002597 first = false;
2598 break;
2599 }
2600 }
2601 i++;
2602 }
2603 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002604 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002605 return ret >= 0;
2606}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002607
Haynes Mathew George569b7482017-05-08 14:44:27 -07002608static bool stream_get_parameter_formats(struct str_parms *query,
2609 struct str_parms *reply,
2610 audio_format_t *supported_formats) {
2611 int ret = -1;
2612 char value[256];
2613 int i;
2614
2615 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2616 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002617 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002618 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002619 case AUDIO_FORMAT_PCM_16_BIT:
2620 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2621 break;
2622 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2623 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2624 break;
2625 case AUDIO_FORMAT_PCM_32_BIT:
2626 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2627 break;
2628 default:
2629 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002630 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002631 break;
2632 }
2633 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002634 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002635 return ret >= 0;
2636}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002637
Haynes Mathew George569b7482017-05-08 14:44:27 -07002638static bool stream_get_parameter_rates(struct str_parms *query,
2639 struct str_parms *reply,
2640 uint32_t *supported_sample_rates) {
2641
2642 int i;
2643 char value[256];
2644 int ret = -1;
2645 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2646 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002647 value[0] = '\0';
2648 i=0;
2649 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002650 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002651 int avail = sizeof(value) - cursor;
2652 ret = snprintf(value + cursor, avail, "%s%d",
2653 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002654 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002655 if (ret < 0 || ret >= avail) {
2656 // if cursor is at the last element of the array
2657 // overwrite with \0 is duplicate work as
2658 // snprintf already put a \0 in place.
2659 // else
2660 // we had space to write the '|' at value[cursor]
2661 // (which will be overwritten) or no space to fill
2662 // the first element (=> cursor == 0)
2663 value[cursor] = '\0';
2664 break;
2665 }
2666 cursor += ret;
2667 ++i;
2668 }
2669 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2670 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002671 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002672 return ret >= 0;
2673}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002674
Haynes Mathew George569b7482017-05-08 14:44:27 -07002675static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2676{
2677 struct stream_out *out = (struct stream_out *)stream;
2678 struct str_parms *query = str_parms_create_str(keys);
2679 char *str;
2680 struct str_parms *reply = str_parms_create();
2681 bool replied = false;
2682 ALOGV("%s: enter: keys - %s", __func__, keys);
2683
2684 replied |= stream_get_parameter_channels(query, reply,
2685 &out->supported_channel_masks[0]);
2686 replied |= stream_get_parameter_formats(query, reply,
2687 &out->supported_formats[0]);
2688 replied |= stream_get_parameter_rates(query, reply,
2689 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002690 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002691 str = str_parms_to_str(reply);
2692 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002693 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002694 }
2695 str_parms_destroy(query);
2696 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002697 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002698 return str;
2699}
2700
2701static uint32_t out_get_latency(const struct audio_stream_out *stream)
2702{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002703 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002704 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002705 uint32_t latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002706
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002707 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2708 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002709 else if ((out->realtime) ||
2710 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002711 // since the buffer won't be filled up faster than realtime,
2712 // return a smaller number
2713 period_ms = (out->af_period_multiplier * out->config.period_size *
2714 1000) / (out->config.rate);
2715 hw_delay = platform_render_latency(out->usecase)/1000;
2716 return period_ms + hw_delay;
2717 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002718
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002719 latency = (out->config.period_count * out->config.period_size * 1000) /
2720 (out->config.rate);
2721
2722 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
2723 latency += audio_extn_a2dp_get_encoder_latency();
2724
2725 return latency;
2726}
2727
2728static int set_compr_volume(struct audio_stream_out *stream, float left,
2729 float right)
2730{
2731 struct stream_out *out = (struct stream_out *)stream;
2732 int volume[2];
2733 char mixer_ctl_name[128];
2734 struct audio_device *adev = out->dev;
2735 struct mixer_ctl *ctl;
2736 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2737 PCM_PLAYBACK);
2738
2739 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2740 "Compress Playback %d Volume", pcm_device_id);
2741 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2742 if (!ctl) {
2743 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2744 __func__, mixer_ctl_name);
2745 return -EINVAL;
2746 }
2747 ALOGV("%s: ctl for mixer cmd - %s, left %f, right %f",
2748 __func__, mixer_ctl_name, left, right);
2749 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2750 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2751 mixer_ctl_set_array(ctl, volume, sizeof(volume) / sizeof(volume[0]));
2752
2753 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002754}
2755
2756static int out_set_volume(struct audio_stream_out *stream, float left,
2757 float right)
2758{
Eric Laurenta9024de2013-04-04 09:19:12 -07002759 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002760 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002761
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002762 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002763 /* only take left channel into account: the API is for stereo anyway */
2764 out->muted = (left == 0.0f);
2765 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002766 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002767 pthread_mutex_lock(&out->compr_mute_lock);
2768 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
2769 if (!out->a2dp_compress_mute)
2770 ret = set_compr_volume(stream, left, right);
2771 out->volume_l = left;
2772 out->volume_r = right;
2773 pthread_mutex_unlock(&out->compr_mute_lock);
2774 return ret;
vivek mehtaa68fea62017-06-08 19:04:02 -07002775 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002776 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2777 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2778 if (!out->standby) {
2779 // if in standby, cached volume will be sent after stream is opened
2780 audio_extn_utils_send_app_type_gain(out->dev,
2781 out->app_type_cfg.app_type,
2782 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002783 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002784 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002785 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002786
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002787 return -ENOSYS;
2788}
2789
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002790// note: this call is safe only if the stream_cb is
2791// removed first in close_output_stream (as is done now).
2792static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2793{
2794 if (!stream || !parms)
2795 return;
2796
2797 struct stream_out *out = (struct stream_out *)stream;
2798 struct audio_device *adev = out->dev;
2799
2800 card_status_t status;
2801 int card;
2802 if (parse_snd_card_status(parms, &card, &status) < 0)
2803 return;
2804
2805 pthread_mutex_lock(&adev->lock);
2806 bool valid_cb = (card == adev->snd_card);
2807 pthread_mutex_unlock(&adev->lock);
2808
2809 if (!valid_cb)
2810 return;
2811
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002812 lock_output_stream(out);
2813 if (out->card_status != status)
2814 out->card_status = status;
2815 pthread_mutex_unlock(&out->lock);
2816
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002817 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2818 use_case_table[out->usecase],
2819 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2820
2821 if (status == CARD_STATUS_OFFLINE)
2822 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002823
2824 return;
2825}
2826
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002827#ifdef NO_AUDIO_OUT
2828static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002829 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002830{
2831 struct stream_out *out = (struct stream_out *)stream;
2832
2833 /* No Output device supported other than BT for playback.
2834 * Sleep for the amount of buffer duration
2835 */
Eric Laurenta1478072015-09-21 17:21:52 -07002836 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002837 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2838 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002839 out_get_sample_rate(&out->stream.common));
2840 pthread_mutex_unlock(&out->lock);
2841 return bytes;
2842}
2843#endif
2844
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002845static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2846 size_t bytes)
2847{
2848 struct stream_out *out = (struct stream_out *)stream;
2849 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002850 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002851 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002852
Eric Laurenta1478072015-09-21 17:21:52 -07002853 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002854 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07002855 const size_t frame_size = audio_stream_out_frame_size(stream);
2856 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002857
Eric Laurent0e46adf2016-12-16 12:49:24 -08002858 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2859 error_code = ERROR_CODE_WRITE;
2860 goto exit;
2861 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002862
2863 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2864 (audio_extn_a2dp_is_suspended())) {
2865 if (!(out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2866 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2867 ret = -EIO;
2868 goto exit;
2869 }
2870 }
2871 }
2872
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002873 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002874 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002875 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002876 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07002877
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002878 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002879 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002880 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07002881 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002882 goto exit;
2883 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002884
vivek mehta40125092017-08-21 18:48:51 -07002885 // after standby always force set last known cal step
2886 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
2887 ALOGD("%s: retry previous failed cal level set", __func__);
2888 send_gain_dep_calibration_l();
2889 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002890 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002891
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002892 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002893 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002894 if (out->send_new_metadata) {
2895 ALOGVV("send new gapless metadata");
2896 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2897 out->send_new_metadata = 0;
2898 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002899 unsigned int avail;
2900 struct timespec tstamp;
2901 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2902 /* Do not limit write size if the available frames count is unknown */
2903 if (ret != 0) {
2904 avail = bytes;
2905 }
2906 if (avail == 0) {
2907 ret = 0;
2908 } else {
2909 if (avail > bytes) {
2910 avail = bytes;
2911 }
2912 ret = compress_write(out->compr, buffer, avail);
2913 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2914 __func__, avail, ret);
2915 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002916
Eric Laurent6e895242013-09-05 16:10:57 -07002917 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002918 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2919 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002920 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002921 compress_start(out->compr);
2922 out->playback_started = 1;
2923 out->offload_state = OFFLOAD_STATE_PLAYING;
2924 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002925 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002926 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002927 } else {
2928 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002929 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002930 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002931 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002932 return ret;
2933 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002934 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002935 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07002936 size_t bytes_to_write = bytes;
2937
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002938 if (out->muted)
2939 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07002940 // FIXME: this can be removed once audio flinger mixer supports mono output
Nadav Bar3d72cfc2018-01-07 12:19:24 +02002941 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP || out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
Eric Laurentad2dde92017-09-20 18:27:31 -07002942 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
2943 int16_t *src = (int16_t *)buffer;
2944 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002945
Eric Laurentad2dde92017-09-20 18:27:31 -07002946 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
2947 out->format != AUDIO_FORMAT_PCM_16_BIT,
2948 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002949
Eric Laurentad2dde92017-09-20 18:27:31 -07002950 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
2951 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
2952 }
2953 bytes_to_write /= 2;
2954 }
2955 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes_to_write);
2956
Glenn Kasten5a59dff2018-02-22 08:05:35 -08002957 long ns = (frames * (int64_t) NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002958 request_out_focus(out, ns);
2959
2960 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2961 if (use_mmap)
Eric Laurentad2dde92017-09-20 18:27:31 -07002962 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002963 else
Eric Laurentad2dde92017-09-20 18:27:31 -07002964 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002965
Haynes Mathew George03c40102016-01-29 17:57:48 -08002966 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002967 } else {
2968 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002969 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002970 }
2971
2972exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002973 // For PCM we always consume the buffer and return #bytes regardless of ret.
2974 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07002975 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07002976 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002977 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07002978
Andy Hung7401c7c2016-09-21 12:41:21 -07002979 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07002980 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07002981 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2982 ALOGE_IF(out->pcm != NULL,
2983 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07002984 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002985 // usleep not guaranteed for values over 1 second but we don't limit here.
2986 }
2987 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002988
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002989 pthread_mutex_unlock(&out->lock);
2990
2991 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002992 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002993 if (sleeptime_us != 0)
2994 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002995 }
2996 return bytes;
2997}
2998
2999static int out_get_render_position(const struct audio_stream_out *stream,
3000 uint32_t *dsp_frames)
3001{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003002 struct stream_out *out = (struct stream_out *)stream;
3003 *dsp_frames = 0;
3004 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07003005 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003006 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003007 unsigned long frames = 0;
3008 // TODO: check return value
3009 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
3010 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003011 ALOGVV("%s rendered frames %d sample_rate %d",
3012 __func__, *dsp_frames, out->sample_rate);
3013 }
3014 pthread_mutex_unlock(&out->lock);
3015 return 0;
3016 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003017 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003018}
3019
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003020static int out_add_audio_effect(const struct audio_stream *stream __unused,
3021 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003022{
3023 return 0;
3024}
3025
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003026static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3027 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003028{
3029 return 0;
3030}
3031
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003032static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3033 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003034{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003035 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003036}
3037
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003038static int out_get_presentation_position(const struct audio_stream_out *stream,
3039 uint64_t *frames, struct timespec *timestamp)
3040{
3041 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003042 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07003043 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003044
Eric Laurenta1478072015-09-21 17:21:52 -07003045 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003046
Eric Laurent949a0892013-09-20 09:20:13 -07003047 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3048 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003049 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07003050 compress_get_tstamp(out->compr, &dsp_frames,
3051 &out->sample_rate);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003052 // Adjustment accounts for A2DP encoder latency with offload usecases
3053 // Note: Encoder latency is returned in ms.
3054 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3055 unsigned long offset =
3056 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3057 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
3058 }
Eric Laurent949a0892013-09-20 09:20:13 -07003059 ALOGVV("%s rendered frames %ld sample_rate %d",
3060 __func__, dsp_frames, out->sample_rate);
3061 *frames = dsp_frames;
3062 ret = 0;
3063 /* this is the best we can do */
3064 clock_gettime(CLOCK_MONOTONIC, timestamp);
3065 }
3066 } else {
3067 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07003068 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003069 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3070 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003071 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003072 // This adjustment accounts for buffering after app processor.
3073 // It is based on estimated DSP latency per use case, rather than exact.
3074 signed_frames -=
3075 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3076
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003077 // Adjustment accounts for A2DP encoder latency with non-offload usecases
3078 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3079 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3080 signed_frames -=
3081 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3082 }
3083
Eric Laurent949a0892013-09-20 09:20:13 -07003084 // It would be unusual for this value to be negative, but check just in case ...
3085 if (signed_frames >= 0) {
3086 *frames = signed_frames;
3087 ret = 0;
3088 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003089 }
3090 }
3091 }
3092
3093 pthread_mutex_unlock(&out->lock);
3094
3095 return ret;
3096}
3097
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003098static int out_set_callback(struct audio_stream_out *stream,
3099 stream_callback_t callback, void *cookie)
3100{
3101 struct stream_out *out = (struct stream_out *)stream;
3102
3103 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003104 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003105 out->offload_callback = callback;
3106 out->offload_cookie = cookie;
3107 pthread_mutex_unlock(&out->lock);
3108 return 0;
3109}
3110
3111static int out_pause(struct audio_stream_out* stream)
3112{
3113 struct stream_out *out = (struct stream_out *)stream;
3114 int status = -ENOSYS;
3115 ALOGV("%s", __func__);
3116 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003117 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003118 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
3119 status = compress_pause(out->compr);
3120 out->offload_state = OFFLOAD_STATE_PAUSED;
3121 }
3122 pthread_mutex_unlock(&out->lock);
3123 }
3124 return status;
3125}
3126
3127static int out_resume(struct audio_stream_out* stream)
3128{
3129 struct stream_out *out = (struct stream_out *)stream;
3130 int status = -ENOSYS;
3131 ALOGV("%s", __func__);
3132 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3133 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07003134 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003135 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
3136 status = compress_resume(out->compr);
3137 out->offload_state = OFFLOAD_STATE_PLAYING;
3138 }
3139 pthread_mutex_unlock(&out->lock);
3140 }
3141 return status;
3142}
3143
3144static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3145{
3146 struct stream_out *out = (struct stream_out *)stream;
3147 int status = -ENOSYS;
3148 ALOGV("%s", __func__);
3149 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003150 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003151 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3152 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3153 else
3154 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3155 pthread_mutex_unlock(&out->lock);
3156 }
3157 return status;
3158}
3159
3160static int out_flush(struct audio_stream_out* stream)
3161{
3162 struct stream_out *out = (struct stream_out *)stream;
3163 ALOGV("%s", __func__);
3164 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003165 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003166 stop_compressed_output_l(out);
3167 pthread_mutex_unlock(&out->lock);
3168 return 0;
3169 }
3170 return -ENOSYS;
3171}
3172
Eric Laurent0e46adf2016-12-16 12:49:24 -08003173static int out_stop(const struct audio_stream_out* stream)
3174{
3175 struct stream_out *out = (struct stream_out *)stream;
3176 struct audio_device *adev = out->dev;
3177 int ret = -ENOSYS;
3178
3179 ALOGV("%s", __func__);
3180 pthread_mutex_lock(&adev->lock);
3181 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3182 out->playback_started && out->pcm != NULL) {
3183 pcm_stop(out->pcm);
3184 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08003185 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003186 }
3187 pthread_mutex_unlock(&adev->lock);
3188 return ret;
3189}
3190
3191static int out_start(const struct audio_stream_out* stream)
3192{
3193 struct stream_out *out = (struct stream_out *)stream;
3194 struct audio_device *adev = out->dev;
3195 int ret = -ENOSYS;
3196
3197 ALOGV("%s", __func__);
3198 pthread_mutex_lock(&adev->lock);
3199 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3200 !out->playback_started && out->pcm != NULL) {
3201 ret = start_output_stream(out);
3202 if (ret == 0) {
3203 out->playback_started = true;
3204 }
3205 }
3206 pthread_mutex_unlock(&adev->lock);
3207 return ret;
3208}
3209
Phil Burkbc991042017-02-24 08:06:44 -08003210/*
3211 * Modify config->period_count based on min_size_frames
3212 */
3213static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
3214{
3215 int periodCountRequested = (min_size_frames + config->period_size - 1)
3216 / config->period_size;
3217 int periodCount = MMAP_PERIOD_COUNT_MIN;
3218
3219 ALOGV("%s original config.period_size = %d config.period_count = %d",
3220 __func__, config->period_size, config->period_count);
3221
3222 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
3223 periodCount *= 2;
3224 }
3225 config->period_count = periodCount;
3226
3227 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
3228}
3229
Eric Laurent0e46adf2016-12-16 12:49:24 -08003230static int out_create_mmap_buffer(const struct audio_stream_out *stream,
3231 int32_t min_size_frames,
3232 struct audio_mmap_buffer_info *info)
3233{
3234 struct stream_out *out = (struct stream_out *)stream;
3235 struct audio_device *adev = out->dev;
3236 int ret = 0;
3237 unsigned int offset1;
3238 unsigned int frames1;
3239 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003240 uint32_t mmap_size;
3241 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003242
3243 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003244 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003245 pthread_mutex_lock(&adev->lock);
3246
3247 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003248 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003249 ret = -EINVAL;
3250 goto exit;
3251 }
3252 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003253 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003254 ret = -ENOSYS;
3255 goto exit;
3256 }
3257 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3258 if (out->pcm_device_id < 0) {
3259 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3260 __func__, out->pcm_device_id, out->usecase);
3261 ret = -EINVAL;
3262 goto exit;
3263 }
Phil Burkbc991042017-02-24 08:06:44 -08003264
3265 adjust_mmap_period_count(&out->config, min_size_frames);
3266
Eric Laurent0e46adf2016-12-16 12:49:24 -08003267 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3268 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3269 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3270 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3271 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3272 step = "open";
3273 ret = -ENODEV;
3274 goto exit;
3275 }
3276 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3277 if (ret < 0) {
3278 step = "begin";
3279 goto exit;
3280 }
3281 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003282 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003283 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003284 ret = platform_get_mmap_data_fd(adev->platform,
3285 out->pcm_device_id, 0 /*playback*/,
3286 &info->shared_memory_fd,
3287 &mmap_size);
3288 if (ret < 0) {
3289 // Fall back to non exclusive mode
3290 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3291 } else {
3292 if (mmap_size < buffer_size) {
3293 step = "mmap";
3294 goto exit;
3295 }
3296 // FIXME: indicate exclusive mode support by returning a negative buffer size
3297 info->buffer_size_frames *= -1;
3298 }
3299 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003300
3301 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3302 if (ret < 0) {
3303 step = "commit";
3304 goto exit;
3305 }
Phil Burkbc991042017-02-24 08:06:44 -08003306
3307 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003308 ret = 0;
3309
3310 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3311 __func__, info->shared_memory_address, info->buffer_size_frames);
3312
3313exit:
3314 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003315 if (out->pcm == NULL) {
3316 ALOGE("%s: %s - %d", __func__, step, ret);
3317 } else {
3318 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003319 pcm_close(out->pcm);
3320 out->pcm = NULL;
3321 }
3322 }
3323 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003324 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003325 return ret;
3326}
3327
3328static int out_get_mmap_position(const struct audio_stream_out *stream,
3329 struct audio_mmap_position *position)
3330{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003331 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003332 struct stream_out *out = (struct stream_out *)stream;
3333 ALOGVV("%s", __func__);
3334 if (position == NULL) {
3335 return -EINVAL;
3336 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003337 lock_output_stream(out);
3338 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3339 out->pcm == NULL) {
3340 ret = -ENOSYS;
3341 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003342 }
3343
3344 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003345 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003346 if (ret < 0) {
3347 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003348 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003349 }
Andy Hungfc044e12017-03-20 09:24:22 -07003350 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003351exit:
3352 pthread_mutex_unlock(&out->lock);
3353 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003354}
3355
3356
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003357/** audio_stream_in implementation **/
3358static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3359{
3360 struct stream_in *in = (struct stream_in *)stream;
3361
3362 return in->config.rate;
3363}
3364
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003365static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003366{
3367 return -ENOSYS;
3368}
3369
3370static size_t in_get_buffer_size(const struct audio_stream *stream)
3371{
3372 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003373 return in->config.period_size * in->af_period_multiplier *
3374 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003375}
3376
3377static uint32_t in_get_channels(const struct audio_stream *stream)
3378{
3379 struct stream_in *in = (struct stream_in *)stream;
3380
3381 return in->channel_mask;
3382}
3383
vivek mehta4ed66e62016-04-15 23:33:34 -07003384static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003385{
vivek mehta4ed66e62016-04-15 23:33:34 -07003386 struct stream_in *in = (struct stream_in *)stream;
3387 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003388}
3389
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003390static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003391{
3392 return -ENOSYS;
3393}
3394
3395static int in_standby(struct audio_stream *stream)
3396{
3397 struct stream_in *in = (struct stream_in *)stream;
3398 struct audio_device *adev = in->dev;
3399 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003400 bool do_stop = true;
3401
Eric Laurent994a6932013-07-17 11:51:42 -07003402 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003403
3404 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003405
3406 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003407 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003408 audio_extn_sound_trigger_stop_lab(in);
3409 in->standby = true;
3410 }
3411
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003412 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003413 if (adev->adm_deregister_stream)
3414 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3415
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003416 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003417 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003418 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003419 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003420 in->capture_started = false;
3421 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003422 if (in->pcm) {
3423 pcm_close(in->pcm);
3424 in->pcm = NULL;
3425 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003426 adev->enable_voicerx = false;
3427 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003428 if (do_stop) {
3429 status = stop_input_stream(in);
3430 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003431 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003432 }
3433 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003434 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003435 return status;
3436}
3437
Andy Hungd13f0d32017-06-12 13:58:37 -07003438static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003439{
Andy Hungd13f0d32017-06-12 13:58:37 -07003440 struct stream_in *in = (struct stream_in *)stream;
3441
3442 // We try to get the lock for consistency,
3443 // but it isn't necessary for these variables.
3444 // If we're not in standby, we may be blocked on a read.
3445 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3446 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3447 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3448 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3449
3450 if (locked) {
3451 pthread_mutex_unlock(&in->lock);
3452 }
3453
3454 // dump error info
3455 (void)error_log_dump(
3456 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003457 return 0;
3458}
3459
3460static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3461{
3462 struct stream_in *in = (struct stream_in *)stream;
3463 struct audio_device *adev = in->dev;
3464 struct str_parms *parms;
3465 char *str;
3466 char value[32];
3467 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003468 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003469
Eric Laurent994a6932013-07-17 11:51:42 -07003470 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003471 parms = str_parms_create_str(kvpairs);
3472
3473 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3474
Eric Laurenta1478072015-09-21 17:21:52 -07003475 lock_input_stream(in);
3476
Eric Laurent150dbfe2013-02-27 14:31:02 -08003477 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003478 if (ret >= 0) {
3479 val = atoi(value);
3480 /* no audio source uses val == 0 */
3481 if ((in->source != val) && (val != 0)) {
3482 in->source = val;
3483 }
3484 }
3485
3486 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003487
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003488 if (ret >= 0) {
3489 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003490 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003491
3492 // Workaround: If routing to an non existing usb device, fail gracefully
3493 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003494 int card;
3495 if (audio_is_usb_in_device(val) &&
3496 (card = get_alive_usb_card(parms)) >= 0) {
3497
3498 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003499 status = -ENOSYS;
3500 } else {
3501
3502 in->device = val;
3503 /* If recording is in progress, change the tx device to new device */
3504 if (!in->standby) {
3505 ALOGV("update input routing change");
3506 // inform adm before actual routing to prevent glitches.
3507 if (adev->adm_on_routing_change) {
3508 adev->adm_on_routing_change(adev->adm_data,
3509 in->capture_handle);
3510 }
3511 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003512 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003513 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003514 }
3515 }
3516
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003517 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003518 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003519
3520 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003521 ALOGV("%s: exit: status(%d)", __func__, status);
3522 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003523}
3524
Haynes Mathew George569b7482017-05-08 14:44:27 -07003525static char* in_get_parameters(const struct audio_stream *stream,
3526 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003527{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003528 struct stream_in *in = (struct stream_in *)stream;
3529 struct str_parms *query = str_parms_create_str(keys);
3530 char *str;
3531 struct str_parms *reply = str_parms_create();
3532 bool replied = false;
3533
3534 ALOGV("%s: enter: keys - %s", __func__, keys);
3535 replied |= stream_get_parameter_channels(query, reply,
3536 &in->supported_channel_masks[0]);
3537 replied |= stream_get_parameter_formats(query, reply,
3538 &in->supported_formats[0]);
3539 replied |= stream_get_parameter_rates(query, reply,
3540 &in->supported_sample_rates[0]);
3541 if (replied) {
3542 str = str_parms_to_str(reply);
3543 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003544 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003545 }
3546 str_parms_destroy(query);
3547 str_parms_destroy(reply);
3548 ALOGV("%s: exit: returns - %s", __func__, str);
3549 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003550}
3551
Eric Laurent51f3c662018-04-10 18:21:34 -07003552static int in_set_gain(struct audio_stream_in *stream, float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003553{
Eric Laurent51f3c662018-04-10 18:21:34 -07003554 struct stream_in *in = (struct stream_in *)stream;
3555 char mixer_ctl_name[128];
3556 struct mixer_ctl *ctl;
3557 int ctl_value;
3558
3559 ALOGV("%s: gain %f", __func__, gain);
3560
3561 if (stream == NULL)
3562 return -EINVAL;
3563
3564 /* in_set_gain() only used to silence MMAP capture for now */
3565 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
3566 return -ENOSYS;
3567
3568 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
3569
3570 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
3571 if (!ctl) {
3572 ALOGW("%s: Could not get ctl for mixer cmd - %s",
3573 __func__, mixer_ctl_name);
3574 return -ENOSYS;
3575 }
3576
3577 if (gain < RECORD_GAIN_MIN)
3578 gain = RECORD_GAIN_MIN;
3579 else if (gain > RECORD_GAIN_MAX)
3580 gain = RECORD_GAIN_MAX;
3581 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
3582
3583 mixer_ctl_set_value(ctl, 0, ctl_value);
3584 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003585}
3586
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003587static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3588{
3589 if (!stream || !parms)
3590 return;
3591
3592 struct stream_in *in = (struct stream_in *)stream;
3593 struct audio_device *adev = in->dev;
3594
3595 card_status_t status;
3596 int card;
3597 if (parse_snd_card_status(parms, &card, &status) < 0)
3598 return;
3599
3600 pthread_mutex_lock(&adev->lock);
3601 bool valid_cb = (card == adev->snd_card);
3602 pthread_mutex_unlock(&adev->lock);
3603
3604 if (!valid_cb)
3605 return;
3606
3607 lock_input_stream(in);
3608 if (in->card_status != status)
3609 in->card_status = status;
3610 pthread_mutex_unlock(&in->lock);
3611
3612 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3613 use_case_table[in->usecase],
3614 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3615
3616 // a better solution would be to report error back to AF and let
3617 // it put the stream to standby
3618 if (status == CARD_STATUS_OFFLINE)
3619 in_standby(&in->stream.common);
3620
3621 return;
3622}
3623
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003624static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3625 size_t bytes)
3626{
3627 struct stream_in *in = (struct stream_in *)stream;
3628 struct audio_device *adev = in->dev;
3629 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003630 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003631 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003632
Eric Laurenta1478072015-09-21 17:21:52 -07003633 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003634 const size_t frame_size = audio_stream_in_frame_size(stream);
3635 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003636
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003637 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003638 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003639 /* Read from sound trigger HAL */
3640 audio_extn_sound_trigger_read(in, buffer, bytes);
3641 pthread_mutex_unlock(&in->lock);
3642 return bytes;
3643 }
3644
Eric Laurent0e46adf2016-12-16 12:49:24 -08003645 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3646 ret = -ENOSYS;
3647 goto exit;
3648 }
3649
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003650 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003651 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003652 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003653 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003654 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003655 goto exit;
3656 }
3657 in->standby = 0;
3658 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003659
Andy Hungd13f0d32017-06-12 13:58:37 -07003660 // errors that occur here are read errors.
3661 error_code = ERROR_CODE_READ;
3662
Haynes Mathew George03c40102016-01-29 17:57:48 -08003663 //what's the duration requested by the client?
3664 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3665 in->config.rate;
3666 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003667
Haynes Mathew George03c40102016-01-29 17:57:48 -08003668 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003669 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003670 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003671 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003672 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003673 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003674 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003675 if (ret < 0) {
3676 ALOGE("Failed to read w/err %s", strerror(errno));
3677 ret = -errno;
3678 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003679 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3680 if (bytes % 4 == 0) {
3681 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3682 int_buf_stream = buffer;
3683 for (size_t itt=0; itt < bytes/4 ; itt++) {
3684 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003685 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003686 } else {
3687 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3688 ret = -EINVAL;
3689 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003690 }
3691 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003692 }
3693
Haynes Mathew George03c40102016-01-29 17:57:48 -08003694 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003695
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003696 /*
3697 * Instead of writing zeroes here, we could trust the hardware
3698 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003699 * 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 -08003700 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08003701 if (ret == 0 && adev->mic_muted &&
3702 !voice_is_in_call_rec_stream(in) &&
3703 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003704 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07003705 in->frames_muted += frames;
3706 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003707
3708exit:
3709 pthread_mutex_unlock(&in->lock);
3710
3711 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07003712 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003713 in_standby(&in->stream.common);
3714 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003715 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003716 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07003717 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08003718 }
3719 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003720 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003721 }
3722 return bytes;
3723}
3724
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003725static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003726{
3727 return 0;
3728}
3729
Andy Hung6ebe5962016-01-15 17:46:57 -08003730static int in_get_capture_position(const struct audio_stream_in *stream,
3731 int64_t *frames, int64_t *time)
3732{
3733 if (stream == NULL || frames == NULL || time == NULL) {
3734 return -EINVAL;
3735 }
3736 struct stream_in *in = (struct stream_in *)stream;
3737 int ret = -ENOSYS;
3738
3739 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003740 // note: ST sessions do not close the alsa pcm driver synchronously
3741 // on standby. Therefore, we may return an error even though the
3742 // pcm stream is still opened.
3743 if (in->standby) {
3744 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
3745 "%s stream in standby but pcm not NULL for non ST session", __func__);
3746 goto exit;
3747 }
Andy Hung6ebe5962016-01-15 17:46:57 -08003748 if (in->pcm) {
3749 struct timespec timestamp;
3750 unsigned int avail;
3751 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3752 *frames = in->frames_read + avail;
3753 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3754 ret = 0;
3755 }
3756 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003757exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08003758 pthread_mutex_unlock(&in->lock);
3759 return ret;
3760}
3761
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003762static int add_remove_audio_effect(const struct audio_stream *stream,
3763 effect_handle_t effect,
3764 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003765{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003766 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003767 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003768 int status = 0;
3769 effect_descriptor_t desc;
3770
3771 status = (*effect)->get_descriptor(effect, &desc);
3772 if (status != 0)
3773 return status;
3774
Eric Laurenta1478072015-09-21 17:21:52 -07003775 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003776 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003777 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003778 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003779 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003780 in->enable_aec != enable &&
3781 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3782 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003783 if (!enable)
3784 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003785 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3786 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3787 adev->enable_voicerx = enable;
3788 struct audio_usecase *usecase;
3789 struct listnode *node;
3790 list_for_each(node, &adev->usecase_list) {
3791 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07003792 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07003793 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05003794 }
3795 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003796 if (!in->standby)
3797 select_devices(in->dev, in->usecase);
3798 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003799 if (in->enable_ns != enable &&
3800 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3801 in->enable_ns = enable;
3802 if (!in->standby)
3803 select_devices(in->dev, in->usecase);
3804 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003805 pthread_mutex_unlock(&in->dev->lock);
3806 pthread_mutex_unlock(&in->lock);
3807
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003808 return 0;
3809}
3810
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003811static int in_add_audio_effect(const struct audio_stream *stream,
3812 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003813{
Eric Laurent994a6932013-07-17 11:51:42 -07003814 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003815 return add_remove_audio_effect(stream, effect, true);
3816}
3817
3818static int in_remove_audio_effect(const struct audio_stream *stream,
3819 effect_handle_t effect)
3820{
Eric Laurent994a6932013-07-17 11:51:42 -07003821 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003822 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003823}
3824
Eric Laurent0e46adf2016-12-16 12:49:24 -08003825static int in_stop(const struct audio_stream_in* stream)
3826{
3827 struct stream_in *in = (struct stream_in *)stream;
3828 struct audio_device *adev = in->dev;
3829
3830 int ret = -ENOSYS;
3831 ALOGV("%s", __func__);
3832 pthread_mutex_lock(&adev->lock);
3833 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3834 in->capture_started && in->pcm != NULL) {
3835 pcm_stop(in->pcm);
3836 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003837 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003838 }
3839 pthread_mutex_unlock(&adev->lock);
3840 return ret;
3841}
3842
3843static int in_start(const struct audio_stream_in* stream)
3844{
3845 struct stream_in *in = (struct stream_in *)stream;
3846 struct audio_device *adev = in->dev;
3847 int ret = -ENOSYS;
3848
3849 ALOGV("%s in %p", __func__, in);
3850 pthread_mutex_lock(&adev->lock);
3851 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3852 !in->capture_started && in->pcm != NULL) {
3853 if (!in->capture_started) {
3854 ret = start_input_stream(in);
3855 if (ret == 0) {
3856 in->capture_started = true;
3857 }
3858 }
3859 }
3860 pthread_mutex_unlock(&adev->lock);
3861 return ret;
3862}
3863
3864static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3865 int32_t min_size_frames,
3866 struct audio_mmap_buffer_info *info)
3867{
3868 struct stream_in *in = (struct stream_in *)stream;
3869 struct audio_device *adev = in->dev;
3870 int ret = 0;
3871 unsigned int offset1;
3872 unsigned int frames1;
3873 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003874 uint32_t mmap_size;
3875 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003876
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003877 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003878 pthread_mutex_lock(&adev->lock);
3879 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003880
Eric Laurent0e46adf2016-12-16 12:49:24 -08003881 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003882 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003883 ret = -EINVAL;
3884 goto exit;
3885 }
3886 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003887 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003888 ALOGV("%s in %p", __func__, in);
3889 ret = -ENOSYS;
3890 goto exit;
3891 }
3892 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3893 if (in->pcm_device_id < 0) {
3894 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3895 __func__, in->pcm_device_id, in->usecase);
3896 ret = -EINVAL;
3897 goto exit;
3898 }
Phil Burkbc991042017-02-24 08:06:44 -08003899
3900 adjust_mmap_period_count(&in->config, min_size_frames);
3901
Eric Laurent0e46adf2016-12-16 12:49:24 -08003902 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3903 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3904 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3905 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3906 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3907 step = "open";
3908 ret = -ENODEV;
3909 goto exit;
3910 }
3911
3912 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3913 if (ret < 0) {
3914 step = "begin";
3915 goto exit;
3916 }
3917 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003918 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003919 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003920 ret = platform_get_mmap_data_fd(adev->platform,
3921 in->pcm_device_id, 1 /*capture*/,
3922 &info->shared_memory_fd,
3923 &mmap_size);
3924 if (ret < 0) {
3925 // Fall back to non exclusive mode
3926 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3927 } else {
3928 if (mmap_size < buffer_size) {
3929 step = "mmap";
3930 goto exit;
3931 }
3932 // FIXME: indicate exclusive mode support by returning a negative buffer size
3933 info->buffer_size_frames *= -1;
3934 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08003935
Haynes Mathew George96483a22017-03-28 14:52:47 -07003936 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003937
3938 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3939 if (ret < 0) {
3940 step = "commit";
3941 goto exit;
3942 }
3943
Phil Burkbc991042017-02-24 08:06:44 -08003944 in->standby = false;
3945 ret = 0;
3946
Eric Laurent0e46adf2016-12-16 12:49:24 -08003947 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3948 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003949
3950exit:
3951 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003952 if (in->pcm == NULL) {
3953 ALOGE("%s: %s - %d", __func__, step, ret);
3954 } else {
3955 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003956 pcm_close(in->pcm);
3957 in->pcm = NULL;
3958 }
3959 }
3960 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003961 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003962 return ret;
3963}
3964
3965static int in_get_mmap_position(const struct audio_stream_in *stream,
3966 struct audio_mmap_position *position)
3967{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003968 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003969 struct stream_in *in = (struct stream_in *)stream;
3970 ALOGVV("%s", __func__);
3971 if (position == NULL) {
3972 return -EINVAL;
3973 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003974 lock_input_stream(in);
3975 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
3976 in->pcm == NULL) {
3977 ret = -ENOSYS;
3978 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003979 }
3980 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003981 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003982 if (ret < 0) {
3983 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003984 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003985 }
Andy Hungfc044e12017-03-20 09:24:22 -07003986 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003987exit:
3988 pthread_mutex_unlock(&in->lock);
3989 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003990}
3991
jiabin8962a4d2018-03-19 18:21:24 -07003992static int in_get_active_microphones(const struct audio_stream_in *stream,
3993 struct audio_microphone_characteristic_t *mic_array,
3994 size_t *mic_count) {
3995 struct stream_in *in = (struct stream_in *)stream;
3996 struct audio_device *adev = in->dev;
3997 ALOGVV("%s", __func__);
3998
3999 lock_input_stream(in);
4000 pthread_mutex_lock(&adev->lock);
4001 int ret = platform_get_active_microphones(adev->platform, in->device,
4002 audio_channel_count_from_in_mask(in->channel_mask),
4003 in->source, in->usecase, mic_array, mic_count);
4004 pthread_mutex_unlock(&adev->lock);
4005 pthread_mutex_unlock(&in->lock);
4006
4007 return ret;
4008}
4009
4010static int adev_get_microphones(const struct audio_hw_device *dev,
4011 struct audio_microphone_characteristic_t *mic_array,
4012 size_t *mic_count) {
4013 struct audio_device *adev = (struct audio_device *)dev;
4014 ALOGVV("%s", __func__);
4015
4016 pthread_mutex_lock(&adev->lock);
4017 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
4018 pthread_mutex_unlock(&adev->lock);
4019
4020 return ret;
4021}
Eric Laurent0e46adf2016-12-16 12:49:24 -08004022
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004023static int adev_open_output_stream(struct audio_hw_device *dev,
4024 audio_io_handle_t handle,
4025 audio_devices_t devices,
4026 audio_output_flags_t flags,
4027 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07004028 struct audio_stream_out **stream_out,
4029 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004030{
4031 struct audio_device *adev = (struct audio_device *)dev;
4032 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004033 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004034 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
4035 bool is_usb_dev = audio_is_usb_out_device(devices) &&
4036 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004037
Andy Hungd9653bd2017-08-01 19:31:39 -07004038 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
4039 return -ENOSYS;
4040 }
4041
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004042 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
4043 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004044 *stream_out = NULL;
4045 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4046
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004047 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
4048
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004049 if (devices == AUDIO_DEVICE_NONE)
4050 devices = AUDIO_DEVICE_OUT_SPEAKER;
4051
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004052 out->flags = flags;
4053 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004054 out->dev = adev;
Eric Laurentc4aef752013-09-12 17:45:53 -07004055 out->handle = handle;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004056 out->a2dp_compress_mute = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004057
4058 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004059 if ((is_hdmi || is_usb_dev) &&
4060 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
4061 (flags == AUDIO_OUTPUT_FLAG_NONE ||
4062 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Eric Laurentab805ee2018-03-30 12:20:38 -07004063 audio_format_t req_format = config->format;
4064 audio_channel_mask_t req_channel_mask = config->channel_mask;
4065 uint32_t req_sample_rate = config->sample_rate;
4066
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004067 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004068 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004069 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004070 if (config->sample_rate == 0)
4071 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Eric Laurentab805ee2018-03-30 12:20:38 -07004072 if (config->channel_mask == AUDIO_CHANNEL_NONE)
Haynes Mathew George569b7482017-05-08 14:44:27 -07004073 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
4074 if (config->format == AUDIO_FORMAT_DEFAULT)
4075 config->format = AUDIO_FORMAT_PCM_16_BIT;
4076 } else if (is_usb_dev) {
4077 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
4078 &config->format,
4079 &out->supported_formats[0],
4080 MAX_SUPPORTED_FORMATS,
4081 &config->channel_mask,
4082 &out->supported_channel_masks[0],
4083 MAX_SUPPORTED_CHANNEL_MASKS,
4084 &config->sample_rate,
4085 &out->supported_sample_rates[0],
4086 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004087 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004088 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004089 pthread_mutex_unlock(&adev->lock);
Eric Laurentab805ee2018-03-30 12:20:38 -07004090 if (ret != 0) {
4091 // For MMAP NO IRQ, allow conversions in ADSP
4092 if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
4093 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004094
Eric Laurentab805ee2018-03-30 12:20:38 -07004095 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
4096 config->sample_rate = req_sample_rate;
4097 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
4098 config->channel_mask = req_channel_mask;
4099 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
4100 config->format = req_format;
4101 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004102
Haynes Mathew George569b7482017-05-08 14:44:27 -07004103 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004104 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004105 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004106 if (is_hdmi) {
4107 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4108 out->config = pcm_config_hdmi_multi;
4109 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
4110 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4111 out->config = pcm_config_mmap_playback;
4112 out->stream.start = out_start;
4113 out->stream.stop = out_stop;
4114 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4115 out->stream.get_mmap_position = out_get_mmap_position;
4116 } else {
4117 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4118 out->config = pcm_config_hifi;
4119 }
4120
4121 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004122 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004123 if (is_hdmi) {
4124 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
4125 audio_bytes_per_sample(out->format));
4126 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004127 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004128 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07004129 pthread_mutex_lock(&adev->lock);
4130 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4131 pthread_mutex_unlock(&adev->lock);
4132
4133 // reject offload during card offline to allow
4134 // fallback to s/w paths
4135 if (offline) {
4136 ret = -ENODEV;
4137 goto error_open;
4138 }
4139
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004140 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4141 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4142 ALOGE("%s: Unsupported Offload information", __func__);
4143 ret = -EINVAL;
4144 goto error_open;
4145 }
4146 if (!is_supported_format(config->offload_info.format)) {
4147 ALOGE("%s: Unsupported audio format", __func__);
4148 ret = -EINVAL;
4149 goto error_open;
4150 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004151 out->sample_rate = config->offload_info.sample_rate;
4152 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
4153 out->channel_mask = config->offload_info.channel_mask;
4154 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
4155 out->channel_mask = config->channel_mask;
4156 else
4157 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4158
4159 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004160
4161 out->compr_config.codec = (struct snd_codec *)
4162 calloc(1, sizeof(struct snd_codec));
4163
4164 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004165
4166 out->stream.set_callback = out_set_callback;
4167 out->stream.pause = out_pause;
4168 out->stream.resume = out_resume;
4169 out->stream.drain = out_drain;
4170 out->stream.flush = out_flush;
4171
4172 out->compr_config.codec->id =
4173 get_snd_codec_id(config->offload_info.format);
4174 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
4175 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004176 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004177 out->compr_config.codec->bit_rate =
4178 config->offload_info.bit_rate;
4179 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004180 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004181 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
4182
4183 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4184 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004185
4186 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004187 create_offload_callback_thread(out);
4188 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4189 __func__, config->offload_info.version,
4190 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02004191 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4192 switch (config->sample_rate) {
4193 case 0:
4194 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4195 break;
4196 case 8000:
4197 case 16000:
4198 case 48000:
4199 out->sample_rate = config->sample_rate;
4200 break;
4201 default:
4202 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
4203 config->sample_rate);
4204 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4205 ret = -EINVAL;
4206 goto error_open;
4207 }
4208 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4209 switch (config->channel_mask) {
4210 case AUDIO_CHANNEL_NONE:
4211 case AUDIO_CHANNEL_OUT_STEREO:
4212 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4213 break;
4214 default:
4215 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
4216 config->channel_mask);
4217 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4218 ret = -EINVAL;
4219 goto error_open;
4220 }
4221 switch (config->format) {
4222 case AUDIO_FORMAT_DEFAULT:
4223 case AUDIO_FORMAT_PCM_16_BIT:
4224 out->format = AUDIO_FORMAT_PCM_16_BIT;
4225 break;
4226 default:
4227 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
4228 config->format);
4229 config->format = AUDIO_FORMAT_PCM_16_BIT;
4230 ret = -EINVAL;
4231 goto error_open;
4232 }
4233
4234 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004235 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004236 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004237 case 0:
4238 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
4239 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07004240 case 8000:
4241 case 16000:
4242 case 48000:
4243 out->sample_rate = config->sample_rate;
4244 break;
4245 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004246 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
4247 config->sample_rate);
4248 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4249 ret = -EINVAL;
4250 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004251 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004252 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4253 switch (config->channel_mask) {
4254 case AUDIO_CHANNEL_NONE:
4255 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4256 break;
4257 case AUDIO_CHANNEL_OUT_STEREO:
4258 out->channel_mask = config->channel_mask;
4259 break;
4260 default:
4261 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
4262 config->channel_mask);
4263 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4264 ret = -EINVAL;
4265 break;
4266 }
4267 switch (config->format) {
4268 case AUDIO_FORMAT_DEFAULT:
4269 out->format = AUDIO_FORMAT_PCM_16_BIT;
4270 break;
4271 case AUDIO_FORMAT_PCM_16_BIT:
4272 out->format = config->format;
4273 break;
4274 default:
4275 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
4276 config->format);
4277 config->format = AUDIO_FORMAT_PCM_16_BIT;
4278 ret = -EINVAL;
4279 break;
4280 }
4281 if (ret != 0)
4282 goto error_open;
4283
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004284 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4285 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004286 out->config.rate = out->sample_rate;
4287 out->config.channels =
4288 audio_channel_count_from_out_mask(out->channel_mask);
4289 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004290 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004291 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
4292 switch (config->sample_rate) {
4293 case 0:
4294 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4295 break;
4296 case 8000:
4297 case 16000:
4298 case 32000:
4299 case 48000:
4300 out->sample_rate = config->sample_rate;
4301 break;
4302 default:
4303 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
4304 config->sample_rate);
4305 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4306 ret = -EINVAL;
4307 break;
4308 }
Eric Laurentad2dde92017-09-20 18:27:31 -07004309 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004310 switch (config->channel_mask) {
4311 case AUDIO_CHANNEL_NONE:
4312 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4313 break;
4314 case AUDIO_CHANNEL_OUT_STEREO:
4315 out->channel_mask = config->channel_mask;
4316 break;
4317 default:
4318 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
4319 config->channel_mask);
4320 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4321 ret = -EINVAL;
4322 break;
4323 }
4324 switch (config->format) {
4325 case AUDIO_FORMAT_DEFAULT:
4326 out->format = AUDIO_FORMAT_PCM_16_BIT;
4327 break;
4328 case AUDIO_FORMAT_PCM_16_BIT:
4329 out->format = config->format;
4330 break;
4331 default:
4332 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
4333 config->format);
4334 config->format = AUDIO_FORMAT_PCM_16_BIT;
4335 ret = -EINVAL;
4336 break;
4337 }
4338 if (ret != 0)
4339 goto error_open;
4340
vivek mehtaa68fea62017-06-08 19:04:02 -07004341 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07004342 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4343 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004344 out->config.rate = out->sample_rate;
4345 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07004346 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004347 out->sample_rate,
4348 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07004349 out->config.channels,
4350 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004351 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07004352 out->config.period_size = buffer_size / frame_size;
4353 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
4354 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004355 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004356 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07004357 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4358 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004359 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07004360 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
4361 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004362 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07004363 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004364 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004365 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004366 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004367 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4368 out->config = pcm_config_mmap_playback;
4369 out->stream.start = out_start;
4370 out->stream.stop = out_stop;
4371 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4372 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004373 } else {
4374 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4375 out->config = pcm_config_low_latency;
4376 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004377
4378 if (config->sample_rate == 0) {
4379 out->sample_rate = out->config.rate;
4380 } else {
4381 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004382 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004383 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
4384 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
4385 } else {
4386 out->channel_mask = config->channel_mask;
4387 }
4388 if (config->format == AUDIO_FORMAT_DEFAULT)
4389 out->format = audio_format_from_pcm_format(out->config.format);
4390 else if (!audio_is_linear_pcm(config->format)) {
4391 config->format = AUDIO_FORMAT_PCM_16_BIT;
4392 ret = -EINVAL;
4393 goto error_open;
4394 } else {
4395 out->format = config->format;
4396 }
4397
4398 out->config.rate = out->sample_rate;
4399 out->config.channels =
4400 audio_channel_count_from_out_mask(out->channel_mask);
4401 if (out->format != audio_format_from_pcm_format(out->config.format)) {
4402 out->config.format = pcm_format_from_audio_format(out->format);
4403 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004404 }
Kevin Rocard50eff892017-05-02 16:52:05 -07004405
4406 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
4407 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004408 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004409 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
4410 __func__, config->sample_rate, config->format, config->channel_mask);
4411 config->sample_rate = out->sample_rate;
4412 config->format = out->format;
4413 config->channel_mask = out->channel_mask;
4414 ret = -EINVAL;
4415 goto error_open;
4416 }
4417
Andy Hung6fcba9c2014-03-18 11:53:32 -07004418 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
4419 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004420
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004421 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004422 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004423 adev->primary_output = out;
4424 else {
4425 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004426 ret = -EEXIST;
4427 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004428 }
4429 }
4430
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004431 /* Check if this usecase is already existing */
4432 pthread_mutex_lock(&adev->lock);
4433 if (get_usecase_from_list(adev, out->usecase) != NULL) {
4434 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004435 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004436 ret = -EEXIST;
4437 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004438 }
4439 pthread_mutex_unlock(&adev->lock);
4440
4441 out->stream.common.get_sample_rate = out_get_sample_rate;
4442 out->stream.common.set_sample_rate = out_set_sample_rate;
4443 out->stream.common.get_buffer_size = out_get_buffer_size;
4444 out->stream.common.get_channels = out_get_channels;
4445 out->stream.common.get_format = out_get_format;
4446 out->stream.common.set_format = out_set_format;
4447 out->stream.common.standby = out_standby;
4448 out->stream.common.dump = out_dump;
4449 out->stream.common.set_parameters = out_set_parameters;
4450 out->stream.common.get_parameters = out_get_parameters;
4451 out->stream.common.add_audio_effect = out_add_audio_effect;
4452 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4453 out->stream.get_latency = out_get_latency;
4454 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004455#ifdef NO_AUDIO_OUT
4456 out->stream.write = out_write_for_no_output;
4457#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004458 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004459#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004460 out->stream.get_render_position = out_get_render_position;
4461 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004462 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004463
Eric Laurent0e46adf2016-12-16 12:49:24 -08004464 if (out->realtime)
4465 out->af_period_multiplier = af_period_multiplier;
4466 else
4467 out->af_period_multiplier = 1;
4468
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004469 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004470 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004471 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004472
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004473 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004474 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004475 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4476
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004477 config->format = out->stream.common.get_format(&out->stream.common);
4478 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4479 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4480
Kevin Rocarda325aa22018-04-03 09:15:52 -07004481 register_format(out->format, out->supported_formats);
4482 register_channel_mask(out->channel_mask, out->supported_channel_masks);
4483 register_sample_rate(out->sample_rate, out->supported_sample_rates);
4484
Andy Hunga452b0a2017-03-15 14:51:15 -07004485 out->error_log = error_log_create(
4486 ERROR_LOG_ENTRIES,
4487 1000000000 /* aggregate consecutive identical errors within one second in ns */);
4488
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004489 /*
4490 By locking output stream before registering, we allow the callback
4491 to update stream's state only after stream's initial state is set to
4492 adev state.
4493 */
4494 lock_output_stream(out);
4495 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4496 pthread_mutex_lock(&adev->lock);
4497 out->card_status = adev->card_status;
4498 pthread_mutex_unlock(&adev->lock);
4499 pthread_mutex_unlock(&out->lock);
4500
vivek mehta4a824772017-06-08 19:05:49 -07004501 stream_app_type_cfg_init(&out->app_type_cfg);
4502
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004503 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004504
Eric Laurent994a6932013-07-17 11:51:42 -07004505 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004506 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004507
4508error_open:
4509 free(out);
4510 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07004511 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004512 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004513}
4514
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004515static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004516 struct audio_stream_out *stream)
4517{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004518 struct stream_out *out = (struct stream_out *)stream;
4519 struct audio_device *adev = out->dev;
4520
Eric Laurent994a6932013-07-17 11:51:42 -07004521 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004522
4523 // must deregister from sndmonitor first to prevent races
4524 // between the callback and close_stream
4525 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004526 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004527 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
4528 destroy_offload_callback_thread(out);
4529
4530 if (out->compr_config.codec != NULL)
4531 free(out->compr_config.codec);
4532 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004533
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004534 out->a2dp_compress_mute = false;
4535
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004536 if (adev->voice_tx_output == out)
4537 adev->voice_tx_output = NULL;
4538
Andy Hunga452b0a2017-03-15 14:51:15 -07004539 error_log_destroy(out->error_log);
4540 out->error_log = NULL;
4541
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004542 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004543 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004544 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004545 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004546 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004547}
4548
4549static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4550{
4551 struct audio_device *adev = (struct audio_device *)dev;
4552 struct str_parms *parms;
4553 char *str;
4554 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004555 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004556 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07004557 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004558
Joe Onorato188b6222016-03-01 11:02:27 -08004559 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004560
4561 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004562
4563 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004564 status = voice_set_parameters(adev, parms);
4565 if (status != 0) {
4566 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004567 }
4568
4569 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4570 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07004571 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004572 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4573 adev->bluetooth_nrec = true;
4574 else
4575 adev->bluetooth_nrec = false;
4576 }
4577
4578 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4579 if (ret >= 0) {
4580 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4581 adev->screen_off = false;
4582 else
4583 adev->screen_off = true;
4584 }
4585
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004586 ret = str_parms_get_int(parms, "rotation", &val);
4587 if (ret >= 0) {
4588 bool reverse_speakers = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004589 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004590 // FIXME: note that the code below assumes that the speakers are in the correct placement
4591 // relative to the user when the device is rotated 90deg from its default rotation. This
4592 // assumption is device-specific, not platform-specific like this code.
4593 case 270:
4594 reverse_speakers = true;
4595 break;
4596 case 0:
4597 case 90:
4598 case 180:
4599 break;
4600 default:
4601 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07004602 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004603 }
Eric Laurent03f09432014-03-25 18:09:11 -07004604 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004605 // check and set swap
4606 // - check if orientation changed and speaker active
4607 // - set rotation and cache the rotation value
4608 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004609 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004610 }
4611
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004612 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4613 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004614 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004615 }
4616
David Linee3fe402017-03-13 10:00:42 -07004617 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4618 if (ret >= 0) {
4619 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004620 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004621 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4622 if (ret >= 0) {
4623 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004624 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004625 }
Eric Laurent99dab492017-06-17 15:19:08 -07004626 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004627 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4628 if (ret >= 0) {
4629 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004630 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004631 }
4632 }
4633 }
4634
4635 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4636 if (ret >= 0) {
4637 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004638 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004639 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4640 if (ret >= 0) {
4641 const int card = atoi(value);
4642
Eric Laurent99dab492017-06-17 15:19:08 -07004643 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004644 }
Eric Laurent99dab492017-06-17 15:19:08 -07004645 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004646 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4647 if (ret >= 0) {
4648 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004649 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004650 }
4651 }
4652 }
4653
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004654 audio_extn_hfp_set_parameters(adev, parms);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004655 audio_extn_a2dp_set_parameters(parms);
4656 // reconfigure should be done only after updating A2DP state in audio extension
4657 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4658 if (ret >= 0) {
4659 struct audio_usecase *usecase;
4660 struct listnode *node;
4661 list_for_each(node, &adev->usecase_list) {
4662 usecase = node_to_item(node, struct audio_usecase, list);
4663 if ((usecase->type == PCM_PLAYBACK) &&
4664 (usecase->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP)) {
4665 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
4666
4667 pthread_mutex_unlock(&adev->lock);
4668 lock_output_stream(usecase->stream.out);
4669 pthread_mutex_lock(&adev->lock);
4670 audio_extn_a2dp_set_handoff_mode(true);
4671 // force device switch to reconfigure encoder
4672 select_devices(adev, usecase->id);
4673 audio_extn_a2dp_set_handoff_mode(false);
4674 pthread_mutex_unlock(&usecase->stream.out->lock);
4675 break;
4676 }
4677 }
4678 }
4679
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004680done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004681 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004682 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004683 ALOGV("%s: exit with code(%d)", __func__, status);
4684 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004685}
4686
4687static char* adev_get_parameters(const struct audio_hw_device *dev,
4688 const char *keys)
4689{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004690 struct audio_device *adev = (struct audio_device *)dev;
4691 struct str_parms *reply = str_parms_create();
4692 struct str_parms *query = str_parms_create_str(keys);
4693 char *str;
4694
4695 pthread_mutex_lock(&adev->lock);
4696
4697 voice_get_parameters(adev, query, reply);
4698 str = str_parms_to_str(reply);
4699 str_parms_destroy(query);
4700 str_parms_destroy(reply);
4701
4702 pthread_mutex_unlock(&adev->lock);
4703 ALOGV("%s: exit: returns - %s", __func__, str);
4704 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004705}
4706
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004707static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004708{
4709 return 0;
4710}
4711
Haynes Mathew George5191a852013-09-11 14:19:36 -07004712static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4713{
4714 int ret;
4715 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004716
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004717 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4718
Haynes Mathew George5191a852013-09-11 14:19:36 -07004719 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004720 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004721 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004722
Haynes Mathew George5191a852013-09-11 14:19:36 -07004723 return ret;
4724}
4725
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004726static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004727{
4728 return -ENOSYS;
4729}
4730
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004731static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4732 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004733{
4734 return -ENOSYS;
4735}
4736
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004737static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004738{
4739 return -ENOSYS;
4740}
4741
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004742static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004743{
4744 return -ENOSYS;
4745}
4746
4747static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4748{
4749 struct audio_device *adev = (struct audio_device *)dev;
4750
4751 pthread_mutex_lock(&adev->lock);
4752 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004753 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004754 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004755 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4756 voice_is_in_call(adev)) {
4757 voice_stop_call(adev);
4758 adev->current_call_output = NULL;
4759 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004760 }
4761 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004762
4763 audio_extn_extspk_set_mode(adev->extspk, mode);
4764
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004765 return 0;
4766}
4767
4768static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4769{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004770 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004771 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004772
Eric Laurent2bafff12016-03-17 12:17:23 -07004773 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004774 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004775 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4776 ret = audio_extn_hfp_set_mic_mute(adev, state);
4777 } else {
4778 ret = voice_set_mic_mute(adev, state);
4779 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004780 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004781 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004782
4783 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004784}
4785
4786static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4787{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004788 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004789 return 0;
4790}
4791
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004792static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004793 const struct audio_config *config)
4794{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004795 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004796
Eric Laurent74b55762017-07-09 17:04:53 -07004797 /* Don't know if USB HIFI in this context so use true to be conservative */
4798 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4799 true /*is_usb_hifi */) != 0)
4800 return 0;
4801
vivek mehtaa68fea62017-06-08 19:04:02 -07004802 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4803 config->sample_rate, config->format,
4804 channel_count,
4805 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004806}
4807
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004808static bool adev_input_allow_hifi_record(struct audio_device *adev,
4809 audio_devices_t devices,
4810 audio_input_flags_t flags,
4811 audio_source_t source) {
4812 const bool allowed = true;
4813
4814 if (!audio_is_usb_in_device(devices))
4815 return !allowed;
4816
4817 switch (flags) {
4818 case AUDIO_INPUT_FLAG_NONE:
4819 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4820 break;
4821 default:
4822 return !allowed;
4823 }
4824
4825 switch (source) {
4826 case AUDIO_SOURCE_DEFAULT:
4827 case AUDIO_SOURCE_MIC:
4828 case AUDIO_SOURCE_UNPROCESSED:
4829 break;
4830 default:
4831 return !allowed;
4832 }
4833
4834 switch (adev->mode) {
4835 case 0:
4836 break;
4837 default:
4838 return !allowed;
4839 }
4840
4841 return allowed;
4842}
4843
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004844static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004845 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004846 audio_devices_t devices,
4847 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004848 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004849 audio_input_flags_t flags,
4850 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004851 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004852{
4853 struct audio_device *adev = (struct audio_device *)dev;
4854 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004855 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004856 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004857 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004858 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004859 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4860 devices,
4861 flags,
4862 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004863 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004864 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004865
Andy Hungd9653bd2017-08-01 19:31:39 -07004866 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
4867 return -ENOSYS;
4868 }
4869
Eric Laurent74b55762017-07-09 17:04:53 -07004870 if (!(is_usb_dev && may_use_hifi_record)) {
4871 if (config->sample_rate == 0)
4872 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4873 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4874 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4875 if (config->format == AUDIO_FORMAT_DEFAULT)
4876 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004877
Eric Laurent74b55762017-07-09 17:04:53 -07004878 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
4879
4880 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
4881 return -EINVAL;
4882 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004883
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004884 if (audio_extn_tfa_98xx_is_supported() &&
4885 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004886 return -EINVAL;
4887
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004888 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4889
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004890 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004891 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004892
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004893 in->stream.common.get_sample_rate = in_get_sample_rate;
4894 in->stream.common.set_sample_rate = in_set_sample_rate;
4895 in->stream.common.get_buffer_size = in_get_buffer_size;
4896 in->stream.common.get_channels = in_get_channels;
4897 in->stream.common.get_format = in_get_format;
4898 in->stream.common.set_format = in_set_format;
4899 in->stream.common.standby = in_standby;
4900 in->stream.common.dump = in_dump;
4901 in->stream.common.set_parameters = in_set_parameters;
4902 in->stream.common.get_parameters = in_get_parameters;
4903 in->stream.common.add_audio_effect = in_add_audio_effect;
4904 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4905 in->stream.set_gain = in_set_gain;
4906 in->stream.read = in_read;
4907 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08004908 in->stream.get_capture_position = in_get_capture_position;
jiabin8962a4d2018-03-19 18:21:24 -07004909 in->stream.get_active_microphones = in_get_active_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004910
4911 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004912 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004913 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004914 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004915 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004916 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004917
Haynes Mathew George569b7482017-05-08 14:44:27 -07004918 if (is_usb_dev && may_use_hifi_record) {
4919 /* HiFi record selects an appropriate format, channel, rate combo
4920 depending on sink capabilities*/
4921 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
4922 &config->format,
4923 &in->supported_formats[0],
4924 MAX_SUPPORTED_FORMATS,
4925 &config->channel_mask,
4926 &in->supported_channel_masks[0],
4927 MAX_SUPPORTED_CHANNEL_MASKS,
4928 &config->sample_rate,
4929 &in->supported_sample_rates[0],
4930 MAX_SUPPORTED_SAMPLE_RATES);
4931 if (ret != 0) {
4932 ret = -EINVAL;
4933 goto err_open;
4934 }
Eric Laurent74b55762017-07-09 17:04:53 -07004935 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004936 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07004937 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07004938 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
4939 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
4940 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4941 bool ret_error = false;
4942 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4943 from HAL is 8_24
4944 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4945 8_24 return error indicating supported format is 8_24
4946 *> In case of any other source requesting 24 bit or float return error
4947 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07004948
vivek mehta57ff9b52016-04-28 14:13:08 -07004949 on error flinger will retry with supported format passed
4950 */
4951 if (source != AUDIO_SOURCE_UNPROCESSED) {
4952 config->format = AUDIO_FORMAT_PCM_16_BIT;
4953 ret_error = true;
4954 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
4955 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
4956 ret_error = true;
4957 }
4958
4959 if (ret_error) {
4960 ret = -EINVAL;
4961 goto err_open;
4962 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004963 }
4964
vivek mehta57ff9b52016-04-28 14:13:08 -07004965 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07004966 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07004967
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004968 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004969 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
4970 if (config->sample_rate == 0)
4971 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4972 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4973 config->sample_rate != 8000) {
4974 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4975 ret = -EINVAL;
4976 goto err_open;
4977 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004978
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004979 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4980 config->format = AUDIO_FORMAT_PCM_16_BIT;
4981 ret = -EINVAL;
4982 goto err_open;
4983 }
4984
4985 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4986 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07004987 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004988 } else if (is_usb_dev && may_use_hifi_record) {
4989 in->usecase = USECASE_AUDIO_RECORD_HIFI;
4990 in->config = pcm_config_audio_capture;
4991 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004992 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4993 config->sample_rate,
4994 config->format,
4995 channel_count,
4996 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004997 in->config.period_size = buffer_size / frame_size;
4998 in->config.rate = config->sample_rate;
4999 in->af_period_multiplier = 1;
5000 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005001 } else {
5002 in->usecase = USECASE_AUDIO_RECORD;
5003 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08005004 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005005 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07005006#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005007 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07005008#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08005009 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005010 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08005011 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005012 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005013 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5014 config->sample_rate,
5015 config->format,
5016 channel_count,
5017 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005018 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005019 in->config.rate = config->sample_rate;
5020 in->af_period_multiplier = 1;
5021 } else {
5022 // period size is left untouched for rt mode playback
5023 in->config = pcm_config_audio_capture_rt;
5024 in->af_period_multiplier = af_period_multiplier;
5025 }
5026 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
5027 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005028 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08005029 in->usecase = USECASE_AUDIO_RECORD_MMAP;
5030 in->config = pcm_config_mmap_capture;
5031 in->stream.start = in_start;
5032 in->stream.stop = in_stop;
5033 in->stream.create_mmap_buffer = in_create_mmap_buffer;
5034 in->stream.get_mmap_position = in_get_mmap_position;
5035 in->af_period_multiplier = 1;
5036 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07005037 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07005038 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07005039 (config->sample_rate == 8000 ||
5040 config->sample_rate == 16000 ||
5041 config->sample_rate == 32000 ||
5042 config->sample_rate == 48000) &&
5043 channel_count == 1) {
5044 in->usecase = USECASE_AUDIO_RECORD_VOIP;
5045 in->config = pcm_config_audio_capture;
5046 frame_size = audio_stream_in_frame_size(&in->stream);
5047 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
5048 config->sample_rate,
5049 config->format,
5050 channel_count, false /*is_low_latency*/);
5051 in->config.period_size = buffer_size / frame_size;
5052 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
5053 in->config.rate = config->sample_rate;
5054 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005055 } else {
5056 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005057 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005058 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5059 config->sample_rate,
5060 config->format,
5061 channel_count,
5062 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005063 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005064 in->config.rate = config->sample_rate;
5065 in->af_period_multiplier = 1;
5066 }
5067 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
5068 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005069 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08005070
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005071 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07005072 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005073
Kevin Rocarda325aa22018-04-03 09:15:52 -07005074
5075 register_format(in->format, in->supported_formats);
5076 register_channel_mask(in->channel_mask, in->supported_channel_masks);
5077 register_sample_rate(in->sample_rate, in->supported_sample_rates);
5078
Andy Hungd13f0d32017-06-12 13:58:37 -07005079 in->error_log = error_log_create(
5080 ERROR_LOG_ENTRIES,
5081 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
5082
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005083 /* This stream could be for sound trigger lab,
5084 get sound trigger pcm if present */
5085 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005086
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005087 lock_input_stream(in);
5088 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5089 pthread_mutex_lock(&adev->lock);
5090 in->card_status = adev->card_status;
5091 pthread_mutex_unlock(&adev->lock);
5092 pthread_mutex_unlock(&in->lock);
5093
vivek mehta4a824772017-06-08 19:05:49 -07005094 stream_app_type_cfg_init(&in->app_type_cfg);
5095
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005096 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005097 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005098 return 0;
5099
5100err_open:
5101 free(in);
5102 *stream_in = NULL;
5103 return ret;
5104}
5105
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005106static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005107 struct audio_stream_in *stream)
5108{
Andy Hungd13f0d32017-06-12 13:58:37 -07005109 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005110 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005111
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005112 // must deregister from sndmonitor first to prevent races
5113 // between the callback and close_stream
5114 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005115 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07005116
5117 error_log_destroy(in->error_log);
5118 in->error_log = NULL;
5119
Andy Hung0dbb52b2017-08-09 13:51:38 -07005120 pthread_mutex_destroy(&in->pre_lock);
5121 pthread_mutex_destroy(&in->lock);
5122
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005123 free(stream);
5124
5125 return;
5126}
5127
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005128static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005129{
5130 return 0;
5131}
5132
Andy Hung31aca912014-03-20 17:14:59 -07005133/* verifies input and output devices and their capabilities.
5134 *
5135 * This verification is required when enabling extended bit-depth or
5136 * sampling rates, as not all qcom products support it.
5137 *
5138 * Suitable for calling only on initialization such as adev_open().
5139 * It fills the audio_device use_case_table[] array.
5140 *
5141 * Has a side-effect that it needs to configure audio routing / devices
5142 * in order to power up the devices and read the device parameters.
5143 * It does not acquire any hw device lock. Should restore the devices
5144 * back to "normal state" upon completion.
5145 */
5146static int adev_verify_devices(struct audio_device *adev)
5147{
5148 /* enumeration is a bit difficult because one really wants to pull
5149 * the use_case, device id, etc from the hidden pcm_device_table[].
5150 * In this case there are the following use cases and device ids.
5151 *
5152 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
5153 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005154 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07005155 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
5156 * [USECASE_AUDIO_RECORD] = {0, 0},
5157 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
5158 * [USECASE_VOICE_CALL] = {2, 2},
5159 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005160 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07005161 * USECASE_VOICE_CALL omitted, but possible for either input or output.
5162 */
5163
5164 /* should be the usecases enabled in adev_open_input_stream() */
5165 static const int test_in_usecases[] = {
5166 USECASE_AUDIO_RECORD,
5167 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
5168 };
5169 /* should be the usecases enabled in adev_open_output_stream()*/
5170 static const int test_out_usecases[] = {
5171 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
5172 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
5173 };
5174 static const usecase_type_t usecase_type_by_dir[] = {
5175 PCM_PLAYBACK,
5176 PCM_CAPTURE,
5177 };
5178 static const unsigned flags_by_dir[] = {
5179 PCM_OUT,
5180 PCM_IN,
5181 };
5182
5183 size_t i;
5184 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005185 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07005186 char info[512]; /* for possible debug info */
5187
5188 for (dir = 0; dir < 2; ++dir) {
5189 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
5190 const unsigned flags_dir = flags_by_dir[dir];
5191 const size_t testsize =
5192 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
5193 const int *testcases =
5194 dir ? test_in_usecases : test_out_usecases;
5195 const audio_devices_t audio_device =
5196 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
5197
5198 for (i = 0; i < testsize; ++i) {
5199 const audio_usecase_t audio_usecase = testcases[i];
5200 int device_id;
5201 snd_device_t snd_device;
5202 struct pcm_params **pparams;
5203 struct stream_out out;
5204 struct stream_in in;
5205 struct audio_usecase uc_info;
5206 int retval;
5207
5208 pparams = &adev->use_case_table[audio_usecase];
5209 pcm_params_free(*pparams); /* can accept null input */
5210 *pparams = NULL;
5211
5212 /* find the device ID for the use case (signed, for error) */
5213 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
5214 if (device_id < 0)
5215 continue;
5216
5217 /* prepare structures for device probing */
5218 memset(&uc_info, 0, sizeof(uc_info));
5219 uc_info.id = audio_usecase;
5220 uc_info.type = usecase_type;
5221 if (dir) {
5222 adev->active_input = &in;
5223 memset(&in, 0, sizeof(in));
5224 in.device = audio_device;
5225 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
5226 uc_info.stream.in = &in;
5227 } else {
5228 adev->active_input = NULL;
5229 }
5230 memset(&out, 0, sizeof(out));
5231 out.devices = audio_device; /* only field needed in select_devices */
5232 uc_info.stream.out = &out;
5233 uc_info.devices = audio_device;
5234 uc_info.in_snd_device = SND_DEVICE_NONE;
5235 uc_info.out_snd_device = SND_DEVICE_NONE;
5236 list_add_tail(&adev->usecase_list, &uc_info.list);
5237
5238 /* select device - similar to start_(in/out)put_stream() */
5239 retval = select_devices(adev, audio_usecase);
5240 if (retval >= 0) {
5241 *pparams = pcm_params_get(card_id, device_id, flags_dir);
5242#if LOG_NDEBUG == 0
5243 if (*pparams) {
5244 ALOGV("%s: (%s) card %d device %d", __func__,
5245 dir ? "input" : "output", card_id, device_id);
5246 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07005247 } else {
5248 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
5249 }
5250#endif
5251 }
5252
5253 /* deselect device - similar to stop_(in/out)put_stream() */
5254 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07005255 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07005256 /* 2. Disable the rx device */
5257 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07005258 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07005259 list_remove(&uc_info.list);
5260 }
5261 }
5262 adev->active_input = NULL; /* restore adev state */
5263 return 0;
5264}
5265
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005266static int adev_close(hw_device_t *device)
5267{
Andy Hung31aca912014-03-20 17:14:59 -07005268 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005269 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005270
5271 if (!adev)
5272 return 0;
5273
5274 pthread_mutex_lock(&adev_init_lock);
5275
5276 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005277 audio_extn_snd_mon_unregister_listener(adev);
5278 audio_extn_tfa_98xx_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005279 audio_route_free(adev->audio_route);
5280 free(adev->snd_dev_ref_cnt);
5281 platform_deinit(adev->platform);
5282 audio_extn_extspk_deinit(adev->extspk);
5283 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005284 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005285 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
5286 pcm_params_free(adev->use_case_table[i]);
5287 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005288 if (adev->adm_deinit)
5289 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005290 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005291 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07005292 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07005293
5294 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005295
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005296 return 0;
5297}
5298
Glenn Kasten4f993392014-05-14 07:30:48 -07005299/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5300 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5301 * just that it _might_ work.
5302 */
5303static int period_size_is_plausible_for_low_latency(int period_size)
5304{
5305 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005306 case 48:
5307 case 96:
5308 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07005309 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005310 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07005311 case 240:
5312 case 320:
5313 case 480:
5314 return 1;
5315 default:
5316 return 0;
5317 }
5318}
5319
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005320static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
5321{
5322 int card;
5323 card_status_t status;
5324
5325 if (!parms)
5326 return;
5327
5328 if (parse_snd_card_status(parms, &card, &status) < 0)
5329 return;
5330
5331 pthread_mutex_lock(&adev->lock);
5332 bool valid_cb = (card == adev->snd_card);
5333 if (valid_cb) {
5334 if (adev->card_status != status) {
5335 adev->card_status = status;
5336 platform_snd_card_update(adev->platform, status);
5337 }
5338 }
5339 pthread_mutex_unlock(&adev->lock);
5340 return;
5341}
5342
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005343/* out and adev lock held */
5344static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
5345{
5346 struct audio_usecase *uc_info;
5347 float left_p;
5348 float right_p;
5349 audio_devices_t devices;
5350
5351 uc_info = get_usecase_from_list(adev, out->usecase);
5352 if (uc_info == NULL) {
5353 ALOGE("%s: Could not find the usecase (%d) in the list",
5354 __func__, out->usecase);
5355 return -EINVAL;
5356 }
5357
5358 ALOGD("%s: enter: usecase(%d: %s)", __func__,
5359 out->usecase, use_case_table[out->usecase]);
5360
5361 if (restore) {
5362 // restore A2DP device for active usecases and unmute if required
5363 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
5364 !is_a2dp_device(uc_info->out_snd_device)) {
5365 ALOGD("%s: restoring A2DP and unmuting stream", __func__);
5366 select_devices(adev, uc_info->id);
5367 pthread_mutex_lock(&out->compr_mute_lock);
5368 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5369 (out->a2dp_compress_mute)) {
5370 out->a2dp_compress_mute = false;
5371 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5372 }
5373 pthread_mutex_unlock(&out->compr_mute_lock);
5374 }
5375 } else {
5376 // mute compress stream if suspended
5377 pthread_mutex_lock(&out->compr_mute_lock);
5378 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5379 (!out->a2dp_compress_mute)) {
5380 if (!out->standby) {
5381 ALOGD("%s: selecting speaker and muting stream", __func__);
5382 devices = out->devices;
5383 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
5384 left_p = out->volume_l;
5385 right_p = out->volume_r;
5386 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5387 compress_pause(out->compr);
5388 set_compr_volume(&out->stream, 0.0f, 0.0f);
5389 out->a2dp_compress_mute = true;
5390 select_devices(adev, out->usecase);
5391 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5392 compress_resume(out->compr);
5393 out->devices = devices;
5394 out->volume_l = left_p;
5395 out->volume_r = right_p;
5396 }
5397 }
5398 pthread_mutex_unlock(&out->compr_mute_lock);
5399 }
5400 ALOGV("%s: exit", __func__);
5401 return 0;
5402}
5403
5404int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
5405{
5406 int ret = 0;
5407
5408 lock_output_stream(out);
5409 pthread_mutex_lock(&adev->lock);
5410
5411 ret = check_a2dp_restore_l(adev, out, restore);
5412
5413 pthread_mutex_unlock(&adev->lock);
5414 pthread_mutex_unlock(&out->lock);
5415 return ret;
5416}
5417
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005418static int adev_open(const hw_module_t *module, const char *name,
5419 hw_device_t **device)
5420{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005421 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005422
Eric Laurent2bafff12016-03-17 12:17:23 -07005423 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005424 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005425 pthread_mutex_lock(&adev_init_lock);
5426 if (audio_device_ref_count != 0) {
5427 *device = &adev->device.common;
5428 audio_device_ref_count++;
5429 ALOGV("%s: returning existing instance of adev", __func__);
5430 ALOGV("%s: exit", __func__);
5431 pthread_mutex_unlock(&adev_init_lock);
5432 return 0;
5433 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005434 adev = calloc(1, sizeof(struct audio_device));
5435
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005436 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5437
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005438 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5439 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5440 adev->device.common.module = (struct hw_module_t *)module;
5441 adev->device.common.close = adev_close;
5442
5443 adev->device.init_check = adev_init_check;
5444 adev->device.set_voice_volume = adev_set_voice_volume;
5445 adev->device.set_master_volume = adev_set_master_volume;
5446 adev->device.get_master_volume = adev_get_master_volume;
5447 adev->device.set_master_mute = adev_set_master_mute;
5448 adev->device.get_master_mute = adev_get_master_mute;
5449 adev->device.set_mode = adev_set_mode;
5450 adev->device.set_mic_mute = adev_set_mic_mute;
5451 adev->device.get_mic_mute = adev_get_mic_mute;
5452 adev->device.set_parameters = adev_set_parameters;
5453 adev->device.get_parameters = adev_get_parameters;
5454 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5455 adev->device.open_output_stream = adev_open_output_stream;
5456 adev->device.close_output_stream = adev_close_output_stream;
5457 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005458
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005459 adev->device.close_input_stream = adev_close_input_stream;
5460 adev->device.dump = adev_dump;
jiabin8962a4d2018-03-19 18:21:24 -07005461 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005462
5463 /* Set the default route before the PCM stream is opened */
5464 pthread_mutex_lock(&adev->lock);
5465 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005466 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005467 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005468 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005469 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005470 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005471 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005472 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005473 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005474 pthread_mutex_unlock(&adev->lock);
5475
5476 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005477 adev->platform = platform_init(adev);
5478 if (!adev->platform) {
5479 free(adev->snd_dev_ref_cnt);
5480 free(adev);
5481 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5482 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005483 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005484 return -EINVAL;
5485 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05005486 adev->extspk = audio_extn_extspk_init(adev);
5487
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005488 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5489 if (adev->visualizer_lib == NULL) {
5490 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5491 } else {
5492 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5493 adev->visualizer_start_output =
5494 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5495 "visualizer_hal_start_output");
5496 adev->visualizer_stop_output =
5497 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5498 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07005499 }
5500
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005501 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5502 if (adev->offload_effects_lib == NULL) {
5503 ALOGW("%s: DLOPEN failed for %s", __func__,
5504 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5505 } else {
5506 ALOGV("%s: DLOPEN successful for %s", __func__,
5507 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5508 adev->offload_effects_start_output =
5509 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5510 "offload_effects_bundle_hal_start_output");
5511 adev->offload_effects_stop_output =
5512 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5513 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07005514 }
5515
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005516 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5517 if (adev->adm_lib == NULL) {
5518 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5519 } else {
5520 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5521 adev->adm_init = (adm_init_t)
5522 dlsym(adev->adm_lib, "adm_init");
5523 adev->adm_deinit = (adm_deinit_t)
5524 dlsym(adev->adm_lib, "adm_deinit");
5525 adev->adm_register_input_stream = (adm_register_input_stream_t)
5526 dlsym(adev->adm_lib, "adm_register_input_stream");
5527 adev->adm_register_output_stream = (adm_register_output_stream_t)
5528 dlsym(adev->adm_lib, "adm_register_output_stream");
5529 adev->adm_deregister_stream = (adm_deregister_stream_t)
5530 dlsym(adev->adm_lib, "adm_deregister_stream");
5531 adev->adm_request_focus = (adm_request_focus_t)
5532 dlsym(adev->adm_lib, "adm_request_focus");
5533 adev->adm_abandon_focus = (adm_abandon_focus_t)
5534 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08005535 adev->adm_set_config = (adm_set_config_t)
5536 dlsym(adev->adm_lib, "adm_set_config");
5537 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5538 dlsym(adev->adm_lib, "adm_request_focus_v2");
5539 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5540 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5541 adev->adm_on_routing_change = (adm_on_routing_change_t)
5542 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005543 }
5544
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005545 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005546 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005547
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005548 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005549
Andy Hung31aca912014-03-20 17:14:59 -07005550 if (k_enable_extended_precision)
5551 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005552
Glenn Kasten4f993392014-05-14 07:30:48 -07005553 char value[PROPERTY_VALUE_MAX];
5554 int trial;
5555 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5556 trial = atoi(value);
5557 if (period_size_is_plausible_for_low_latency(trial)) {
5558 pcm_config_low_latency.period_size = trial;
5559 pcm_config_low_latency.start_threshold = trial / 4;
5560 pcm_config_low_latency.avail_min = trial / 4;
5561 configured_low_latency_capture_period_size = trial;
5562 }
5563 }
5564 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5565 trial = atoi(value);
5566 if (period_size_is_plausible_for_low_latency(trial)) {
5567 configured_low_latency_capture_period_size = trial;
5568 }
5569 }
5570
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005571 // commented as full set of app type cfg is sent from platform
5572 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005573 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005574
5575 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5576 af_period_multiplier = atoi(value);
5577 if (af_period_multiplier < 0) {
5578 af_period_multiplier = 2;
5579 } else if (af_period_multiplier > 4) {
5580 af_period_multiplier = 4;
5581 }
5582 ALOGV("new period_multiplier = %d", af_period_multiplier);
5583 }
5584
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005585 audio_extn_tfa_98xx_init(adev);
5586
vivek mehta1a9b7c02015-06-25 11:49:38 -07005587 pthread_mutex_unlock(&adev_init_lock);
5588
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005589 if (adev->adm_init)
5590 adev->adm_data = adev->adm_init();
5591
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005592 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005593 audio_extn_snd_mon_init();
5594 pthread_mutex_lock(&adev->lock);
5595 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
5596 adev->card_status = CARD_STATUS_ONLINE;
5597 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005598 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005599
Eric Laurent2bafff12016-03-17 12:17:23 -07005600 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005601 return 0;
5602}
5603
5604static struct hw_module_methods_t hal_module_methods = {
5605 .open = adev_open,
5606};
5607
5608struct audio_module HAL_MODULE_INFO_SYM = {
5609 .common = {
5610 .tag = HARDWARE_MODULE_TAG,
5611 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5612 .hal_api_version = HARDWARE_HAL_API_VERSION,
5613 .id = AUDIO_HARDWARE_MODULE_ID,
5614 .name = "QCOM Audio HAL",
5615 .author = "Code Aurora Forum",
5616 .methods = &hal_module_methods,
5617 },
5618};