blob: 325131eb7174ba108a957d2689f2d729692b99f4 [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",
Eric Laurentb23d5282013-05-14 15:27:20 -0700294};
295
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800296
297#define STRING_TO_ENUM(string) { #string, string }
298
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800299struct string_to_enum {
300 const char *name;
301 uint32_t value;
302};
303
Haynes Mathew George569b7482017-05-08 14:44:27 -0700304static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800305 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
306 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
307 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Eric Laurent74b55762017-07-09 17:04:53 -0700308 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
Haynes Mathew George569b7482017-05-08 14:44:27 -0700309 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
Eric Laurent74b55762017-07-09 17:04:53 -0700310 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
311 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
312 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
313 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
314 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
315 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
316 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
317 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
318 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800319};
320
Haynes Mathew George5191a852013-09-11 14:19:36 -0700321static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700322static struct audio_device *adev = NULL;
Andy Hung9e737de2017-05-22 10:51:22 -0700323static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700324static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700325//cache last MBDRC cal step level
326static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700327
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800328static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
329static int set_compr_volume(struct audio_stream_out *stream, float left, float right);
330
Haynes Mathew George03c40102016-01-29 17:57:48 -0800331static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
332 int flags __unused)
333{
334 int dir = 0;
335 switch (uc_id) {
336 case USECASE_AUDIO_RECORD_LOW_LATENCY:
337 dir = 1;
338 case USECASE_AUDIO_PLAYBACK_ULL:
339 break;
340 default:
341 return false;
342 }
343
344 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
345 PCM_PLAYBACK : PCM_CAPTURE);
346 if (adev->adm_is_noirq_avail)
347 return adev->adm_is_noirq_avail(adev->adm_data,
348 adev->snd_card, dev_id, dir);
349 return false;
350}
351
352static void register_out_stream(struct stream_out *out)
353{
354 struct audio_device *adev = out->dev;
355 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
356 return;
357
358 if (!adev->adm_register_output_stream)
359 return;
360
361 adev->adm_register_output_stream(adev->adm_data,
362 out->handle,
363 out->flags);
364
365 if (!adev->adm_set_config)
366 return;
367
368 if (out->realtime) {
369 adev->adm_set_config(adev->adm_data,
370 out->handle,
371 out->pcm, &out->config);
372 }
373}
374
375static void register_in_stream(struct stream_in *in)
376{
377 struct audio_device *adev = in->dev;
378 if (!adev->adm_register_input_stream)
379 return;
380
381 adev->adm_register_input_stream(adev->adm_data,
382 in->capture_handle,
383 in->flags);
384
385 if (!adev->adm_set_config)
386 return;
387
388 if (in->realtime) {
389 adev->adm_set_config(adev->adm_data,
390 in->capture_handle,
391 in->pcm,
392 &in->config);
393 }
394}
395
396static void request_out_focus(struct stream_out *out, long ns)
397{
398 struct audio_device *adev = out->dev;
399
Haynes Mathew George03c40102016-01-29 17:57:48 -0800400 if (adev->adm_request_focus_v2) {
401 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
402 } else if (adev->adm_request_focus) {
403 adev->adm_request_focus(adev->adm_data, out->handle);
404 }
405}
406
407static void request_in_focus(struct stream_in *in, long ns)
408{
409 struct audio_device *adev = in->dev;
410
Haynes Mathew George03c40102016-01-29 17:57:48 -0800411 if (adev->adm_request_focus_v2) {
412 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
413 } else if (adev->adm_request_focus) {
414 adev->adm_request_focus(adev->adm_data, in->capture_handle);
415 }
416}
417
418static void release_out_focus(struct stream_out *out, long ns __unused)
419{
420 struct audio_device *adev = out->dev;
421
422 if (adev->adm_abandon_focus)
423 adev->adm_abandon_focus(adev->adm_data, out->handle);
424}
425
426static void release_in_focus(struct stream_in *in, long ns __unused)
427{
428 struct audio_device *adev = in->dev;
429 if (adev->adm_abandon_focus)
430 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
431}
432
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700433static int parse_snd_card_status(struct str_parms * parms, int * card,
434 card_status_t * status)
435{
436 char value[32]={0};
437 char state[32]={0};
438
439 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
440
441 if (ret < 0)
442 return -1;
443
444 // sscanf should be okay as value is of max length 32.
445 // same as sizeof state.
446 if (sscanf(value, "%d,%s", card, state) < 2)
447 return -1;
448
449 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
450 CARD_STATUS_OFFLINE;
451 return 0;
452}
453
vivek mehta40125092017-08-21 18:48:51 -0700454// always call with adev lock held
455void send_gain_dep_calibration_l() {
456 if (last_known_cal_step >= 0)
457 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
458}
459
vivek mehta1a9b7c02015-06-25 11:49:38 -0700460__attribute__ ((visibility ("default")))
461bool audio_hw_send_gain_dep_calibration(int level) {
462 bool ret_val = false;
463 ALOGV("%s: enter ... ", __func__);
464
465 pthread_mutex_lock(&adev_init_lock);
466
467 if (adev != NULL && adev->platform != NULL) {
468 pthread_mutex_lock(&adev->lock);
vivek mehta40125092017-08-21 18:48:51 -0700469 last_known_cal_step = level;
470 send_gain_dep_calibration_l();
vivek mehta1a9b7c02015-06-25 11:49:38 -0700471 pthread_mutex_unlock(&adev->lock);
472 } else {
473 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
474 }
475
476 pthread_mutex_unlock(&adev_init_lock);
477
478 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
479 return ret_val;
480}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700481
vivek mehtaa8d7c922016-05-25 14:40:44 -0700482__attribute__ ((visibility ("default")))
483int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
484 int table_size) {
485 int ret_val = 0;
486 ALOGV("%s: enter ... ", __func__);
487
488 pthread_mutex_lock(&adev_init_lock);
489 if (adev == NULL) {
490 ALOGW("%s: adev is NULL .... ", __func__);
491 goto done;
492 }
493
494 pthread_mutex_lock(&adev->lock);
495 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
496 pthread_mutex_unlock(&adev->lock);
497done:
498 pthread_mutex_unlock(&adev_init_lock);
499 ALOGV("%s: exit ... ", __func__);
500 return ret_val;
501}
502
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700503static bool is_supported_format(audio_format_t format)
504{
Eric Laurent8251ac82014-07-23 11:00:25 -0700505 switch (format) {
506 case AUDIO_FORMAT_MP3:
507 case AUDIO_FORMAT_AAC_LC:
508 case AUDIO_FORMAT_AAC_HE_V1:
509 case AUDIO_FORMAT_AAC_HE_V2:
510 return true;
511 default:
512 break;
513 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700514 return false;
515}
516
Haynes Mathew George03c40102016-01-29 17:57:48 -0800517static inline bool is_mmap_usecase(audio_usecase_t uc_id)
518{
519 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
520 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
521}
522
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700523static int get_snd_codec_id(audio_format_t format)
524{
525 int id = 0;
526
Eric Laurent8251ac82014-07-23 11:00:25 -0700527 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700528 case AUDIO_FORMAT_MP3:
529 id = SND_AUDIOCODEC_MP3;
530 break;
531 case AUDIO_FORMAT_AAC:
532 id = SND_AUDIOCODEC_AAC;
533 break;
534 default:
535 ALOGE("%s: Unsupported audio format", __func__);
536 }
537
538 return id;
539}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800540
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800541static int audio_ssr_status(struct audio_device *adev)
542{
543 int ret = 0;
544 struct mixer_ctl *ctl;
545 const char *mixer_ctl_name = "Audio SSR Status";
546
547 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
548 ret = mixer_ctl_get_value(ctl, 0);
549 ALOGD("%s: value: %d", __func__, ret);
550 return ret;
551}
552
vivek mehta4a824772017-06-08 19:05:49 -0700553static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
554{
555 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
556}
557
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800558static bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
559{
560 return out_snd_device == SND_DEVICE_OUT_BT_SCO ||
561 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
562 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
563 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
564 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
565 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC;
566
567}
568
569static bool is_a2dp_device(snd_device_t out_snd_device)
570{
571 return out_snd_device == SND_DEVICE_OUT_BT_A2DP;
572}
573
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800574int enable_audio_route(struct audio_device *adev,
575 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800576{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700577 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800578 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800579
580 if (usecase == NULL)
581 return -EINVAL;
582
583 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
584
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800585 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700586 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800587 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700588 snd_device = usecase->out_snd_device;
Yamit Mehtae3b99562016-09-16 22:44:00 +0530589 audio_extn_utils_send_app_type_cfg(adev, usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800590 audio_extn_utils_send_audio_calibration(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800591 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500592 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000593 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700594 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700595 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800596
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800597 ALOGV("%s: exit", __func__);
598 return 0;
599}
600
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800601int disable_audio_route(struct audio_device *adev,
602 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800603{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700604 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800605 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800606
607 if (usecase == NULL)
608 return -EINVAL;
609
610 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700611 if (usecase->type == PCM_CAPTURE)
612 snd_device = usecase->in_snd_device;
613 else
614 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800615 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500616 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700617 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700618 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000619 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800620
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800621 ALOGV("%s: exit", __func__);
622 return 0;
623}
624
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800625int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700626 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800627{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700628 int i, num_devices = 0;
629 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800630 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800631 if (snd_device < SND_DEVICE_MIN ||
632 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800633 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800634 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800635 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700636
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700637 platform_send_audio_calibration(adev->platform, snd_device);
638
vivek mehtade4849c2016-03-03 17:23:38 -0800639 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700640 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700641 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800642 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700643 }
644
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700645 /* due to the possibility of calibration overwrite between listen
646 and audio, notify sound trigger hal before audio calibration is sent */
647 audio_extn_sound_trigger_update_device_status(snd_device,
648 ST_EVENT_SND_DEVICE_BUSY);
649
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700650 if (audio_extn_spkr_prot_is_enabled())
651 audio_extn_spkr_prot_calib_cancel(adev);
652
zhaoyang yin4211fad2015-06-04 21:13:25 +0800653 audio_extn_dsm_feedback_enable(adev, snd_device, true);
654
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800655 if (is_a2dp_device(snd_device) &&
656 (audio_extn_a2dp_start_playback() < 0)) {
657 ALOGE("%s: failed to configure A2DP control path", __func__);
658 goto on_error;
659 }
660
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700661 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800662 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700663 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
664 audio_extn_spkr_prot_is_enabled()) {
665 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800666 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700667 }
668 if (audio_extn_spkr_prot_start_processing(snd_device)) {
669 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800670 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700671 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700672 } else if (platform_can_split_snd_device(snd_device,
673 &num_devices,
674 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700675 for (i = 0; i < num_devices; i++) {
676 enable_snd_device(adev, new_snd_devices[i]);
677 }
vivek mehtab6506412015-08-07 16:55:17 -0700678 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700679 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800680 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
681 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
682 ALOGE(" %s: Invalid sound device returned", __func__);
683 goto on_error;
684 }
Ed Tam70b5c142016-03-21 19:14:29 -0700685
Eric Laurent2e140aa2016-06-30 17:14:46 -0700686 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800687 audio_route_apply_and_update_path(adev->audio_route, device_name);
688 }
689on_success:
690 adev->snd_dev_ref_cnt[snd_device]++;
691 ret_val = 0;
692on_error:
693 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800694}
695
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800696int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700697 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800698{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700699 int i, num_devices = 0;
700 snd_device_t new_snd_devices[2];
701
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800702 if (snd_device < SND_DEVICE_MIN ||
703 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800704 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800705 return -EINVAL;
706 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700707 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
708 ALOGE("%s: device ref cnt is already 0", __func__);
709 return -EINVAL;
710 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800711 audio_extn_tfa_98xx_disable_speaker(snd_device);
712
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700713 adev->snd_dev_ref_cnt[snd_device]--;
714 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800715 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800716
717 if (is_a2dp_device(snd_device))
718 audio_extn_a2dp_stop_playback();
719
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700720 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800721 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700722 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700723 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
724 audio_extn_spkr_prot_is_enabled()) {
725 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700726
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700727 // FIXME b/65363602: bullhead is the only Nexus with audio_extn_spkr_prot_is_enabled()
728 // and does not use speaker swap. As this code causes a problem with device enable ref
729 // counting we remove it for now.
vivek mehtae59cfb22017-06-16 15:57:11 -0700730 // when speaker device is disabled, reset swap.
731 // will be renabled on usecase start
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700732 // platform_set_swap_channels(adev, false);
vivek mehtae59cfb22017-06-16 15:57:11 -0700733
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700734 } else if (platform_can_split_snd_device(snd_device,
735 &num_devices,
736 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700737 for (i = 0; i < num_devices; i++) {
738 disable_snd_device(adev, new_snd_devices[i]);
739 }
vivek mehtab6506412015-08-07 16:55:17 -0700740 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700741 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800742 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
743 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
744 ALOGE(" %s: Invalid sound device returned", __func__);
745 return -EINVAL;
746 }
747
Eric Laurent2e140aa2016-06-30 17:14:46 -0700748 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800749 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700750 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700751 audio_extn_sound_trigger_update_device_status(snd_device,
752 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700753 }
vivek mehtab6506412015-08-07 16:55:17 -0700754
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800755 return 0;
756}
757
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700758/*
759 legend:
760 uc - existing usecase
761 new_uc - new usecase
762 d1, d11, d2 - SND_DEVICE enums
763 a1, a2 - corresponding ANDROID device enums
764 B, B1, B2 - backend strings
765
766case 1
767 uc->dev d1 (a1) B1
768 new_uc->dev d1 (a1), d2 (a2) B1, B2
769
770 resolution: disable and enable uc->dev on d1
771
772case 2
773 uc->dev d1 (a1) B1
774 new_uc->dev d11 (a1) B1
775
776 resolution: need to switch uc since d1 and d11 are related
777 (e.g. speaker and voice-speaker)
778 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
779
780case 3
781 uc->dev d1 (a1) B1
782 new_uc->dev d2 (a2) B2
783
784 resolution: no need to switch uc
785
786case 4
787 uc->dev d1 (a1) B
788 new_uc->dev d2 (a2) B
789
790 resolution: disable enable uc-dev on d2 since backends match
791 we cannot enable two streams on two different devices if they
792 share the same backend. e.g. if offload is on speaker device using
793 QUAD_MI2S backend and a low-latency stream is started on voice-handset
794 using the same backend, offload must also be switched to voice-handset.
795
796case 5
797 uc->dev d1 (a1) B
798 new_uc->dev d1 (a1), d2 (a2) B
799
800 resolution: disable enable uc-dev on d2 since backends match
801 we cannot enable two streams on two different devices if they
802 share the same backend.
803
804case 6
805 uc->dev d1 a1 B1
806 new_uc->dev d2 a1 B2
807
808 resolution: no need to switch
809
810case 7
811
812 uc->dev d1 (a1), d2 (a2) B1, B2
813 new_uc->dev d1 B1
814
815 resolution: no need to switch
816
817*/
818static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
819 struct audio_usecase *new_uc,
820 snd_device_t new_snd_device)
821{
822 audio_devices_t a1 = uc->stream.out->devices;
823 audio_devices_t a2 = new_uc->stream.out->devices;
824
825 snd_device_t d1 = uc->out_snd_device;
826 snd_device_t d2 = new_snd_device;
827
828 // Treat as a special case when a1 and a2 are not disjoint
829 if ((a1 != a2) && (a1 & a2)) {
830 snd_device_t d3[2];
831 int num_devices = 0;
832 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
833 &num_devices,
834 d3);
835 if (ret < 0) {
836 if (ret != -ENOSYS) {
837 ALOGW("%s failed to split snd_device %d",
838 __func__,
839 popcount(a1) > 1 ? d1 : d2);
840 }
841 goto end;
842 }
843
844 // NB: case 7 is hypothetical and isn't a practical usecase yet.
845 // But if it does happen, we need to give priority to d2 if
846 // the combo devices active on the existing usecase share a backend.
847 // This is because we cannot have a usecase active on a combo device
848 // and a new usecase requests one device in this combo pair.
849 if (platform_check_backends_match(d3[0], d3[1])) {
850 return d2; // case 5
851 } else {
852 return d1; // case 1
853 }
854 } else {
855 if (platform_check_backends_match(d1, d2)) {
856 return d2; // case 2, 4
857 } else {
858 return d1; // case 6, 3
859 }
860 }
861
862end:
863 return d2; // return whatever was calculated before.
864}
865
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700866static void check_and_route_playback_usecases(struct audio_device *adev,
867 struct audio_usecase *uc_info,
868 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700869{
870 struct listnode *node;
871 struct audio_usecase *usecase;
872 bool switch_device[AUDIO_USECASE_MAX];
873 int i, num_uc_to_switch = 0;
874
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700875 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
876 uc_info,
877 snd_device);
David Linee3fe402017-03-13 10:00:42 -0700878
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800879 /* For a2dp device reconfigure all active sessions
880 * with new AFE encoder format based on a2dp state
881 */
882 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
883 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
884 audio_extn_a2dp_is_force_device_switch()) {
885 force_routing = true;
886 }
887
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700888 /*
889 * This function is to make sure that all the usecases that are active on
890 * the hardware codec backend are always routed to any one device that is
891 * handled by the hardware codec.
892 * For example, if low-latency and deep-buffer usecases are currently active
893 * on speaker and out_set_parameters(headset) is received on low-latency
894 * output, then we have to make sure deep-buffer is also switched to headset,
895 * because of the limitation that both the devices cannot be enabled
896 * at the same time as they share the same backend.
897 */
898 /* Disable all the usecases on the shared backend other than the
899 specified usecase */
900 for (i = 0; i < AUDIO_USECASE_MAX; i++)
901 switch_device[i] = false;
902
903 list_for_each(node, &adev->usecase_list) {
904 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700905 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
906 continue;
907
908 if (force_routing ||
909 (usecase->out_snd_device != snd_device &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -0700910 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
911 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700912 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700913 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
914 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700915 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700916 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700917 switch_device[usecase->id] = true;
918 num_uc_to_switch++;
919 }
920 }
921
922 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700923 list_for_each(node, &adev->usecase_list) {
924 usecase = node_to_item(node, struct audio_usecase, list);
925 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700926 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900927 }
928 }
929
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700930 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900931 list_for_each(node, &adev->usecase_list) {
932 usecase = node_to_item(node, struct audio_usecase, list);
933 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700934 d_device = derive_playback_snd_device(usecase, uc_info,
935 snd_device);
936 enable_snd_device(adev, d_device);
937 /* Update the out_snd_device before enabling the audio route */
938 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700939 }
940 }
941
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700942 /* Re-route all the usecases on the shared backend other than the
943 specified usecase to new snd devices */
944 list_for_each(node, &adev->usecase_list) {
945 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700946 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700947 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700948 }
949 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700950 }
951}
952
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700953static void check_and_route_capture_usecases(struct audio_device *adev,
954 struct audio_usecase *uc_info,
955 snd_device_t snd_device)
956{
957 struct listnode *node;
958 struct audio_usecase *usecase;
959 bool switch_device[AUDIO_USECASE_MAX];
960 int i, num_uc_to_switch = 0;
961
vivek mehta4ed66e62016-04-15 23:33:34 -0700962 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
963
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700964 /*
965 * This function is to make sure that all the active capture usecases
966 * are always routed to the same input sound device.
967 * For example, if audio-record and voice-call usecases are currently
968 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
969 * is received for voice call then we have to make sure that audio-record
970 * usecase is also switched to earpiece i.e. voice-dmic-ef,
971 * because of the limitation that two devices cannot be enabled
972 * at the same time if they share the same backend.
973 */
974 for (i = 0; i < AUDIO_USECASE_MAX; i++)
975 switch_device[i] = false;
976
977 list_for_each(node, &adev->usecase_list) {
978 usecase = node_to_item(node, struct audio_usecase, list);
979 if (usecase->type != PCM_PLAYBACK &&
980 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700981 usecase->in_snd_device != snd_device &&
982 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700983 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
984 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700985 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700986 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700987 switch_device[usecase->id] = true;
988 num_uc_to_switch++;
989 }
990 }
991
992 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700993 list_for_each(node, &adev->usecase_list) {
994 usecase = node_to_item(node, struct audio_usecase, list);
995 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700996 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700997 }
998 }
999
1000 list_for_each(node, &adev->usecase_list) {
1001 usecase = node_to_item(node, struct audio_usecase, list);
1002 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001003 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001004 }
1005 }
1006
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001007 /* Re-route all the usecases on the shared backend other than the
1008 specified usecase to new snd devices */
1009 list_for_each(node, &adev->usecase_list) {
1010 usecase = node_to_item(node, struct audio_usecase, list);
1011 /* Update the in_snd_device only before enabling the audio route */
1012 if (switch_device[usecase->id] ) {
1013 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001014 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001015 }
1016 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001017 }
1018}
1019
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001020/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001021static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001022{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001023 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001024 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001025
1026 switch (channels) {
1027 /*
1028 * Do not handle stereo output in Multi-channel cases
1029 * Stereo case is handled in normal playback path
1030 */
1031 case 6:
1032 ALOGV("%s: HDMI supports 5.1", __func__);
1033 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1034 break;
1035 case 8:
1036 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
1037 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1038 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
1039 break;
1040 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001041 ALOGE("HDMI does not support multi channel playback");
1042 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001043 break;
1044 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001045 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001046}
1047
Andy Hung18859412017-08-09 11:47:21 -07001048static ssize_t read_usb_sup_sample_rates(bool is_playback,
1049 uint32_t *supported_sample_rates,
1050 uint32_t max_rates)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001051{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001052 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1053 supported_sample_rates,
1054 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001055#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001056 for (ssize_t i=0; i<count; i++) {
1057 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1058 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001059 }
1060#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001061 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001062}
1063
Haynes Mathew George569b7482017-05-08 14:44:27 -07001064static int read_usb_sup_channel_masks(bool is_playback,
1065 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001066 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001067{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001068 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001069 int channel_count;
1070 uint32_t num_masks = 0;
1071 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1072 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001073 }
Eric Laurent74b55762017-07-09 17:04:53 -07001074 if (is_playback) {
Andy Hung6c1afb12017-12-22 11:34:41 -08001075 // start from 2 channels as framework currently doesn't support mono.
1076 // TODO: consider only supporting channel index masks beyond stereo here.
1077 for (channel_count = FCC_2;
1078 channel_count <= channels && num_masks < max_masks;
1079 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001080 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1081 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001082 for (channel_count = FCC_2;
1083 channel_count <= channels && num_masks < max_masks;
1084 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001085 supported_channel_masks[num_masks++] =
1086 audio_channel_mask_for_index_assignment_from_count(channel_count);
1087 }
1088 } else {
1089 // For capture we report all supported channel masks from 1 channel up.
1090 channel_count = MIN_CHANNEL_COUNT;
1091 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1092 // indexed mask
1093 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1094 supported_channel_masks[num_masks++] =
1095 audio_channel_in_mask_from_count(channel_count);
1096 }
1097 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001098#ifdef NDEBUG
1099 for (size_t i = 0; i < num_masks; ++i) {
1100 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1101 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
1102 }
1103#endif
Eric Laurent74b55762017-07-09 17:04:53 -07001104 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001105}
1106
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001107static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001108 audio_format_t *supported_formats,
1109 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001110{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001111 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001112 switch (bitwidth) {
1113 case 24:
1114 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001115 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001116 break;
1117 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001118 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001119 break;
1120 case 16:
1121 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001122 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001123 break;
1124 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001125 ALOGV("%s: %s supported format %d", __func__,
1126 is_playback ? "P" : "C", bitwidth);
1127 return 1;
1128}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001129
Haynes Mathew George569b7482017-05-08 14:44:27 -07001130static int read_usb_sup_params_and_compare(bool is_playback,
1131 audio_format_t *format,
1132 audio_format_t *supported_formats,
1133 uint32_t max_formats,
1134 audio_channel_mask_t *mask,
1135 audio_channel_mask_t *supported_channel_masks,
1136 uint32_t max_masks,
1137 uint32_t *rate,
1138 uint32_t *supported_sample_rates,
1139 uint32_t max_rates) {
1140 int ret = 0;
1141 int num_formats;
1142 int num_masks;
1143 int num_rates;
1144 int i;
1145
1146 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1147 max_formats);
1148 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1149 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001150
Haynes Mathew George569b7482017-05-08 14:44:27 -07001151 num_rates = read_usb_sup_sample_rates(is_playback,
1152 supported_sample_rates, max_rates);
1153
1154#define LUT(table, len, what, dflt) \
1155 for (i=0; i<len && (table[i] != what); i++); \
1156 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1157
1158 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1159 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1160 LUT(supported_sample_rates, num_rates, *rate, 0);
1161
1162#undef LUT
1163 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001164}
1165
Andy Hungd9653bd2017-08-01 19:31:39 -07001166static bool is_usb_ready(struct audio_device *adev, bool is_playback)
1167{
1168 // Check if usb is ready.
1169 // The usb device may have been removed quickly after insertion and hence
1170 // no longer available. This will show up as empty channel masks, or rates.
1171
1172 pthread_mutex_lock(&adev->lock);
1173 uint32_t supported_sample_rate;
1174
1175 // we consider usb ready if we can fetch at least one sample rate.
1176 const bool ready = read_usb_sup_sample_rates(
1177 is_playback, &supported_sample_rate, 1 /* max_rates */) > 0;
1178 pthread_mutex_unlock(&adev->lock);
1179 return ready;
1180}
1181
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001182static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1183{
1184 struct audio_usecase *usecase;
1185 struct listnode *node;
1186
1187 list_for_each(node, &adev->usecase_list) {
1188 usecase = node_to_item(node, struct audio_usecase, list);
1189 if (usecase->type == VOICE_CALL) {
1190 ALOGV("%s: usecase id %d", __func__, usecase->id);
1191 return usecase->id;
1192 }
1193 }
1194 return USECASE_INVALID;
1195}
1196
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001197struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1198 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001199{
1200 struct audio_usecase *usecase;
1201 struct listnode *node;
1202
1203 list_for_each(node, &adev->usecase_list) {
1204 usecase = node_to_item(node, struct audio_usecase, list);
1205 if (usecase->id == uc_id)
1206 return usecase;
1207 }
1208 return NULL;
1209}
1210
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001211static bool force_device_switch(struct audio_usecase *usecase)
1212{
1213 if (usecase->stream.out == NULL) {
1214 ALOGE("%s: stream.out is NULL", __func__);
1215 return false;
1216 }
1217
1218 // Force all A2DP output devices to reconfigure for proper AFE encode format
1219 // Also handle a case where in earlier A2DP start failed as A2DP stream was
1220 // in suspended state, hence try to trigger a retry when we again get a routing request.
1221 if ((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
1222 audio_extn_a2dp_is_force_device_switch()) {
1223 ALOGD("%s: Force A2DP device switch to update new encoder config", __func__);
1224 return true;
1225 }
1226
1227 return false;
1228}
1229
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001230int select_devices(struct audio_device *adev,
1231 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001232{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001233 snd_device_t out_snd_device = SND_DEVICE_NONE;
1234 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001235 struct audio_usecase *usecase = NULL;
1236 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001237 struct audio_usecase *hfp_usecase = NULL;
1238 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001239 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001240 int status = 0;
Eric Laurentf4520b02017-09-20 18:31:58 -07001241 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1242 USECASE_AUDIO_PLAYBACK_VOIP);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001243
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001244 usecase = get_usecase_from_list(adev, uc_id);
1245 if (usecase == NULL) {
1246 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1247 return -EINVAL;
1248 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001249
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001250 if ((usecase->type == VOICE_CALL) ||
1251 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001252 out_snd_device = platform_get_output_snd_device(adev->platform,
1253 usecase->stream.out->devices);
1254 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001255 usecase->devices = usecase->stream.out->devices;
1256 } else {
1257 /*
1258 * If the voice call is active, use the sound devices of voice call usecase
1259 * so that it would not result any device switch. All the usecases will
1260 * be switched to new device when select_devices() is called for voice call
1261 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001262 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001263 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001264 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001265 vc_usecase = get_usecase_from_list(adev,
1266 get_voice_usecase_id_from_list(adev));
1267 if ((vc_usecase != NULL) &&
1268 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1269 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001270 in_snd_device = vc_usecase->in_snd_device;
1271 out_snd_device = vc_usecase->out_snd_device;
1272 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001273 } else if (audio_extn_hfp_is_active(adev)) {
1274 hfp_ucid = audio_extn_hfp_get_usecase();
1275 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1276 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1277 in_snd_device = hfp_usecase->in_snd_device;
1278 out_snd_device = hfp_usecase->out_snd_device;
1279 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001280 }
1281 if (usecase->type == PCM_PLAYBACK) {
1282 usecase->devices = usecase->stream.out->devices;
1283 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001284 if (out_snd_device == SND_DEVICE_NONE) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001285 struct stream_out *voip_out = adev->primary_output;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001286
Eric Laurentb23d5282013-05-14 15:27:20 -07001287 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001288 usecase->stream.out->devices);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001289
1290 if (voip_usecase)
1291 voip_out = voip_usecase->stream.out;
1292
1293 if (usecase->stream.out == voip_out &&
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001294 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001295 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001296 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001297 select_devices(adev, adev->active_input->usecase);
1298 }
1299 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001300 } else if (usecase->type == PCM_CAPTURE) {
1301 usecase->devices = usecase->stream.in->device;
1302 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001303 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001304 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001305 if (adev->active_input &&
1306 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1307 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001308
1309 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1310 USECASE_AUDIO_PLAYBACK_VOIP);
1311
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001312 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001313 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1314 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001315 } else if (voip_usecase) {
1316 out_device = voip_usecase->stream.out->devices;
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001317 } else if (adev->primary_output) {
1318 out_device = adev->primary_output->devices;
1319 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001320 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001321 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001322 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001323 }
1324 }
1325
1326 if (out_snd_device == usecase->out_snd_device &&
1327 in_snd_device == usecase->in_snd_device) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001328 if (!force_device_switch(usecase))
1329 return 0;
1330 }
1331
1332 if (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready()) {
1333 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1334 return 0;
1335 }
1336
1337 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP) &&
1338 (!audio_extn_a2dp_is_ready())) {
1339 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
1340 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001341 }
1342
Eric Laurent2bafff12016-03-17 12:17:23 -07001343 if (out_snd_device != SND_DEVICE_NONE &&
1344 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1345 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1346 __func__,
1347 use_case_table[uc_id],
1348 adev->last_logged_snd_device[uc_id][0],
1349 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1350 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1351 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1352 -1,
1353 out_snd_device,
1354 platform_get_snd_device_name(out_snd_device),
1355 platform_get_snd_device_acdb_id(out_snd_device));
1356 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1357 }
1358 if (in_snd_device != SND_DEVICE_NONE &&
1359 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1360 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1361 __func__,
1362 use_case_table[uc_id],
1363 adev->last_logged_snd_device[uc_id][1],
1364 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1365 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1366 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1367 -1,
1368 in_snd_device,
1369 platform_get_snd_device_name(in_snd_device),
1370 platform_get_snd_device_acdb_id(in_snd_device));
1371 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1372 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001373
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001374 /*
1375 * Limitation: While in call, to do a device switch we need to disable
1376 * and enable both RX and TX devices though one of them is same as current
1377 * device.
1378 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001379 if ((usecase->type == VOICE_CALL) &&
1380 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1381 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001382 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001383 /* Disable sidetone only if voice call already exists */
1384 if (voice_is_call_state_active(adev))
1385 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001386 }
1387
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001388 /* Disable current sound devices */
1389 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001390 disable_audio_route(adev, usecase);
1391 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001392 }
1393
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001394 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001395 disable_audio_route(adev, usecase);
1396 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001397 }
1398
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001399 /* Applicable only on the targets that has external modem.
1400 * New device information should be sent to modem before enabling
1401 * the devices to reduce in-call device switch time.
1402 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001403 if ((usecase->type == VOICE_CALL) &&
1404 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1405 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001406 status = platform_switch_voice_call_enable_device_config(adev->platform,
1407 out_snd_device,
1408 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001409 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001410
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001411 /* Enable new sound devices */
1412 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001413 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001414 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) ||
1415 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001416 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001417 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001418 }
1419
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001420 if (in_snd_device != SND_DEVICE_NONE) {
1421 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001422 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001423 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001424
Eric Laurentb23d5282013-05-14 15:27:20 -07001425 if (usecase->type == VOICE_CALL)
1426 status = platform_switch_voice_call_device_post(adev->platform,
1427 out_snd_device,
1428 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001429
sangwoo170731f2013-06-08 15:36:36 +09001430 usecase->in_snd_device = in_snd_device;
1431 usecase->out_snd_device = out_snd_device;
1432
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001433 audio_extn_tfa_98xx_set_mode();
1434
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001435 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001436
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001437 /* Applicable only on the targets that has external modem.
1438 * Enable device command should be sent to modem only after
1439 * enabling voice call mixer controls
1440 */
vivek mehta765eb642015-08-07 19:46:06 -07001441 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001442 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1443 out_snd_device,
1444 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001445 /* Enable sidetone only if voice call already exists */
1446 if (voice_is_call_state_active(adev))
1447 voice_set_sidetone(adev, out_snd_device, true);
1448 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001449
Eric Laurentf4520b02017-09-20 18:31:58 -07001450 if (usecase == voip_usecase) {
1451 struct stream_out *voip_out = voip_usecase->stream.out;
1452 audio_extn_utils_send_app_type_gain(adev,
1453 voip_out->app_type_cfg.app_type,
1454 &voip_out->app_type_cfg.gain[0]);
1455 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001456 return status;
1457}
1458
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001459static int stop_input_stream(struct stream_in *in)
1460{
1461 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001462 struct audio_usecase *uc_info;
1463 struct audio_device *adev = in->dev;
1464
Eric Laurent994a6932013-07-17 11:51:42 -07001465 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001466 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001467
1468 if (adev->active_input) {
1469 if (adev->active_input->usecase == in->usecase) {
1470 adev->active_input = NULL;
1471 } else {
1472 ALOGW("%s adev->active_input->usecase %s, v/s in->usecase %s",
1473 __func__,
1474 use_case_table[adev->active_input->usecase],
1475 use_case_table[in->usecase]);
1476 }
1477 }
1478
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001479 uc_info = get_usecase_from_list(adev, in->usecase);
1480 if (uc_info == NULL) {
1481 ALOGE("%s: Could not find the usecase (%d) in the list",
1482 __func__, in->usecase);
1483 return -EINVAL;
1484 }
1485
vivek mehta781065c2017-04-04 12:55:01 -07001486 /* Close in-call recording streams */
1487 voice_check_and_stop_incall_rec_usecase(adev, in);
1488
Eric Laurent150dbfe2013-02-27 14:31:02 -08001489 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001490 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001491
1492 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001493 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001494
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001495 list_remove(&uc_info->list);
1496 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001497
Eric Laurent994a6932013-07-17 11:51:42 -07001498 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001499 return ret;
1500}
1501
1502int start_input_stream(struct stream_in *in)
1503{
1504 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001505 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001506 struct audio_usecase *uc_info;
1507 struct audio_device *adev = in->dev;
1508
Eric Laurent994a6932013-07-17 11:51:42 -07001509 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001510
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001511 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1512 return -EIO;
1513
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001514 if (in->card_status == CARD_STATUS_OFFLINE ||
1515 adev->card_status == CARD_STATUS_OFFLINE) {
1516 ALOGW("in->card_status or adev->card_status offline, try again");
1517 ret = -EAGAIN;
1518 goto error_config;
1519 }
1520
vivek mehta781065c2017-04-04 12:55:01 -07001521 /* Check if source matches incall recording usecase criteria */
1522 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1523 if (ret)
1524 goto error_config;
1525 else
1526 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1527
Eric Laurentb23d5282013-05-14 15:27:20 -07001528 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001529 if (in->pcm_device_id < 0) {
1530 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1531 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001532 ret = -EINVAL;
1533 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001534 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001535
1536 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001537 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1538 uc_info->id = in->usecase;
1539 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001540 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001541 uc_info->devices = in->device;
1542 uc_info->in_snd_device = SND_DEVICE_NONE;
1543 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001544
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001545 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001546
Wei Wangf4837d52017-11-21 14:51:20 -08001547 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001548 audio_extn_perf_lock_acquire();
1549
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001550 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001551
Eric Laurent0e46adf2016-12-16 12:49:24 -08001552 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001553 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001554 ALOGE("%s: pcm stream not ready", __func__);
1555 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001556 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001557 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001558 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001559 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1560 goto error_open;
1561 }
1562 } else {
1563 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1564 unsigned int pcm_open_retry_count = 0;
1565
1566 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1567 flags |= PCM_MMAP | PCM_NOIRQ;
1568 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1569 } else if (in->realtime) {
1570 flags |= PCM_MMAP | PCM_NOIRQ;
1571 }
1572
1573 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1574 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1575
1576 while (1) {
1577 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1578 flags, &in->config);
1579 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1580 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1581 if (in->pcm != NULL) {
1582 pcm_close(in->pcm);
1583 in->pcm = NULL;
1584 }
1585 if (pcm_open_retry_count-- == 0) {
1586 ret = -EIO;
1587 goto error_open;
1588 }
1589 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1590 continue;
1591 }
1592 break;
1593 }
1594
1595 ALOGV("%s: pcm_prepare", __func__);
1596 ret = pcm_prepare(in->pcm);
1597 if (ret < 0) {
1598 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001599 pcm_close(in->pcm);
1600 in->pcm = NULL;
1601 goto error_open;
1602 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001603 if (in->realtime) {
1604 ret = pcm_start(in->pcm);
1605 if (ret < 0) {
1606 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1607 pcm_close(in->pcm);
1608 in->pcm = NULL;
1609 goto error_open;
1610 }
1611 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001612 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001613 register_in_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001614 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001615 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001616 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001617
Eric Laurent0e46adf2016-12-16 12:49:24 -08001618 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001619
1620error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001621 stop_input_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001622 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001623 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001624
1625error_config:
1626 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001627 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001628 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001629}
1630
Eric Laurenta1478072015-09-21 17:21:52 -07001631void lock_input_stream(struct stream_in *in)
1632{
1633 pthread_mutex_lock(&in->pre_lock);
1634 pthread_mutex_lock(&in->lock);
1635 pthread_mutex_unlock(&in->pre_lock);
1636}
1637
1638void lock_output_stream(struct stream_out *out)
1639{
1640 pthread_mutex_lock(&out->pre_lock);
1641 pthread_mutex_lock(&out->lock);
1642 pthread_mutex_unlock(&out->pre_lock);
1643}
1644
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001645/* must be called with out->lock locked */
1646static int send_offload_cmd_l(struct stream_out* out, int command)
1647{
1648 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1649
1650 ALOGVV("%s %d", __func__, command);
1651
1652 cmd->cmd = command;
1653 list_add_tail(&out->offload_cmd_list, &cmd->node);
1654 pthread_cond_signal(&out->offload_cond);
1655 return 0;
1656}
1657
1658/* must be called iwth out->lock locked */
1659static void stop_compressed_output_l(struct stream_out *out)
1660{
1661 out->offload_state = OFFLOAD_STATE_IDLE;
1662 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001663 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001664 if (out->compr != NULL) {
1665 compress_stop(out->compr);
1666 while (out->offload_thread_blocked) {
1667 pthread_cond_wait(&out->cond, &out->lock);
1668 }
1669 }
1670}
1671
1672static void *offload_thread_loop(void *context)
1673{
1674 struct stream_out *out = (struct stream_out *) context;
1675 struct listnode *item;
1676
1677 out->offload_state = OFFLOAD_STATE_IDLE;
1678 out->playback_started = 0;
1679
1680 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1681 set_sched_policy(0, SP_FOREGROUND);
1682 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1683
1684 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001685 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001686 for (;;) {
1687 struct offload_cmd *cmd = NULL;
1688 stream_callback_event_t event;
1689 bool send_callback = false;
1690
1691 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1692 __func__, list_empty(&out->offload_cmd_list),
1693 out->offload_state);
1694 if (list_empty(&out->offload_cmd_list)) {
1695 ALOGV("%s SLEEPING", __func__);
1696 pthread_cond_wait(&out->offload_cond, &out->lock);
1697 ALOGV("%s RUNNING", __func__);
1698 continue;
1699 }
1700
1701 item = list_head(&out->offload_cmd_list);
1702 cmd = node_to_item(item, struct offload_cmd, node);
1703 list_remove(item);
1704
1705 ALOGVV("%s STATE %d CMD %d out->compr %p",
1706 __func__, out->offload_state, cmd->cmd, out->compr);
1707
1708 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1709 free(cmd);
1710 break;
1711 }
1712
1713 if (out->compr == NULL) {
1714 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001715 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001716 pthread_cond_signal(&out->cond);
1717 continue;
1718 }
1719 out->offload_thread_blocked = true;
1720 pthread_mutex_unlock(&out->lock);
1721 send_callback = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001722 switch (cmd->cmd) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001723 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1724 compress_wait(out->compr, -1);
1725 send_callback = true;
1726 event = STREAM_CBK_EVENT_WRITE_READY;
1727 break;
1728 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001729 compress_next_track(out->compr);
1730 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001731 send_callback = true;
1732 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001733 /* Resend the metadata for next iteration */
1734 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001735 break;
1736 case OFFLOAD_CMD_DRAIN:
1737 compress_drain(out->compr);
1738 send_callback = true;
1739 event = STREAM_CBK_EVENT_DRAIN_READY;
1740 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001741 case OFFLOAD_CMD_ERROR:
1742 send_callback = true;
1743 event = STREAM_CBK_EVENT_ERROR;
1744 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001745 default:
1746 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1747 break;
1748 }
Eric Laurenta1478072015-09-21 17:21:52 -07001749 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001750 out->offload_thread_blocked = false;
1751 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001752 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001753 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001754 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001755 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001756 free(cmd);
1757 }
1758
1759 pthread_cond_signal(&out->cond);
1760 while (!list_empty(&out->offload_cmd_list)) {
1761 item = list_head(&out->offload_cmd_list);
1762 list_remove(item);
1763 free(node_to_item(item, struct offload_cmd, node));
1764 }
1765 pthread_mutex_unlock(&out->lock);
1766
1767 return NULL;
1768}
1769
1770static int create_offload_callback_thread(struct stream_out *out)
1771{
1772 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1773 list_init(&out->offload_cmd_list);
1774 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1775 offload_thread_loop, out);
1776 return 0;
1777}
1778
1779static int destroy_offload_callback_thread(struct stream_out *out)
1780{
Eric Laurenta1478072015-09-21 17:21:52 -07001781 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001782 stop_compressed_output_l(out);
1783 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1784
1785 pthread_mutex_unlock(&out->lock);
1786 pthread_join(out->offload_thread, (void **) NULL);
1787 pthread_cond_destroy(&out->offload_cond);
1788
1789 return 0;
1790}
1791
Eric Laurent07eeafd2013-10-06 12:52:49 -07001792static bool allow_hdmi_channel_config(struct audio_device *adev)
1793{
1794 struct listnode *node;
1795 struct audio_usecase *usecase;
1796 bool ret = true;
1797
1798 list_for_each(node, &adev->usecase_list) {
1799 usecase = node_to_item(node, struct audio_usecase, list);
1800 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1801 /*
1802 * If voice call is already existing, do not proceed further to avoid
1803 * disabling/enabling both RX and TX devices, CSD calls, etc.
1804 * Once the voice call done, the HDMI channels can be configured to
1805 * max channels of remaining use cases.
1806 */
1807 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001808 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001809 __func__);
1810 ret = false;
1811 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001812 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1813 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001814 "no change in HDMI channels", __func__);
1815 ret = false;
1816 break;
1817 }
1818 }
1819 }
1820 return ret;
1821}
1822
1823static int check_and_set_hdmi_channels(struct audio_device *adev,
1824 unsigned int channels)
1825{
1826 struct listnode *node;
1827 struct audio_usecase *usecase;
1828
1829 /* Check if change in HDMI channel config is allowed */
1830 if (!allow_hdmi_channel_config(adev))
1831 return 0;
1832
1833 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001834 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001835 return 0;
1836 }
1837
1838 platform_set_hdmi_channels(adev->platform, channels);
1839 adev->cur_hdmi_channels = channels;
1840
1841 /*
1842 * Deroute all the playback streams routed to HDMI so that
1843 * the back end is deactivated. Note that backend will not
1844 * be deactivated if any one stream is connected to it.
1845 */
1846 list_for_each(node, &adev->usecase_list) {
1847 usecase = node_to_item(node, struct audio_usecase, list);
1848 if (usecase->type == PCM_PLAYBACK &&
1849 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001850 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001851 }
1852 }
1853
1854 /*
1855 * Enable all the streams disabled above. Now the HDMI backend
1856 * will be activated with new channel configuration
1857 */
1858 list_for_each(node, &adev->usecase_list) {
1859 usecase = node_to_item(node, struct audio_usecase, list);
1860 if (usecase->type == PCM_PLAYBACK &&
1861 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001862 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001863 }
1864 }
1865
1866 return 0;
1867}
1868
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001869static int stop_output_stream(struct stream_out *out)
1870{
1871 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001872 struct audio_usecase *uc_info;
1873 struct audio_device *adev = out->dev;
1874
Eric Laurent994a6932013-07-17 11:51:42 -07001875 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001876 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001877 uc_info = get_usecase_from_list(adev, out->usecase);
1878 if (uc_info == NULL) {
1879 ALOGE("%s: Could not find the usecase (%d) in the list",
1880 __func__, out->usecase);
1881 return -EINVAL;
1882 }
1883
Haynes Mathew George41f86652014-06-17 14:22:15 -07001884 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1885 if (adev->visualizer_stop_output != NULL)
1886 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1887 if (adev->offload_effects_stop_output != NULL)
1888 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08001889 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
1890 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
1891 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07001892 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001893
Eric Laurent150dbfe2013-02-27 14:31:02 -08001894 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001895 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001896
1897 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001898 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001899
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001900 list_remove(&uc_info->list);
1901 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001902
Eric Laurent0499d4f2014-08-25 22:39:29 -05001903 audio_extn_extspk_update(adev->extspk);
1904
Eric Laurent07eeafd2013-10-06 12:52:49 -07001905 /* Must be called after removing the usecase from list */
1906 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1907 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07001908 else if (out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
1909 struct listnode *node;
1910 struct audio_usecase *usecase;
1911 list_for_each(node, &adev->usecase_list) {
1912 usecase = node_to_item(node, struct audio_usecase, list);
1913 if (usecase->devices & AUDIO_DEVICE_OUT_SPEAKER)
1914 select_devices(adev, usecase->id);
1915 }
1916 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001917
Eric Laurent994a6932013-07-17 11:51:42 -07001918 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001919 return ret;
1920}
1921
1922int start_output_stream(struct stream_out *out)
1923{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001924 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001925 struct audio_usecase *uc_info;
1926 struct audio_device *adev = out->dev;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001927 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001928
Eric Laurent994a6932013-07-17 11:51:42 -07001929 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001930 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001931
1932 if (out->card_status == CARD_STATUS_OFFLINE ||
1933 adev->card_status == CARD_STATUS_OFFLINE) {
1934 ALOGW("out->card_status or adev->card_status offline, try again");
1935 ret = -EAGAIN;
1936 goto error_config;
1937 }
1938
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001939 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
1940 if (!audio_extn_a2dp_is_ready()) {
1941 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
1942 a2dp_combo = true;
1943 } else {
1944 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
1945 ALOGE("%s: A2DP profile is not ready, return error", __func__);
1946 ret = -EAGAIN;
1947 goto error_config;
1948 }
1949 }
1950 }
1951 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001952 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001953 if (out->pcm_device_id < 0) {
1954 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1955 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001956 ret = -EINVAL;
1957 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001958 }
1959
1960 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1961 uc_info->id = out->usecase;
1962 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001963 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001964 uc_info->devices = out->devices;
1965 uc_info->in_snd_device = SND_DEVICE_NONE;
1966 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001967
Eric Laurent07eeafd2013-10-06 12:52:49 -07001968 /* This must be called before adding this usecase to the list */
1969 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1970 check_and_set_hdmi_channels(adev, out->config.channels);
1971
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001972 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001973
Wei Wangf4837d52017-11-21 14:51:20 -08001974 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001975 audio_extn_perf_lock_acquire();
1976
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001977 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
1978 (!audio_extn_a2dp_is_ready())) {
1979 if (!a2dp_combo) {
1980 check_a2dp_restore_l(adev, out, false);
1981 } else {
1982 audio_devices_t dev = out->devices;
1983 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
1984 select_devices(adev, out->usecase);
1985 out->devices = dev;
1986 }
1987 } else {
1988 select_devices(adev, out->usecase);
1989 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001990
Eric Laurent0499d4f2014-08-25 22:39:29 -05001991 audio_extn_extspk_update(adev->extspk);
1992
Andy Hung31aca912014-03-20 17:14:59 -07001993 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001994 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001995 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1996 out->pcm = NULL;
1997 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1998 COMPRESS_IN, &out->compr_config);
1999 if (out->compr && !is_compress_ready(out->compr)) {
2000 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2001 compress_close(out->compr);
2002 out->compr = NULL;
2003 ret = -EIO;
2004 goto error_open;
2005 }
2006 if (out->offload_callback)
2007 compress_nonblock(out->compr, out->non_blocking);
2008
2009 if (adev->visualizer_start_output != NULL)
2010 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2011 if (adev->offload_effects_start_output != NULL)
2012 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
2013 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002014 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002015 ALOGE("%s: pcm stream not ready", __func__);
2016 goto error_open;
2017 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002018 ret = pcm_start(out->pcm);
2019 if (ret < 0) {
2020 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2021 goto error_open;
2022 }
2023 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07002024 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002025 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002026
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002027 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2028 flags |= PCM_MMAP | PCM_NOIRQ;
2029 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002030 } else if (out->realtime) {
2031 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07002032 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002033
2034 while (1) {
2035 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2036 flags, &out->config);
2037 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2038 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2039 if (out->pcm != NULL) {
2040 pcm_close(out->pcm);
2041 out->pcm = NULL;
2042 }
2043 if (pcm_open_retry_count-- == 0) {
2044 ret = -EIO;
2045 goto error_open;
2046 }
2047 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2048 continue;
2049 }
2050 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002051 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002052 ALOGV("%s: pcm_prepare", __func__);
2053 if (pcm_is_ready(out->pcm)) {
2054 ret = pcm_prepare(out->pcm);
2055 if (ret < 0) {
2056 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2057 pcm_close(out->pcm);
2058 out->pcm = NULL;
2059 goto error_open;
2060 }
2061 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002062 if (out->realtime) {
2063 ret = pcm_start(out->pcm);
2064 if (ret < 0) {
2065 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
2066 pcm_close(out->pcm);
2067 out->pcm = NULL;
2068 goto error_open;
2069 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002070 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002071 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002072 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08002073 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002074 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002075 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07002076
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002077 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2078 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2079 audio_low_latency_hint_start();
2080 }
2081
vivek mehtae59cfb22017-06-16 15:57:11 -07002082 // consider a scenario where on pause lower layers are tear down.
2083 // so on resume, swap mixer control need to be sent only when
2084 // backend is active, hence rather than sending from enable device
2085 // sending it from start of streamtream
2086
2087 platform_set_swap_channels(adev, true);
2088
Eric Laurent994a6932013-07-17 11:51:42 -07002089 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002090 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002091error_open:
Wei Wangf4837d52017-11-21 14:51:20 -08002092 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002093 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002094 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002095error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002096 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002097}
2098
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002099static int check_input_parameters(uint32_t sample_rate,
2100 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07002101 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002102{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002103 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2104 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002105 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2106 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002107 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2108 return -EINVAL;
2109 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002110
Eric Laurent74b55762017-07-09 17:04:53 -07002111 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2112 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002113 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002114 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002115 return -EINVAL;
2116 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002117
2118 switch (sample_rate) {
2119 case 8000:
2120 case 11025:
2121 case 12000:
2122 case 16000:
2123 case 22050:
2124 case 24000:
2125 case 32000:
2126 case 44100:
2127 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002128 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002129 break;
2130 default:
vivek mehtadae44712015-07-27 14:13:18 -07002131 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002132 return -EINVAL;
2133 }
2134
2135 return 0;
2136}
2137
vivek mehtaa68fea62017-06-08 19:04:02 -07002138static size_t get_stream_buffer_size(size_t duration_ms,
2139 uint32_t sample_rate,
2140 audio_format_t format,
2141 int channel_count,
2142 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002143{
2144 size_t size = 0;
2145
vivek mehtaa68fea62017-06-08 19:04:02 -07002146 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002147 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002148 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002149
2150 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002151
Glenn Kasten4f993392014-05-14 07:30:48 -07002152 /* make sure the size is multiple of 32 bytes
2153 * At 48 kHz mono 16-bit PCM:
2154 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2155 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2156 */
2157 size += 0x1f;
2158 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002159
2160 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002161}
2162
2163static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2164{
2165 struct stream_out *out = (struct stream_out *)stream;
2166
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002167 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002168}
2169
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002170static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002171{
2172 return -ENOSYS;
2173}
2174
2175static size_t out_get_buffer_size(const struct audio_stream *stream)
2176{
2177 struct stream_out *out = (struct stream_out *)stream;
2178
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002179 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2180 return out->compr_config.fragment_size;
2181 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002182 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002183 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002184}
2185
2186static uint32_t out_get_channels(const struct audio_stream *stream)
2187{
2188 struct stream_out *out = (struct stream_out *)stream;
2189
2190 return out->channel_mask;
2191}
2192
2193static audio_format_t out_get_format(const struct audio_stream *stream)
2194{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002195 struct stream_out *out = (struct stream_out *)stream;
2196
2197 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002198}
2199
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002200static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002201{
2202 return -ENOSYS;
2203}
2204
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002205/* must be called with out->lock locked */
2206static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002207{
2208 struct stream_out *out = (struct stream_out *)stream;
2209 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002210 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002211
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002212 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002213 if (adev->adm_deregister_stream)
2214 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002215 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002216 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002217 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2218 if (out->pcm) {
2219 pcm_close(out->pcm);
2220 out->pcm = NULL;
2221 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002222 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002223 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002224 out->playback_started = false;
2225 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002226 } else {
2227 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002228 out->gapless_mdata.encoder_delay = 0;
2229 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002230 if (out->compr != NULL) {
2231 compress_close(out->compr);
2232 out->compr = NULL;
2233 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002234 }
Phil Burkbc991042017-02-24 08:06:44 -08002235 if (do_stop) {
2236 stop_output_stream(out);
2237 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002238 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002239 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002240 return 0;
2241}
2242
2243static int out_standby(struct audio_stream *stream)
2244{
2245 struct stream_out *out = (struct stream_out *)stream;
2246
2247 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2248 out->usecase, use_case_table[out->usecase]);
2249
2250 lock_output_stream(out);
2251 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002252 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002253 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002254 return 0;
2255}
2256
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002257static int out_on_error(struct audio_stream *stream)
2258{
2259 struct stream_out *out = (struct stream_out *)stream;
2260 struct audio_device *adev = out->dev;
2261 bool do_standby = false;
2262
2263 lock_output_stream(out);
2264 if (!out->standby) {
2265 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2266 stop_compressed_output_l(out);
2267 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2268 } else
2269 do_standby = true;
2270 }
2271 pthread_mutex_unlock(&out->lock);
2272
2273 if (do_standby)
2274 return out_standby(&out->stream.common);
2275
2276 return 0;
2277}
2278
Andy Hung7401c7c2016-09-21 12:41:21 -07002279static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002280{
Andy Hung7401c7c2016-09-21 12:41:21 -07002281 struct stream_out *out = (struct stream_out *)stream;
2282
2283 // We try to get the lock for consistency,
2284 // but it isn't necessary for these variables.
2285 // If we're not in standby, we may be blocked on a write.
2286 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2287 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2288 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2289
2290 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002291 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002292 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002293
2294 // dump error info
2295 (void)error_log_dump(
2296 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002297
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002298 return 0;
2299}
2300
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002301static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2302{
2303 int ret = 0;
2304 char value[32];
2305 struct compr_gapless_mdata tmp_mdata;
2306
2307 if (!out || !parms) {
2308 return -EINVAL;
2309 }
2310
2311 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2312 if (ret >= 0) {
2313 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2314 } else {
2315 return -EINVAL;
2316 }
2317
2318 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2319 if (ret >= 0) {
2320 tmp_mdata.encoder_padding = atoi(value);
2321 } else {
2322 return -EINVAL;
2323 }
2324
2325 out->gapless_mdata = tmp_mdata;
2326 out->send_new_metadata = 1;
2327 ALOGV("%s new encoder delay %u and padding %u", __func__,
2328 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2329
2330 return 0;
2331}
2332
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002333static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2334{
2335 return out == adev->primary_output || out == adev->voice_tx_output;
2336}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002337
Kevin Rocard1e02c882017-08-09 15:26:07 -07002338static int get_alive_usb_card(struct str_parms* parms) {
2339 int card;
2340 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2341 !audio_extn_usb_alive(card)) {
2342 return card;
2343 }
2344 return -ENODEV;
2345}
2346
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002347static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2348{
2349 struct stream_out *out = (struct stream_out *)stream;
2350 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002351 struct audio_usecase *usecase;
2352 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002353 struct str_parms *parms;
2354 char value[32];
2355 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002356 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002357 int status = 0;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002358 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002359
Eric Laurent2e140aa2016-06-30 17:14:46 -07002360 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002361 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002362 parms = str_parms_create_str(kvpairs);
2363 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2364 if (ret >= 0) {
2365 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002366
Eric Laurenta1478072015-09-21 17:21:52 -07002367 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002368
2369 // The usb driver needs to be closed after usb device disconnection
2370 // otherwise audio is no longer played on the new usb devices.
2371 // By forcing the stream in standby, the usb stack refcount drops to 0
2372 // and the driver is closed.
2373 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD && val == AUDIO_DEVICE_NONE &&
2374 audio_is_usb_out_device(out->devices)) {
2375 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2376 out_standby_l(&out->stream.common);
2377 }
2378
Eric Laurent150dbfe2013-02-27 14:31:02 -08002379 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002380
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002381 /*
2382 * When HDMI cable is unplugged the music playback is paused and
2383 * the policy manager sends routing=0. But the audioflinger
2384 * continues to write data until standby time (3sec).
2385 * As the HDMI core is turned off, the write gets blocked.
2386 * Avoid this by routing audio to speaker until standby.
2387 */
2388 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2389 val == AUDIO_DEVICE_NONE) {
2390 val = AUDIO_DEVICE_OUT_SPEAKER;
2391 }
2392
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002393 /*
2394 * When A2DP is disconnected the
2395 * music playback is paused and the policy manager sends routing=0
2396 * But the audioflingercontinues to write data until standby time
2397 * (3sec). As BT is turned off, the write gets blocked.
2398 * Avoid this by routing audio to speaker until standby.
2399 */
2400 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2401 (val == AUDIO_DEVICE_NONE) &&
2402 !audio_extn_a2dp_is_ready()) {
2403 val = AUDIO_DEVICE_OUT_SPEAKER;
2404 }
2405
2406 /* To avoid a2dp to sco overlapping / BT device improper state
2407 * check with BT lib about a2dp streaming support before routing
2408 */
2409 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2410 if (!audio_extn_a2dp_is_ready()) {
2411 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
2412 //combo usecase just by pass a2dp
2413 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2414 bypass_a2dp = true;
2415 } else {
2416 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2417 /* update device to a2dp and don't route as BT returned error
2418 * However it is still possible a2dp routing called because
2419 * of current active device disconnection (like wired headset)
2420 */
2421 out->devices = val;
2422 pthread_mutex_unlock(&out->lock);
2423 pthread_mutex_unlock(&adev->lock);
2424 status = -ENOSYS;
2425 goto routing_fail;
2426 }
2427 }
2428 }
2429
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002430 audio_devices_t new_dev = val;
2431
2432 // Workaround: If routing to an non existing usb device, fail gracefully
2433 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002434 int card;
2435 if (audio_is_usb_out_device(new_dev) &&
2436 (card = get_alive_usb_card(parms)) >= 0) {
2437
2438 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002439 pthread_mutex_unlock(&adev->lock);
2440 pthread_mutex_unlock(&out->lock);
2441 status = -ENOSYS;
2442 goto routing_fail;
2443 }
2444
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002445 /*
2446 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002447 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002448 * the select_devices(). But how do we undo this?
2449 *
2450 * For example, music playback is active on headset (deep-buffer usecase)
2451 * and if we go to ringtones and select a ringtone, low-latency usecase
2452 * will be started on headset+speaker. As we can't enable headset+speaker
2453 * and headset devices at the same time, select_devices() switches the music
2454 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2455 * So when the ringtone playback is completed, how do we undo the same?
2456 *
2457 * We are relying on the out_set_parameters() call on deep-buffer output,
2458 * once the ringtone playback is ended.
2459 * NOTE: We should not check if the current devices are same as new devices.
2460 * Because select_devices() must be called to switch back the music
2461 * playback to headset.
2462 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002463 if (new_dev != AUDIO_DEVICE_NONE) {
2464 bool same_dev = out->devices == new_dev;
2465 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002466
Eric Laurenta7657192014-10-09 21:09:33 -07002467 if (output_drives_call(adev, out)) {
2468 if (!voice_is_in_call(adev)) {
2469 if (adev->mode == AUDIO_MODE_IN_CALL) {
2470 adev->current_call_output = out;
2471 ret = voice_start_call(adev);
2472 }
2473 } else {
2474 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002475 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002476 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002477 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002478
2479 if (!out->standby) {
2480 if (!same_dev) {
2481 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002482 // inform adm before actual routing to prevent glitches.
2483 if (adev->adm_on_routing_change) {
2484 adev->adm_on_routing_change(adev->adm_data,
2485 out->handle);
2486 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002487 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002488 if (!bypass_a2dp) {
2489 select_devices(adev, out->usecase);
2490 } else {
2491 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2492 select_devices(adev, out->usecase);
2493 out->devices = new_dev;
2494 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002495 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002496
2497 // on device switch force swap, lower functions will make sure
2498 // to check if swap is allowed or not.
2499
2500 if (!same_dev)
2501 platform_set_swap_channels(adev, true);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002502
2503 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2504 out->a2dp_compress_mute &&
2505 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
2506 pthread_mutex_lock(&out->compr_mute_lock);
2507 out->a2dp_compress_mute = false;
2508 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
2509 pthread_mutex_unlock(&out->compr_mute_lock);
2510 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002511 }
2512
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002513 }
2514
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002515 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002516 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002517
2518 /*handles device and call state changes*/
2519 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002520 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002521 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002522
2523 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2524 parse_compress_metadata(out, parms);
2525 }
2526
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002527 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002528 ALOGV("%s: exit: code(%d)", __func__, status);
2529 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002530}
2531
Haynes Mathew George569b7482017-05-08 14:44:27 -07002532static bool stream_get_parameter_channels(struct str_parms *query,
2533 struct str_parms *reply,
2534 audio_channel_mask_t *supported_channel_masks) {
2535 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002536 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002537 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002538 size_t i, j;
2539
2540 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2541 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002542 value[0] = '\0';
2543 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002544 while (supported_channel_masks[i] != 0) {
2545 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2546 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002547 if (!first) {
2548 strcat(value, "|");
2549 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002550 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002551 first = false;
2552 break;
2553 }
2554 }
2555 i++;
2556 }
2557 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002558 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002559 return ret >= 0;
2560}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002561
Haynes Mathew George569b7482017-05-08 14:44:27 -07002562static bool stream_get_parameter_formats(struct str_parms *query,
2563 struct str_parms *reply,
2564 audio_format_t *supported_formats) {
2565 int ret = -1;
2566 char value[256];
2567 int i;
2568
2569 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2570 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002571 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002572 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002573 case AUDIO_FORMAT_PCM_16_BIT:
2574 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2575 break;
2576 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2577 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2578 break;
2579 case AUDIO_FORMAT_PCM_32_BIT:
2580 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2581 break;
2582 default:
2583 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002584 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002585 break;
2586 }
2587 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002588 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002589 return ret >= 0;
2590}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002591
Haynes Mathew George569b7482017-05-08 14:44:27 -07002592static bool stream_get_parameter_rates(struct str_parms *query,
2593 struct str_parms *reply,
2594 uint32_t *supported_sample_rates) {
2595
2596 int i;
2597 char value[256];
2598 int ret = -1;
2599 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2600 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002601 value[0] = '\0';
2602 i=0;
2603 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002604 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002605 int avail = sizeof(value) - cursor;
2606 ret = snprintf(value + cursor, avail, "%s%d",
2607 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002608 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002609 if (ret < 0 || ret >= avail) {
2610 // if cursor is at the last element of the array
2611 // overwrite with \0 is duplicate work as
2612 // snprintf already put a \0 in place.
2613 // else
2614 // we had space to write the '|' at value[cursor]
2615 // (which will be overwritten) or no space to fill
2616 // the first element (=> cursor == 0)
2617 value[cursor] = '\0';
2618 break;
2619 }
2620 cursor += ret;
2621 ++i;
2622 }
2623 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2624 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002625 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002626 return ret >= 0;
2627}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002628
Haynes Mathew George569b7482017-05-08 14:44:27 -07002629static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2630{
2631 struct stream_out *out = (struct stream_out *)stream;
2632 struct str_parms *query = str_parms_create_str(keys);
2633 char *str;
2634 struct str_parms *reply = str_parms_create();
2635 bool replied = false;
2636 ALOGV("%s: enter: keys - %s", __func__, keys);
2637
2638 replied |= stream_get_parameter_channels(query, reply,
2639 &out->supported_channel_masks[0]);
2640 replied |= stream_get_parameter_formats(query, reply,
2641 &out->supported_formats[0]);
2642 replied |= stream_get_parameter_rates(query, reply,
2643 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002644 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002645 str = str_parms_to_str(reply);
2646 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002647 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002648 }
2649 str_parms_destroy(query);
2650 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002651 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002652 return str;
2653}
2654
2655static uint32_t out_get_latency(const struct audio_stream_out *stream)
2656{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002657 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002658 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002659 uint32_t latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002660
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002661 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2662 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002663 else if ((out->realtime) ||
2664 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002665 // since the buffer won't be filled up faster than realtime,
2666 // return a smaller number
2667 period_ms = (out->af_period_multiplier * out->config.period_size *
2668 1000) / (out->config.rate);
2669 hw_delay = platform_render_latency(out->usecase)/1000;
2670 return period_ms + hw_delay;
2671 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002672
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002673 latency = (out->config.period_count * out->config.period_size * 1000) /
2674 (out->config.rate);
2675
2676 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
2677 latency += audio_extn_a2dp_get_encoder_latency();
2678
2679 return latency;
2680}
2681
2682static int set_compr_volume(struct audio_stream_out *stream, float left,
2683 float right)
2684{
2685 struct stream_out *out = (struct stream_out *)stream;
2686 int volume[2];
2687 char mixer_ctl_name[128];
2688 struct audio_device *adev = out->dev;
2689 struct mixer_ctl *ctl;
2690 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2691 PCM_PLAYBACK);
2692
2693 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2694 "Compress Playback %d Volume", pcm_device_id);
2695 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2696 if (!ctl) {
2697 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2698 __func__, mixer_ctl_name);
2699 return -EINVAL;
2700 }
2701 ALOGV("%s: ctl for mixer cmd - %s, left %f, right %f",
2702 __func__, mixer_ctl_name, left, right);
2703 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2704 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2705 mixer_ctl_set_array(ctl, volume, sizeof(volume) / sizeof(volume[0]));
2706
2707 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002708}
2709
2710static int out_set_volume(struct audio_stream_out *stream, float left,
2711 float right)
2712{
Eric Laurenta9024de2013-04-04 09:19:12 -07002713 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002714 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002715
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002716 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002717 /* only take left channel into account: the API is for stereo anyway */
2718 out->muted = (left == 0.0f);
2719 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002720 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002721 pthread_mutex_lock(&out->compr_mute_lock);
2722 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
2723 if (!out->a2dp_compress_mute)
2724 ret = set_compr_volume(stream, left, right);
2725 out->volume_l = left;
2726 out->volume_r = right;
2727 pthread_mutex_unlock(&out->compr_mute_lock);
2728 return ret;
vivek mehtaa68fea62017-06-08 19:04:02 -07002729 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002730 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2731 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2732 if (!out->standby) {
2733 // if in standby, cached volume will be sent after stream is opened
2734 audio_extn_utils_send_app_type_gain(out->dev,
2735 out->app_type_cfg.app_type,
2736 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002737 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002738 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002739 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002740
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002741 return -ENOSYS;
2742}
2743
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002744// note: this call is safe only if the stream_cb is
2745// removed first in close_output_stream (as is done now).
2746static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2747{
2748 if (!stream || !parms)
2749 return;
2750
2751 struct stream_out *out = (struct stream_out *)stream;
2752 struct audio_device *adev = out->dev;
2753
2754 card_status_t status;
2755 int card;
2756 if (parse_snd_card_status(parms, &card, &status) < 0)
2757 return;
2758
2759 pthread_mutex_lock(&adev->lock);
2760 bool valid_cb = (card == adev->snd_card);
2761 pthread_mutex_unlock(&adev->lock);
2762
2763 if (!valid_cb)
2764 return;
2765
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002766 lock_output_stream(out);
2767 if (out->card_status != status)
2768 out->card_status = status;
2769 pthread_mutex_unlock(&out->lock);
2770
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002771 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2772 use_case_table[out->usecase],
2773 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2774
2775 if (status == CARD_STATUS_OFFLINE)
2776 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002777
2778 return;
2779}
2780
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002781#ifdef NO_AUDIO_OUT
2782static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002783 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002784{
2785 struct stream_out *out = (struct stream_out *)stream;
2786
2787 /* No Output device supported other than BT for playback.
2788 * Sleep for the amount of buffer duration
2789 */
Eric Laurenta1478072015-09-21 17:21:52 -07002790 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002791 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2792 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002793 out_get_sample_rate(&out->stream.common));
2794 pthread_mutex_unlock(&out->lock);
2795 return bytes;
2796}
2797#endif
2798
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002799static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2800 size_t bytes)
2801{
2802 struct stream_out *out = (struct stream_out *)stream;
2803 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002804 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002805 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002806
Eric Laurenta1478072015-09-21 17:21:52 -07002807 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002808 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07002809 const size_t frame_size = audio_stream_out_frame_size(stream);
2810 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002811
Eric Laurent0e46adf2016-12-16 12:49:24 -08002812 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2813 error_code = ERROR_CODE_WRITE;
2814 goto exit;
2815 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002816
2817 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2818 (audio_extn_a2dp_is_suspended())) {
2819 if (!(out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2820 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2821 ret = -EIO;
2822 goto exit;
2823 }
2824 }
2825 }
2826
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002827 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002828 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002829 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002830 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07002831
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002832 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002833 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002834 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07002835 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002836 goto exit;
2837 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002838
vivek mehta40125092017-08-21 18:48:51 -07002839 // after standby always force set last known cal step
2840 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
2841 ALOGD("%s: retry previous failed cal level set", __func__);
2842 send_gain_dep_calibration_l();
2843 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002844 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002845
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002846 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002847 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002848 if (out->send_new_metadata) {
2849 ALOGVV("send new gapless metadata");
2850 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2851 out->send_new_metadata = 0;
2852 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002853 unsigned int avail;
2854 struct timespec tstamp;
2855 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2856 /* Do not limit write size if the available frames count is unknown */
2857 if (ret != 0) {
2858 avail = bytes;
2859 }
2860 if (avail == 0) {
2861 ret = 0;
2862 } else {
2863 if (avail > bytes) {
2864 avail = bytes;
2865 }
2866 ret = compress_write(out->compr, buffer, avail);
2867 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2868 __func__, avail, ret);
2869 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002870
Eric Laurent6e895242013-09-05 16:10:57 -07002871 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002872 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2873 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002874 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002875 compress_start(out->compr);
2876 out->playback_started = 1;
2877 out->offload_state = OFFLOAD_STATE_PLAYING;
2878 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002879 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002880 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002881 } else {
2882 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002883 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002884 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002885 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002886 return ret;
2887 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002888 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002889 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07002890 size_t bytes_to_write = bytes;
2891
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002892 if (out->muted)
2893 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07002894 // FIXME: this can be removed once audio flinger mixer supports mono output
Nadav Bar3d72cfc2018-01-07 12:19:24 +02002895 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP || out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
Eric Laurentad2dde92017-09-20 18:27:31 -07002896 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
2897 int16_t *src = (int16_t *)buffer;
2898 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002899
Eric Laurentad2dde92017-09-20 18:27:31 -07002900 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
2901 out->format != AUDIO_FORMAT_PCM_16_BIT,
2902 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002903
Eric Laurentad2dde92017-09-20 18:27:31 -07002904 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
2905 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
2906 }
2907 bytes_to_write /= 2;
2908 }
2909 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes_to_write);
2910
Glenn Kasten5a59dff2018-02-22 08:05:35 -08002911 long ns = (frames * (int64_t) NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002912 request_out_focus(out, ns);
2913
2914 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2915 if (use_mmap)
Eric Laurentad2dde92017-09-20 18:27:31 -07002916 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002917 else
Eric Laurentad2dde92017-09-20 18:27:31 -07002918 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002919
Haynes Mathew George03c40102016-01-29 17:57:48 -08002920 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002921 } else {
2922 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002923 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002924 }
2925
2926exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002927 // For PCM we always consume the buffer and return #bytes regardless of ret.
2928 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07002929 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07002930 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002931 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07002932
Andy Hung7401c7c2016-09-21 12:41:21 -07002933 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07002934 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07002935 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2936 ALOGE_IF(out->pcm != NULL,
2937 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07002938 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002939 // usleep not guaranteed for values over 1 second but we don't limit here.
2940 }
2941 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002942
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002943 pthread_mutex_unlock(&out->lock);
2944
2945 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002946 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002947 if (sleeptime_us != 0)
2948 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002949 }
2950 return bytes;
2951}
2952
2953static int out_get_render_position(const struct audio_stream_out *stream,
2954 uint32_t *dsp_frames)
2955{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002956 struct stream_out *out = (struct stream_out *)stream;
2957 *dsp_frames = 0;
2958 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002959 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002960 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002961 unsigned long frames = 0;
2962 // TODO: check return value
2963 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2964 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002965 ALOGVV("%s rendered frames %d sample_rate %d",
2966 __func__, *dsp_frames, out->sample_rate);
2967 }
2968 pthread_mutex_unlock(&out->lock);
2969 return 0;
2970 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002971 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002972}
2973
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002974static int out_add_audio_effect(const struct audio_stream *stream __unused,
2975 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002976{
2977 return 0;
2978}
2979
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002980static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2981 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002982{
2983 return 0;
2984}
2985
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002986static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2987 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002988{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002989 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002990}
2991
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002992static int out_get_presentation_position(const struct audio_stream_out *stream,
2993 uint64_t *frames, struct timespec *timestamp)
2994{
2995 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002996 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07002997 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002998
Eric Laurenta1478072015-09-21 17:21:52 -07002999 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003000
Eric Laurent949a0892013-09-20 09:20:13 -07003001 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3002 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003003 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07003004 compress_get_tstamp(out->compr, &dsp_frames,
3005 &out->sample_rate);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003006 // Adjustment accounts for A2DP encoder latency with offload usecases
3007 // Note: Encoder latency is returned in ms.
3008 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3009 unsigned long offset =
3010 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3011 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
3012 }
Eric Laurent949a0892013-09-20 09:20:13 -07003013 ALOGVV("%s rendered frames %ld sample_rate %d",
3014 __func__, dsp_frames, out->sample_rate);
3015 *frames = dsp_frames;
3016 ret = 0;
3017 /* this is the best we can do */
3018 clock_gettime(CLOCK_MONOTONIC, timestamp);
3019 }
3020 } else {
3021 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07003022 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003023 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3024 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003025 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003026 // This adjustment accounts for buffering after app processor.
3027 // It is based on estimated DSP latency per use case, rather than exact.
3028 signed_frames -=
3029 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3030
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003031 // Adjustment accounts for A2DP encoder latency with non-offload usecases
3032 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3033 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3034 signed_frames -=
3035 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3036 }
3037
Eric Laurent949a0892013-09-20 09:20:13 -07003038 // It would be unusual for this value to be negative, but check just in case ...
3039 if (signed_frames >= 0) {
3040 *frames = signed_frames;
3041 ret = 0;
3042 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003043 }
3044 }
3045 }
3046
3047 pthread_mutex_unlock(&out->lock);
3048
3049 return ret;
3050}
3051
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003052static int out_set_callback(struct audio_stream_out *stream,
3053 stream_callback_t callback, void *cookie)
3054{
3055 struct stream_out *out = (struct stream_out *)stream;
3056
3057 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003058 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003059 out->offload_callback = callback;
3060 out->offload_cookie = cookie;
3061 pthread_mutex_unlock(&out->lock);
3062 return 0;
3063}
3064
3065static int out_pause(struct audio_stream_out* stream)
3066{
3067 struct stream_out *out = (struct stream_out *)stream;
3068 int status = -ENOSYS;
3069 ALOGV("%s", __func__);
3070 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003071 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003072 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
3073 status = compress_pause(out->compr);
3074 out->offload_state = OFFLOAD_STATE_PAUSED;
3075 }
3076 pthread_mutex_unlock(&out->lock);
3077 }
3078 return status;
3079}
3080
3081static int out_resume(struct audio_stream_out* stream)
3082{
3083 struct stream_out *out = (struct stream_out *)stream;
3084 int status = -ENOSYS;
3085 ALOGV("%s", __func__);
3086 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3087 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07003088 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003089 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
3090 status = compress_resume(out->compr);
3091 out->offload_state = OFFLOAD_STATE_PLAYING;
3092 }
3093 pthread_mutex_unlock(&out->lock);
3094 }
3095 return status;
3096}
3097
3098static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3099{
3100 struct stream_out *out = (struct stream_out *)stream;
3101 int status = -ENOSYS;
3102 ALOGV("%s", __func__);
3103 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003104 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003105 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3106 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3107 else
3108 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3109 pthread_mutex_unlock(&out->lock);
3110 }
3111 return status;
3112}
3113
3114static int out_flush(struct audio_stream_out* stream)
3115{
3116 struct stream_out *out = (struct stream_out *)stream;
3117 ALOGV("%s", __func__);
3118 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003119 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003120 stop_compressed_output_l(out);
3121 pthread_mutex_unlock(&out->lock);
3122 return 0;
3123 }
3124 return -ENOSYS;
3125}
3126
Eric Laurent0e46adf2016-12-16 12:49:24 -08003127static int out_stop(const struct audio_stream_out* stream)
3128{
3129 struct stream_out *out = (struct stream_out *)stream;
3130 struct audio_device *adev = out->dev;
3131 int ret = -ENOSYS;
3132
3133 ALOGV("%s", __func__);
3134 pthread_mutex_lock(&adev->lock);
3135 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3136 out->playback_started && out->pcm != NULL) {
3137 pcm_stop(out->pcm);
3138 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08003139 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003140 }
3141 pthread_mutex_unlock(&adev->lock);
3142 return ret;
3143}
3144
3145static int out_start(const struct audio_stream_out* stream)
3146{
3147 struct stream_out *out = (struct stream_out *)stream;
3148 struct audio_device *adev = out->dev;
3149 int ret = -ENOSYS;
3150
3151 ALOGV("%s", __func__);
3152 pthread_mutex_lock(&adev->lock);
3153 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3154 !out->playback_started && out->pcm != NULL) {
3155 ret = start_output_stream(out);
3156 if (ret == 0) {
3157 out->playback_started = true;
3158 }
3159 }
3160 pthread_mutex_unlock(&adev->lock);
3161 return ret;
3162}
3163
Phil Burkbc991042017-02-24 08:06:44 -08003164/*
3165 * Modify config->period_count based on min_size_frames
3166 */
3167static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
3168{
3169 int periodCountRequested = (min_size_frames + config->period_size - 1)
3170 / config->period_size;
3171 int periodCount = MMAP_PERIOD_COUNT_MIN;
3172
3173 ALOGV("%s original config.period_size = %d config.period_count = %d",
3174 __func__, config->period_size, config->period_count);
3175
3176 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
3177 periodCount *= 2;
3178 }
3179 config->period_count = periodCount;
3180
3181 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
3182}
3183
Eric Laurent0e46adf2016-12-16 12:49:24 -08003184static int out_create_mmap_buffer(const struct audio_stream_out *stream,
3185 int32_t min_size_frames,
3186 struct audio_mmap_buffer_info *info)
3187{
3188 struct stream_out *out = (struct stream_out *)stream;
3189 struct audio_device *adev = out->dev;
3190 int ret = 0;
3191 unsigned int offset1;
3192 unsigned int frames1;
3193 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003194 uint32_t mmap_size;
3195 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003196
3197 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003198 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003199 pthread_mutex_lock(&adev->lock);
3200
3201 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003202 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003203 ret = -EINVAL;
3204 goto exit;
3205 }
3206 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003207 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003208 ret = -ENOSYS;
3209 goto exit;
3210 }
3211 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3212 if (out->pcm_device_id < 0) {
3213 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3214 __func__, out->pcm_device_id, out->usecase);
3215 ret = -EINVAL;
3216 goto exit;
3217 }
Phil Burkbc991042017-02-24 08:06:44 -08003218
3219 adjust_mmap_period_count(&out->config, min_size_frames);
3220
Eric Laurent0e46adf2016-12-16 12:49:24 -08003221 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3222 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3223 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3224 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3225 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3226 step = "open";
3227 ret = -ENODEV;
3228 goto exit;
3229 }
3230 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3231 if (ret < 0) {
3232 step = "begin";
3233 goto exit;
3234 }
3235 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003236 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003237 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003238 ret = platform_get_mmap_data_fd(adev->platform,
3239 out->pcm_device_id, 0 /*playback*/,
3240 &info->shared_memory_fd,
3241 &mmap_size);
3242 if (ret < 0) {
3243 // Fall back to non exclusive mode
3244 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3245 } else {
3246 if (mmap_size < buffer_size) {
3247 step = "mmap";
3248 goto exit;
3249 }
3250 // FIXME: indicate exclusive mode support by returning a negative buffer size
3251 info->buffer_size_frames *= -1;
3252 }
3253 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003254
3255 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3256 if (ret < 0) {
3257 step = "commit";
3258 goto exit;
3259 }
Phil Burkbc991042017-02-24 08:06:44 -08003260
3261 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003262 ret = 0;
3263
3264 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3265 __func__, info->shared_memory_address, info->buffer_size_frames);
3266
3267exit:
3268 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003269 if (out->pcm == NULL) {
3270 ALOGE("%s: %s - %d", __func__, step, ret);
3271 } else {
3272 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003273 pcm_close(out->pcm);
3274 out->pcm = NULL;
3275 }
3276 }
3277 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003278 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003279 return ret;
3280}
3281
3282static int out_get_mmap_position(const struct audio_stream_out *stream,
3283 struct audio_mmap_position *position)
3284{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003285 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003286 struct stream_out *out = (struct stream_out *)stream;
3287 ALOGVV("%s", __func__);
3288 if (position == NULL) {
3289 return -EINVAL;
3290 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003291 lock_output_stream(out);
3292 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3293 out->pcm == NULL) {
3294 ret = -ENOSYS;
3295 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003296 }
3297
3298 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003299 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003300 if (ret < 0) {
3301 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003302 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003303 }
Andy Hungfc044e12017-03-20 09:24:22 -07003304 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003305exit:
3306 pthread_mutex_unlock(&out->lock);
3307 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003308}
3309
3310
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003311/** audio_stream_in implementation **/
3312static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3313{
3314 struct stream_in *in = (struct stream_in *)stream;
3315
3316 return in->config.rate;
3317}
3318
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003319static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003320{
3321 return -ENOSYS;
3322}
3323
3324static size_t in_get_buffer_size(const struct audio_stream *stream)
3325{
3326 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003327 return in->config.period_size * in->af_period_multiplier *
3328 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003329}
3330
3331static uint32_t in_get_channels(const struct audio_stream *stream)
3332{
3333 struct stream_in *in = (struct stream_in *)stream;
3334
3335 return in->channel_mask;
3336}
3337
vivek mehta4ed66e62016-04-15 23:33:34 -07003338static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003339{
vivek mehta4ed66e62016-04-15 23:33:34 -07003340 struct stream_in *in = (struct stream_in *)stream;
3341 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003342}
3343
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003344static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003345{
3346 return -ENOSYS;
3347}
3348
3349static int in_standby(struct audio_stream *stream)
3350{
3351 struct stream_in *in = (struct stream_in *)stream;
3352 struct audio_device *adev = in->dev;
3353 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003354 bool do_stop = true;
3355
Eric Laurent994a6932013-07-17 11:51:42 -07003356 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003357
3358 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003359
3360 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003361 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003362 audio_extn_sound_trigger_stop_lab(in);
3363 in->standby = true;
3364 }
3365
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003366 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003367 if (adev->adm_deregister_stream)
3368 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3369
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003370 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003371 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003372 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003373 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003374 in->capture_started = false;
3375 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003376 if (in->pcm) {
3377 pcm_close(in->pcm);
3378 in->pcm = NULL;
3379 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003380 adev->enable_voicerx = false;
3381 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003382 if (do_stop) {
3383 status = stop_input_stream(in);
3384 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003385 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003386 }
3387 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003388 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003389 return status;
3390}
3391
Andy Hungd13f0d32017-06-12 13:58:37 -07003392static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003393{
Andy Hungd13f0d32017-06-12 13:58:37 -07003394 struct stream_in *in = (struct stream_in *)stream;
3395
3396 // We try to get the lock for consistency,
3397 // but it isn't necessary for these variables.
3398 // If we're not in standby, we may be blocked on a read.
3399 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3400 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3401 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3402 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3403
3404 if (locked) {
3405 pthread_mutex_unlock(&in->lock);
3406 }
3407
3408 // dump error info
3409 (void)error_log_dump(
3410 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003411 return 0;
3412}
3413
3414static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3415{
3416 struct stream_in *in = (struct stream_in *)stream;
3417 struct audio_device *adev = in->dev;
3418 struct str_parms *parms;
3419 char *str;
3420 char value[32];
3421 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003422 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003423
Eric Laurent994a6932013-07-17 11:51:42 -07003424 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003425 parms = str_parms_create_str(kvpairs);
3426
3427 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3428
Eric Laurenta1478072015-09-21 17:21:52 -07003429 lock_input_stream(in);
3430
Eric Laurent150dbfe2013-02-27 14:31:02 -08003431 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003432 if (ret >= 0) {
3433 val = atoi(value);
3434 /* no audio source uses val == 0 */
3435 if ((in->source != val) && (val != 0)) {
3436 in->source = val;
3437 }
3438 }
3439
3440 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003441
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003442 if (ret >= 0) {
3443 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003444 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003445
3446 // Workaround: If routing to an non existing usb device, fail gracefully
3447 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003448 int card;
3449 if (audio_is_usb_in_device(val) &&
3450 (card = get_alive_usb_card(parms)) >= 0) {
3451
3452 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003453 status = -ENOSYS;
3454 } else {
3455
3456 in->device = val;
3457 /* If recording is in progress, change the tx device to new device */
3458 if (!in->standby) {
3459 ALOGV("update input routing change");
3460 // inform adm before actual routing to prevent glitches.
3461 if (adev->adm_on_routing_change) {
3462 adev->adm_on_routing_change(adev->adm_data,
3463 in->capture_handle);
3464 }
3465 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003466 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003467 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003468 }
3469 }
3470
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003471 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003472 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003473
3474 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003475 ALOGV("%s: exit: status(%d)", __func__, status);
3476 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003477}
3478
Haynes Mathew George569b7482017-05-08 14:44:27 -07003479static char* in_get_parameters(const struct audio_stream *stream,
3480 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003481{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003482 struct stream_in *in = (struct stream_in *)stream;
3483 struct str_parms *query = str_parms_create_str(keys);
3484 char *str;
3485 struct str_parms *reply = str_parms_create();
3486 bool replied = false;
3487
3488 ALOGV("%s: enter: keys - %s", __func__, keys);
3489 replied |= stream_get_parameter_channels(query, reply,
3490 &in->supported_channel_masks[0]);
3491 replied |= stream_get_parameter_formats(query, reply,
3492 &in->supported_formats[0]);
3493 replied |= stream_get_parameter_rates(query, reply,
3494 &in->supported_sample_rates[0]);
3495 if (replied) {
3496 str = str_parms_to_str(reply);
3497 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003498 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003499 }
3500 str_parms_destroy(query);
3501 str_parms_destroy(reply);
3502 ALOGV("%s: exit: returns - %s", __func__, str);
3503 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003504}
3505
Eric Laurent51f3c662018-04-10 18:21:34 -07003506static int in_set_gain(struct audio_stream_in *stream, float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003507{
Eric Laurent51f3c662018-04-10 18:21:34 -07003508 struct stream_in *in = (struct stream_in *)stream;
3509 char mixer_ctl_name[128];
3510 struct mixer_ctl *ctl;
3511 int ctl_value;
3512
3513 ALOGV("%s: gain %f", __func__, gain);
3514
3515 if (stream == NULL)
3516 return -EINVAL;
3517
3518 /* in_set_gain() only used to silence MMAP capture for now */
3519 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
3520 return -ENOSYS;
3521
3522 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
3523
3524 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
3525 if (!ctl) {
3526 ALOGW("%s: Could not get ctl for mixer cmd - %s",
3527 __func__, mixer_ctl_name);
3528 return -ENOSYS;
3529 }
3530
3531 if (gain < RECORD_GAIN_MIN)
3532 gain = RECORD_GAIN_MIN;
3533 else if (gain > RECORD_GAIN_MAX)
3534 gain = RECORD_GAIN_MAX;
3535 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
3536
3537 mixer_ctl_set_value(ctl, 0, ctl_value);
3538 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003539}
3540
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003541static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3542{
3543 if (!stream || !parms)
3544 return;
3545
3546 struct stream_in *in = (struct stream_in *)stream;
3547 struct audio_device *adev = in->dev;
3548
3549 card_status_t status;
3550 int card;
3551 if (parse_snd_card_status(parms, &card, &status) < 0)
3552 return;
3553
3554 pthread_mutex_lock(&adev->lock);
3555 bool valid_cb = (card == adev->snd_card);
3556 pthread_mutex_unlock(&adev->lock);
3557
3558 if (!valid_cb)
3559 return;
3560
3561 lock_input_stream(in);
3562 if (in->card_status != status)
3563 in->card_status = status;
3564 pthread_mutex_unlock(&in->lock);
3565
3566 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3567 use_case_table[in->usecase],
3568 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3569
3570 // a better solution would be to report error back to AF and let
3571 // it put the stream to standby
3572 if (status == CARD_STATUS_OFFLINE)
3573 in_standby(&in->stream.common);
3574
3575 return;
3576}
3577
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003578static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3579 size_t bytes)
3580{
3581 struct stream_in *in = (struct stream_in *)stream;
3582 struct audio_device *adev = in->dev;
3583 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003584 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003585 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003586
Eric Laurenta1478072015-09-21 17:21:52 -07003587 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003588 const size_t frame_size = audio_stream_in_frame_size(stream);
3589 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003590
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003591 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003592 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003593 /* Read from sound trigger HAL */
3594 audio_extn_sound_trigger_read(in, buffer, bytes);
3595 pthread_mutex_unlock(&in->lock);
3596 return bytes;
3597 }
3598
Eric Laurent0e46adf2016-12-16 12:49:24 -08003599 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3600 ret = -ENOSYS;
3601 goto exit;
3602 }
3603
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003604 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003605 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003606 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003607 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003608 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003609 goto exit;
3610 }
3611 in->standby = 0;
3612 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003613
Andy Hungd13f0d32017-06-12 13:58:37 -07003614 // errors that occur here are read errors.
3615 error_code = ERROR_CODE_READ;
3616
Haynes Mathew George03c40102016-01-29 17:57:48 -08003617 //what's the duration requested by the client?
3618 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3619 in->config.rate;
3620 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003621
Haynes Mathew George03c40102016-01-29 17:57:48 -08003622 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003623 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003624 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003625 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003626 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003627 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003628 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003629 if (ret < 0) {
3630 ALOGE("Failed to read w/err %s", strerror(errno));
3631 ret = -errno;
3632 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003633 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3634 if (bytes % 4 == 0) {
3635 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3636 int_buf_stream = buffer;
3637 for (size_t itt=0; itt < bytes/4 ; itt++) {
3638 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003639 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003640 } else {
3641 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3642 ret = -EINVAL;
3643 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003644 }
3645 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003646 }
3647
Haynes Mathew George03c40102016-01-29 17:57:48 -08003648 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003649
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003650 /*
3651 * Instead of writing zeroes here, we could trust the hardware
3652 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003653 * 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 -08003654 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08003655 if (ret == 0 && adev->mic_muted &&
3656 !voice_is_in_call_rec_stream(in) &&
3657 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003658 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07003659 in->frames_muted += frames;
3660 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003661
3662exit:
3663 pthread_mutex_unlock(&in->lock);
3664
3665 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07003666 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003667 in_standby(&in->stream.common);
3668 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003669 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003670 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07003671 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08003672 }
3673 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003674 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003675 }
3676 return bytes;
3677}
3678
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003679static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003680{
3681 return 0;
3682}
3683
Andy Hung6ebe5962016-01-15 17:46:57 -08003684static int in_get_capture_position(const struct audio_stream_in *stream,
3685 int64_t *frames, int64_t *time)
3686{
3687 if (stream == NULL || frames == NULL || time == NULL) {
3688 return -EINVAL;
3689 }
3690 struct stream_in *in = (struct stream_in *)stream;
3691 int ret = -ENOSYS;
3692
3693 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003694 // note: ST sessions do not close the alsa pcm driver synchronously
3695 // on standby. Therefore, we may return an error even though the
3696 // pcm stream is still opened.
3697 if (in->standby) {
3698 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
3699 "%s stream in standby but pcm not NULL for non ST session", __func__);
3700 goto exit;
3701 }
Andy Hung6ebe5962016-01-15 17:46:57 -08003702 if (in->pcm) {
3703 struct timespec timestamp;
3704 unsigned int avail;
3705 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3706 *frames = in->frames_read + avail;
3707 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3708 ret = 0;
3709 }
3710 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003711exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08003712 pthread_mutex_unlock(&in->lock);
3713 return ret;
3714}
3715
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003716static int add_remove_audio_effect(const struct audio_stream *stream,
3717 effect_handle_t effect,
3718 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003719{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003720 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003721 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003722 int status = 0;
3723 effect_descriptor_t desc;
3724
3725 status = (*effect)->get_descriptor(effect, &desc);
3726 if (status != 0)
3727 return status;
3728
Eric Laurenta1478072015-09-21 17:21:52 -07003729 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003730 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003731 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003732 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003733 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003734 in->enable_aec != enable &&
3735 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3736 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003737 if (!enable)
3738 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003739 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3740 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3741 adev->enable_voicerx = enable;
3742 struct audio_usecase *usecase;
3743 struct listnode *node;
3744 list_for_each(node, &adev->usecase_list) {
3745 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07003746 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07003747 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05003748 }
3749 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003750 if (!in->standby)
3751 select_devices(in->dev, in->usecase);
3752 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003753 if (in->enable_ns != enable &&
3754 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3755 in->enable_ns = enable;
3756 if (!in->standby)
3757 select_devices(in->dev, in->usecase);
3758 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003759 pthread_mutex_unlock(&in->dev->lock);
3760 pthread_mutex_unlock(&in->lock);
3761
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003762 return 0;
3763}
3764
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003765static int in_add_audio_effect(const struct audio_stream *stream,
3766 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003767{
Eric Laurent994a6932013-07-17 11:51:42 -07003768 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003769 return add_remove_audio_effect(stream, effect, true);
3770}
3771
3772static int in_remove_audio_effect(const struct audio_stream *stream,
3773 effect_handle_t effect)
3774{
Eric Laurent994a6932013-07-17 11:51:42 -07003775 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003776 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003777}
3778
Eric Laurent0e46adf2016-12-16 12:49:24 -08003779static int in_stop(const struct audio_stream_in* stream)
3780{
3781 struct stream_in *in = (struct stream_in *)stream;
3782 struct audio_device *adev = in->dev;
3783
3784 int ret = -ENOSYS;
3785 ALOGV("%s", __func__);
3786 pthread_mutex_lock(&adev->lock);
3787 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3788 in->capture_started && in->pcm != NULL) {
3789 pcm_stop(in->pcm);
3790 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003791 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003792 }
3793 pthread_mutex_unlock(&adev->lock);
3794 return ret;
3795}
3796
3797static int in_start(const struct audio_stream_in* stream)
3798{
3799 struct stream_in *in = (struct stream_in *)stream;
3800 struct audio_device *adev = in->dev;
3801 int ret = -ENOSYS;
3802
3803 ALOGV("%s in %p", __func__, in);
3804 pthread_mutex_lock(&adev->lock);
3805 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3806 !in->capture_started && in->pcm != NULL) {
3807 if (!in->capture_started) {
3808 ret = start_input_stream(in);
3809 if (ret == 0) {
3810 in->capture_started = true;
3811 }
3812 }
3813 }
3814 pthread_mutex_unlock(&adev->lock);
3815 return ret;
3816}
3817
3818static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3819 int32_t min_size_frames,
3820 struct audio_mmap_buffer_info *info)
3821{
3822 struct stream_in *in = (struct stream_in *)stream;
3823 struct audio_device *adev = in->dev;
3824 int ret = 0;
3825 unsigned int offset1;
3826 unsigned int frames1;
3827 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003828 uint32_t mmap_size;
3829 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003830
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003831 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003832 pthread_mutex_lock(&adev->lock);
3833 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003834
Eric Laurent0e46adf2016-12-16 12:49:24 -08003835 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003836 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003837 ret = -EINVAL;
3838 goto exit;
3839 }
3840 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003841 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003842 ALOGV("%s in %p", __func__, in);
3843 ret = -ENOSYS;
3844 goto exit;
3845 }
3846 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3847 if (in->pcm_device_id < 0) {
3848 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3849 __func__, in->pcm_device_id, in->usecase);
3850 ret = -EINVAL;
3851 goto exit;
3852 }
Phil Burkbc991042017-02-24 08:06:44 -08003853
3854 adjust_mmap_period_count(&in->config, min_size_frames);
3855
Eric Laurent0e46adf2016-12-16 12:49:24 -08003856 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3857 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3858 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3859 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3860 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3861 step = "open";
3862 ret = -ENODEV;
3863 goto exit;
3864 }
3865
3866 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3867 if (ret < 0) {
3868 step = "begin";
3869 goto exit;
3870 }
3871 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003872 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003873 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003874 ret = platform_get_mmap_data_fd(adev->platform,
3875 in->pcm_device_id, 1 /*capture*/,
3876 &info->shared_memory_fd,
3877 &mmap_size);
3878 if (ret < 0) {
3879 // Fall back to non exclusive mode
3880 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3881 } else {
3882 if (mmap_size < buffer_size) {
3883 step = "mmap";
3884 goto exit;
3885 }
3886 // FIXME: indicate exclusive mode support by returning a negative buffer size
3887 info->buffer_size_frames *= -1;
3888 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08003889
Haynes Mathew George96483a22017-03-28 14:52:47 -07003890 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003891
3892 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3893 if (ret < 0) {
3894 step = "commit";
3895 goto exit;
3896 }
3897
Phil Burkbc991042017-02-24 08:06:44 -08003898 in->standby = false;
3899 ret = 0;
3900
Eric Laurent0e46adf2016-12-16 12:49:24 -08003901 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3902 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003903
3904exit:
3905 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003906 if (in->pcm == NULL) {
3907 ALOGE("%s: %s - %d", __func__, step, ret);
3908 } else {
3909 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003910 pcm_close(in->pcm);
3911 in->pcm = NULL;
3912 }
3913 }
3914 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003915 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003916 return ret;
3917}
3918
3919static int in_get_mmap_position(const struct audio_stream_in *stream,
3920 struct audio_mmap_position *position)
3921{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003922 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003923 struct stream_in *in = (struct stream_in *)stream;
3924 ALOGVV("%s", __func__);
3925 if (position == NULL) {
3926 return -EINVAL;
3927 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003928 lock_input_stream(in);
3929 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
3930 in->pcm == NULL) {
3931 ret = -ENOSYS;
3932 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003933 }
3934 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003935 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003936 if (ret < 0) {
3937 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003938 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003939 }
Andy Hungfc044e12017-03-20 09:24:22 -07003940 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003941exit:
3942 pthread_mutex_unlock(&in->lock);
3943 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003944}
3945
jiabin8962a4d2018-03-19 18:21:24 -07003946static int in_get_active_microphones(const struct audio_stream_in *stream,
3947 struct audio_microphone_characteristic_t *mic_array,
3948 size_t *mic_count) {
3949 struct stream_in *in = (struct stream_in *)stream;
3950 struct audio_device *adev = in->dev;
3951 ALOGVV("%s", __func__);
3952
3953 lock_input_stream(in);
3954 pthread_mutex_lock(&adev->lock);
3955 int ret = platform_get_active_microphones(adev->platform, in->device,
3956 audio_channel_count_from_in_mask(in->channel_mask),
3957 in->source, in->usecase, mic_array, mic_count);
3958 pthread_mutex_unlock(&adev->lock);
3959 pthread_mutex_unlock(&in->lock);
3960
3961 return ret;
3962}
3963
3964static int adev_get_microphones(const struct audio_hw_device *dev,
3965 struct audio_microphone_characteristic_t *mic_array,
3966 size_t *mic_count) {
3967 struct audio_device *adev = (struct audio_device *)dev;
3968 ALOGVV("%s", __func__);
3969
3970 pthread_mutex_lock(&adev->lock);
3971 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
3972 pthread_mutex_unlock(&adev->lock);
3973
3974 return ret;
3975}
Eric Laurent0e46adf2016-12-16 12:49:24 -08003976
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003977static int adev_open_output_stream(struct audio_hw_device *dev,
3978 audio_io_handle_t handle,
3979 audio_devices_t devices,
3980 audio_output_flags_t flags,
3981 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003982 struct audio_stream_out **stream_out,
3983 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003984{
3985 struct audio_device *adev = (struct audio_device *)dev;
3986 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003987 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003988 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
3989 bool is_usb_dev = audio_is_usb_out_device(devices) &&
3990 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003991
Andy Hungd9653bd2017-08-01 19:31:39 -07003992 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
3993 return -ENOSYS;
3994 }
3995
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003996 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
3997 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003998 *stream_out = NULL;
3999 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4000
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004001 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
4002
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004003 if (devices == AUDIO_DEVICE_NONE)
4004 devices = AUDIO_DEVICE_OUT_SPEAKER;
4005
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004006 out->flags = flags;
4007 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004008 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004009 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07004010 out->handle = handle;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004011 out->a2dp_compress_mute = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004012
4013 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004014 if ((is_hdmi || is_usb_dev) &&
4015 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
4016 (flags == AUDIO_OUTPUT_FLAG_NONE ||
4017 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Eric Laurentab805ee2018-03-30 12:20:38 -07004018 audio_format_t req_format = config->format;
4019 audio_channel_mask_t req_channel_mask = config->channel_mask;
4020 uint32_t req_sample_rate = config->sample_rate;
4021
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004022 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004023 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004024 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004025 if (config->sample_rate == 0)
4026 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Eric Laurentab805ee2018-03-30 12:20:38 -07004027 if (config->channel_mask == AUDIO_CHANNEL_NONE)
Haynes Mathew George569b7482017-05-08 14:44:27 -07004028 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
4029 if (config->format == AUDIO_FORMAT_DEFAULT)
4030 config->format = AUDIO_FORMAT_PCM_16_BIT;
4031 } else if (is_usb_dev) {
4032 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
4033 &config->format,
4034 &out->supported_formats[0],
4035 MAX_SUPPORTED_FORMATS,
4036 &config->channel_mask,
4037 &out->supported_channel_masks[0],
4038 MAX_SUPPORTED_CHANNEL_MASKS,
4039 &config->sample_rate,
4040 &out->supported_sample_rates[0],
4041 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004042 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004043 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004044 pthread_mutex_unlock(&adev->lock);
Eric Laurentab805ee2018-03-30 12:20:38 -07004045 if (ret != 0) {
4046 // For MMAP NO IRQ, allow conversions in ADSP
4047 if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
4048 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004049
Eric Laurentab805ee2018-03-30 12:20:38 -07004050 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
4051 config->sample_rate = req_sample_rate;
4052 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
4053 config->channel_mask = req_channel_mask;
4054 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
4055 config->format = req_format;
4056 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004057
Haynes Mathew George569b7482017-05-08 14:44:27 -07004058 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004059 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004060 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004061 if (is_hdmi) {
4062 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4063 out->config = pcm_config_hdmi_multi;
4064 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
4065 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4066 out->config = pcm_config_mmap_playback;
4067 out->stream.start = out_start;
4068 out->stream.stop = out_stop;
4069 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4070 out->stream.get_mmap_position = out_get_mmap_position;
4071 } else {
4072 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4073 out->config = pcm_config_hifi;
4074 }
4075
4076 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004077 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004078 if (is_hdmi) {
4079 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
4080 audio_bytes_per_sample(out->format));
4081 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004082 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004083 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07004084 pthread_mutex_lock(&adev->lock);
4085 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4086 pthread_mutex_unlock(&adev->lock);
4087
4088 // reject offload during card offline to allow
4089 // fallback to s/w paths
4090 if (offline) {
4091 ret = -ENODEV;
4092 goto error_open;
4093 }
4094
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004095 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4096 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4097 ALOGE("%s: Unsupported Offload information", __func__);
4098 ret = -EINVAL;
4099 goto error_open;
4100 }
4101 if (!is_supported_format(config->offload_info.format)) {
4102 ALOGE("%s: Unsupported audio format", __func__);
4103 ret = -EINVAL;
4104 goto error_open;
4105 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004106 out->sample_rate = config->offload_info.sample_rate;
4107 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
4108 out->channel_mask = config->offload_info.channel_mask;
4109 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
4110 out->channel_mask = config->channel_mask;
4111 else
4112 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4113
4114 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004115
4116 out->compr_config.codec = (struct snd_codec *)
4117 calloc(1, sizeof(struct snd_codec));
4118
4119 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004120
4121 out->stream.set_callback = out_set_callback;
4122 out->stream.pause = out_pause;
4123 out->stream.resume = out_resume;
4124 out->stream.drain = out_drain;
4125 out->stream.flush = out_flush;
4126
4127 out->compr_config.codec->id =
4128 get_snd_codec_id(config->offload_info.format);
4129 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
4130 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004131 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004132 out->compr_config.codec->bit_rate =
4133 config->offload_info.bit_rate;
4134 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004135 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004136 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
4137
4138 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4139 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004140
4141 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004142 create_offload_callback_thread(out);
4143 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4144 __func__, config->offload_info.version,
4145 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02004146 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4147 switch (config->sample_rate) {
4148 case 0:
4149 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4150 break;
4151 case 8000:
4152 case 16000:
4153 case 48000:
4154 out->sample_rate = config->sample_rate;
4155 break;
4156 default:
4157 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
4158 config->sample_rate);
4159 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4160 ret = -EINVAL;
4161 goto error_open;
4162 }
4163 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4164 switch (config->channel_mask) {
4165 case AUDIO_CHANNEL_NONE:
4166 case AUDIO_CHANNEL_OUT_STEREO:
4167 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4168 break;
4169 default:
4170 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
4171 config->channel_mask);
4172 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4173 ret = -EINVAL;
4174 goto error_open;
4175 }
4176 switch (config->format) {
4177 case AUDIO_FORMAT_DEFAULT:
4178 case AUDIO_FORMAT_PCM_16_BIT:
4179 out->format = AUDIO_FORMAT_PCM_16_BIT;
4180 break;
4181 default:
4182 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
4183 config->format);
4184 config->format = AUDIO_FORMAT_PCM_16_BIT;
4185 ret = -EINVAL;
4186 goto error_open;
4187 }
4188
4189 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004190 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004191 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004192 case 0:
4193 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
4194 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07004195 case 8000:
4196 case 16000:
4197 case 48000:
4198 out->sample_rate = config->sample_rate;
4199 break;
4200 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004201 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
4202 config->sample_rate);
4203 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4204 ret = -EINVAL;
4205 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004206 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004207 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4208 switch (config->channel_mask) {
4209 case AUDIO_CHANNEL_NONE:
4210 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4211 break;
4212 case AUDIO_CHANNEL_OUT_STEREO:
4213 out->channel_mask = config->channel_mask;
4214 break;
4215 default:
4216 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
4217 config->channel_mask);
4218 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4219 ret = -EINVAL;
4220 break;
4221 }
4222 switch (config->format) {
4223 case AUDIO_FORMAT_DEFAULT:
4224 out->format = AUDIO_FORMAT_PCM_16_BIT;
4225 break;
4226 case AUDIO_FORMAT_PCM_16_BIT:
4227 out->format = config->format;
4228 break;
4229 default:
4230 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
4231 config->format);
4232 config->format = AUDIO_FORMAT_PCM_16_BIT;
4233 ret = -EINVAL;
4234 break;
4235 }
4236 if (ret != 0)
4237 goto error_open;
4238
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004239 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4240 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004241 out->config.rate = out->sample_rate;
4242 out->config.channels =
4243 audio_channel_count_from_out_mask(out->channel_mask);
4244 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004245 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004246 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
4247 switch (config->sample_rate) {
4248 case 0:
4249 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4250 break;
4251 case 8000:
4252 case 16000:
4253 case 32000:
4254 case 48000:
4255 out->sample_rate = config->sample_rate;
4256 break;
4257 default:
4258 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
4259 config->sample_rate);
4260 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4261 ret = -EINVAL;
4262 break;
4263 }
Eric Laurentad2dde92017-09-20 18:27:31 -07004264 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004265 switch (config->channel_mask) {
4266 case AUDIO_CHANNEL_NONE:
4267 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4268 break;
4269 case AUDIO_CHANNEL_OUT_STEREO:
4270 out->channel_mask = config->channel_mask;
4271 break;
4272 default:
4273 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
4274 config->channel_mask);
4275 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4276 ret = -EINVAL;
4277 break;
4278 }
4279 switch (config->format) {
4280 case AUDIO_FORMAT_DEFAULT:
4281 out->format = AUDIO_FORMAT_PCM_16_BIT;
4282 break;
4283 case AUDIO_FORMAT_PCM_16_BIT:
4284 out->format = config->format;
4285 break;
4286 default:
4287 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
4288 config->format);
4289 config->format = AUDIO_FORMAT_PCM_16_BIT;
4290 ret = -EINVAL;
4291 break;
4292 }
4293 if (ret != 0)
4294 goto error_open;
4295
vivek mehtaa68fea62017-06-08 19:04:02 -07004296 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07004297 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4298 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004299 out->config.rate = out->sample_rate;
4300 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07004301 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004302 out->sample_rate,
4303 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07004304 out->config.channels,
4305 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004306 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07004307 out->config.period_size = buffer_size / frame_size;
4308 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
4309 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004310 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004311 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07004312 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4313 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004314 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07004315 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
4316 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004317 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07004318 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004319 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004320 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004321 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004322 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4323 out->config = pcm_config_mmap_playback;
4324 out->stream.start = out_start;
4325 out->stream.stop = out_stop;
4326 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4327 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004328 } else {
4329 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4330 out->config = pcm_config_low_latency;
4331 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004332
4333 if (config->sample_rate == 0) {
4334 out->sample_rate = out->config.rate;
4335 } else {
4336 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004337 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004338 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
4339 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
4340 } else {
4341 out->channel_mask = config->channel_mask;
4342 }
4343 if (config->format == AUDIO_FORMAT_DEFAULT)
4344 out->format = audio_format_from_pcm_format(out->config.format);
4345 else if (!audio_is_linear_pcm(config->format)) {
4346 config->format = AUDIO_FORMAT_PCM_16_BIT;
4347 ret = -EINVAL;
4348 goto error_open;
4349 } else {
4350 out->format = config->format;
4351 }
4352
4353 out->config.rate = out->sample_rate;
4354 out->config.channels =
4355 audio_channel_count_from_out_mask(out->channel_mask);
4356 if (out->format != audio_format_from_pcm_format(out->config.format)) {
4357 out->config.format = pcm_format_from_audio_format(out->format);
4358 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004359 }
Kevin Rocard50eff892017-05-02 16:52:05 -07004360
4361 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
4362 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004363 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004364 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
4365 __func__, config->sample_rate, config->format, config->channel_mask);
4366 config->sample_rate = out->sample_rate;
4367 config->format = out->format;
4368 config->channel_mask = out->channel_mask;
4369 ret = -EINVAL;
4370 goto error_open;
4371 }
4372
Andy Hung6fcba9c2014-03-18 11:53:32 -07004373 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
4374 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004375
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004376 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004377 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004378 adev->primary_output = out;
4379 else {
4380 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004381 ret = -EEXIST;
4382 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004383 }
4384 }
4385
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004386 /* Check if this usecase is already existing */
4387 pthread_mutex_lock(&adev->lock);
4388 if (get_usecase_from_list(adev, out->usecase) != NULL) {
4389 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004390 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004391 ret = -EEXIST;
4392 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004393 }
4394 pthread_mutex_unlock(&adev->lock);
4395
4396 out->stream.common.get_sample_rate = out_get_sample_rate;
4397 out->stream.common.set_sample_rate = out_set_sample_rate;
4398 out->stream.common.get_buffer_size = out_get_buffer_size;
4399 out->stream.common.get_channels = out_get_channels;
4400 out->stream.common.get_format = out_get_format;
4401 out->stream.common.set_format = out_set_format;
4402 out->stream.common.standby = out_standby;
4403 out->stream.common.dump = out_dump;
4404 out->stream.common.set_parameters = out_set_parameters;
4405 out->stream.common.get_parameters = out_get_parameters;
4406 out->stream.common.add_audio_effect = out_add_audio_effect;
4407 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4408 out->stream.get_latency = out_get_latency;
4409 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004410#ifdef NO_AUDIO_OUT
4411 out->stream.write = out_write_for_no_output;
4412#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004413 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004414#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004415 out->stream.get_render_position = out_get_render_position;
4416 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004417 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004418
Eric Laurent0e46adf2016-12-16 12:49:24 -08004419 if (out->realtime)
4420 out->af_period_multiplier = af_period_multiplier;
4421 else
4422 out->af_period_multiplier = 1;
4423
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004424 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004425 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004426 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004427
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004428 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004429 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004430 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4431
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004432 config->format = out->stream.common.get_format(&out->stream.common);
4433 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4434 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4435
Andy Hunga452b0a2017-03-15 14:51:15 -07004436 out->error_log = error_log_create(
4437 ERROR_LOG_ENTRIES,
4438 1000000000 /* aggregate consecutive identical errors within one second in ns */);
4439
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004440 /*
4441 By locking output stream before registering, we allow the callback
4442 to update stream's state only after stream's initial state is set to
4443 adev state.
4444 */
4445 lock_output_stream(out);
4446 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4447 pthread_mutex_lock(&adev->lock);
4448 out->card_status = adev->card_status;
4449 pthread_mutex_unlock(&adev->lock);
4450 pthread_mutex_unlock(&out->lock);
4451
vivek mehta4a824772017-06-08 19:05:49 -07004452 stream_app_type_cfg_init(&out->app_type_cfg);
4453
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004454 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004455
Eric Laurent994a6932013-07-17 11:51:42 -07004456 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004457 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004458
4459error_open:
4460 free(out);
4461 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07004462 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004463 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004464}
4465
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004466static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004467 struct audio_stream_out *stream)
4468{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004469 struct stream_out *out = (struct stream_out *)stream;
4470 struct audio_device *adev = out->dev;
4471
Eric Laurent994a6932013-07-17 11:51:42 -07004472 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004473
4474 // must deregister from sndmonitor first to prevent races
4475 // between the callback and close_stream
4476 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004477 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004478 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
4479 destroy_offload_callback_thread(out);
4480
4481 if (out->compr_config.codec != NULL)
4482 free(out->compr_config.codec);
4483 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004484
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004485 out->a2dp_compress_mute = false;
4486
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004487 if (adev->voice_tx_output == out)
4488 adev->voice_tx_output = NULL;
4489
Andy Hunga452b0a2017-03-15 14:51:15 -07004490 error_log_destroy(out->error_log);
4491 out->error_log = NULL;
4492
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004493 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004494 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004495 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004496 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004497 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004498}
4499
4500static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4501{
4502 struct audio_device *adev = (struct audio_device *)dev;
4503 struct str_parms *parms;
4504 char *str;
4505 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004506 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004507 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07004508 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004509
Joe Onorato188b6222016-03-01 11:02:27 -08004510 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004511
4512 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004513
4514 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004515 status = voice_set_parameters(adev, parms);
4516 if (status != 0) {
4517 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004518 }
4519
4520 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4521 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07004522 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004523 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4524 adev->bluetooth_nrec = true;
4525 else
4526 adev->bluetooth_nrec = false;
4527 }
4528
4529 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4530 if (ret >= 0) {
4531 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4532 adev->screen_off = false;
4533 else
4534 adev->screen_off = true;
4535 }
4536
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004537 ret = str_parms_get_int(parms, "rotation", &val);
4538 if (ret >= 0) {
4539 bool reverse_speakers = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004540 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004541 // FIXME: note that the code below assumes that the speakers are in the correct placement
4542 // relative to the user when the device is rotated 90deg from its default rotation. This
4543 // assumption is device-specific, not platform-specific like this code.
4544 case 270:
4545 reverse_speakers = true;
4546 break;
4547 case 0:
4548 case 90:
4549 case 180:
4550 break;
4551 default:
4552 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07004553 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004554 }
Eric Laurent03f09432014-03-25 18:09:11 -07004555 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004556 // check and set swap
4557 // - check if orientation changed and speaker active
4558 // - set rotation and cache the rotation value
4559 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004560 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004561 }
4562
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004563 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4564 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004565 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004566 }
4567
David Linee3fe402017-03-13 10:00:42 -07004568 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4569 if (ret >= 0) {
4570 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004571 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004572 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4573 if (ret >= 0) {
4574 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004575 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004576 }
Eric Laurent99dab492017-06-17 15:19:08 -07004577 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004578 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4579 if (ret >= 0) {
4580 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004581 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004582 }
4583 }
4584 }
4585
4586 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4587 if (ret >= 0) {
4588 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004589 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004590 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4591 if (ret >= 0) {
4592 const int card = atoi(value);
4593
Eric Laurent99dab492017-06-17 15:19:08 -07004594 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004595 }
Eric Laurent99dab492017-06-17 15:19:08 -07004596 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004597 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4598 if (ret >= 0) {
4599 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004600 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004601 }
4602 }
4603 }
4604
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004605 audio_extn_hfp_set_parameters(adev, parms);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004606 audio_extn_a2dp_set_parameters(parms);
4607 // reconfigure should be done only after updating A2DP state in audio extension
4608 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4609 if (ret >= 0) {
4610 struct audio_usecase *usecase;
4611 struct listnode *node;
4612 list_for_each(node, &adev->usecase_list) {
4613 usecase = node_to_item(node, struct audio_usecase, list);
4614 if ((usecase->type == PCM_PLAYBACK) &&
4615 (usecase->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP)) {
4616 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
4617
4618 pthread_mutex_unlock(&adev->lock);
4619 lock_output_stream(usecase->stream.out);
4620 pthread_mutex_lock(&adev->lock);
4621 audio_extn_a2dp_set_handoff_mode(true);
4622 // force device switch to reconfigure encoder
4623 select_devices(adev, usecase->id);
4624 audio_extn_a2dp_set_handoff_mode(false);
4625 pthread_mutex_unlock(&usecase->stream.out->lock);
4626 break;
4627 }
4628 }
4629 }
4630
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004631done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004632 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004633 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004634 ALOGV("%s: exit with code(%d)", __func__, status);
4635 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004636}
4637
4638static char* adev_get_parameters(const struct audio_hw_device *dev,
4639 const char *keys)
4640{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004641 struct audio_device *adev = (struct audio_device *)dev;
4642 struct str_parms *reply = str_parms_create();
4643 struct str_parms *query = str_parms_create_str(keys);
4644 char *str;
4645
4646 pthread_mutex_lock(&adev->lock);
4647
4648 voice_get_parameters(adev, query, reply);
4649 str = str_parms_to_str(reply);
4650 str_parms_destroy(query);
4651 str_parms_destroy(reply);
4652
4653 pthread_mutex_unlock(&adev->lock);
4654 ALOGV("%s: exit: returns - %s", __func__, str);
4655 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004656}
4657
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004658static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004659{
4660 return 0;
4661}
4662
Haynes Mathew George5191a852013-09-11 14:19:36 -07004663static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4664{
4665 int ret;
4666 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004667
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004668 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4669
Haynes Mathew George5191a852013-09-11 14:19:36 -07004670 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004671 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004672 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004673
Haynes Mathew George5191a852013-09-11 14:19:36 -07004674 return ret;
4675}
4676
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004677static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004678{
4679 return -ENOSYS;
4680}
4681
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004682static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4683 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004684{
4685 return -ENOSYS;
4686}
4687
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004688static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004689{
4690 return -ENOSYS;
4691}
4692
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004693static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004694{
4695 return -ENOSYS;
4696}
4697
4698static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4699{
4700 struct audio_device *adev = (struct audio_device *)dev;
4701
4702 pthread_mutex_lock(&adev->lock);
4703 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004704 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004705 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004706 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4707 voice_is_in_call(adev)) {
4708 voice_stop_call(adev);
4709 adev->current_call_output = NULL;
4710 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004711 }
4712 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004713
4714 audio_extn_extspk_set_mode(adev->extspk, mode);
4715
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004716 return 0;
4717}
4718
4719static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4720{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004721 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004722 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004723
Eric Laurent2bafff12016-03-17 12:17:23 -07004724 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004725 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004726 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4727 ret = audio_extn_hfp_set_mic_mute(adev, state);
4728 } else {
4729 ret = voice_set_mic_mute(adev, state);
4730 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004731 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004732 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004733
4734 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004735}
4736
4737static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4738{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004739 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004740 return 0;
4741}
4742
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004743static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004744 const struct audio_config *config)
4745{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004746 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004747
Eric Laurent74b55762017-07-09 17:04:53 -07004748 /* Don't know if USB HIFI in this context so use true to be conservative */
4749 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4750 true /*is_usb_hifi */) != 0)
4751 return 0;
4752
vivek mehtaa68fea62017-06-08 19:04:02 -07004753 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4754 config->sample_rate, config->format,
4755 channel_count,
4756 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004757}
4758
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004759static bool adev_input_allow_hifi_record(struct audio_device *adev,
4760 audio_devices_t devices,
4761 audio_input_flags_t flags,
4762 audio_source_t source) {
4763 const bool allowed = true;
4764
4765 if (!audio_is_usb_in_device(devices))
4766 return !allowed;
4767
4768 switch (flags) {
4769 case AUDIO_INPUT_FLAG_NONE:
4770 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4771 break;
4772 default:
4773 return !allowed;
4774 }
4775
4776 switch (source) {
4777 case AUDIO_SOURCE_DEFAULT:
4778 case AUDIO_SOURCE_MIC:
4779 case AUDIO_SOURCE_UNPROCESSED:
4780 break;
4781 default:
4782 return !allowed;
4783 }
4784
4785 switch (adev->mode) {
4786 case 0:
4787 break;
4788 default:
4789 return !allowed;
4790 }
4791
4792 return allowed;
4793}
4794
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004795static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004796 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004797 audio_devices_t devices,
4798 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004799 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004800 audio_input_flags_t flags,
4801 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004802 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004803{
4804 struct audio_device *adev = (struct audio_device *)dev;
4805 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004806 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004807 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004808 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004809 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004810 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4811 devices,
4812 flags,
4813 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004814 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004815 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004816
Andy Hungd9653bd2017-08-01 19:31:39 -07004817 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
4818 return -ENOSYS;
4819 }
4820
Eric Laurent74b55762017-07-09 17:04:53 -07004821 if (!(is_usb_dev && may_use_hifi_record)) {
4822 if (config->sample_rate == 0)
4823 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4824 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4825 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4826 if (config->format == AUDIO_FORMAT_DEFAULT)
4827 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004828
Eric Laurent74b55762017-07-09 17:04:53 -07004829 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
4830
4831 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
4832 return -EINVAL;
4833 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004834
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004835 if (audio_extn_tfa_98xx_is_supported() &&
4836 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004837 return -EINVAL;
4838
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004839 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4840
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004841 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004842 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004843
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004844 in->stream.common.get_sample_rate = in_get_sample_rate;
4845 in->stream.common.set_sample_rate = in_set_sample_rate;
4846 in->stream.common.get_buffer_size = in_get_buffer_size;
4847 in->stream.common.get_channels = in_get_channels;
4848 in->stream.common.get_format = in_get_format;
4849 in->stream.common.set_format = in_set_format;
4850 in->stream.common.standby = in_standby;
4851 in->stream.common.dump = in_dump;
4852 in->stream.common.set_parameters = in_set_parameters;
4853 in->stream.common.get_parameters = in_get_parameters;
4854 in->stream.common.add_audio_effect = in_add_audio_effect;
4855 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4856 in->stream.set_gain = in_set_gain;
4857 in->stream.read = in_read;
4858 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08004859 in->stream.get_capture_position = in_get_capture_position;
jiabin8962a4d2018-03-19 18:21:24 -07004860 in->stream.get_active_microphones = in_get_active_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004861
4862 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004863 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004864 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004865 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004866 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004867 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004868
Haynes Mathew George569b7482017-05-08 14:44:27 -07004869 if (is_usb_dev && may_use_hifi_record) {
4870 /* HiFi record selects an appropriate format, channel, rate combo
4871 depending on sink capabilities*/
4872 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
4873 &config->format,
4874 &in->supported_formats[0],
4875 MAX_SUPPORTED_FORMATS,
4876 &config->channel_mask,
4877 &in->supported_channel_masks[0],
4878 MAX_SUPPORTED_CHANNEL_MASKS,
4879 &config->sample_rate,
4880 &in->supported_sample_rates[0],
4881 MAX_SUPPORTED_SAMPLE_RATES);
4882 if (ret != 0) {
4883 ret = -EINVAL;
4884 goto err_open;
4885 }
Eric Laurent74b55762017-07-09 17:04:53 -07004886 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004887 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07004888 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07004889 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
4890 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
4891 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4892 bool ret_error = false;
4893 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4894 from HAL is 8_24
4895 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4896 8_24 return error indicating supported format is 8_24
4897 *> In case of any other source requesting 24 bit or float return error
4898 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07004899
vivek mehta57ff9b52016-04-28 14:13:08 -07004900 on error flinger will retry with supported format passed
4901 */
4902 if (source != AUDIO_SOURCE_UNPROCESSED) {
4903 config->format = AUDIO_FORMAT_PCM_16_BIT;
4904 ret_error = true;
4905 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
4906 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
4907 ret_error = true;
4908 }
4909
4910 if (ret_error) {
4911 ret = -EINVAL;
4912 goto err_open;
4913 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004914 }
4915
vivek mehta57ff9b52016-04-28 14:13:08 -07004916 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07004917 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07004918
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004919 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004920 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
4921 if (config->sample_rate == 0)
4922 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4923 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4924 config->sample_rate != 8000) {
4925 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4926 ret = -EINVAL;
4927 goto err_open;
4928 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004929
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004930 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4931 config->format = AUDIO_FORMAT_PCM_16_BIT;
4932 ret = -EINVAL;
4933 goto err_open;
4934 }
4935
4936 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4937 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07004938 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004939 } else if (is_usb_dev && may_use_hifi_record) {
4940 in->usecase = USECASE_AUDIO_RECORD_HIFI;
4941 in->config = pcm_config_audio_capture;
4942 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004943 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4944 config->sample_rate,
4945 config->format,
4946 channel_count,
4947 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004948 in->config.period_size = buffer_size / frame_size;
4949 in->config.rate = config->sample_rate;
4950 in->af_period_multiplier = 1;
4951 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004952 } else {
4953 in->usecase = USECASE_AUDIO_RECORD;
4954 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08004955 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004956 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07004957#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004958 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07004959#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08004960 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004961 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08004962 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004963 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004964 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4965 config->sample_rate,
4966 config->format,
4967 channel_count,
4968 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004969 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004970 in->config.rate = config->sample_rate;
4971 in->af_period_multiplier = 1;
4972 } else {
4973 // period size is left untouched for rt mode playback
4974 in->config = pcm_config_audio_capture_rt;
4975 in->af_period_multiplier = af_period_multiplier;
4976 }
4977 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
4978 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004979 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08004980 in->usecase = USECASE_AUDIO_RECORD_MMAP;
4981 in->config = pcm_config_mmap_capture;
4982 in->stream.start = in_start;
4983 in->stream.stop = in_stop;
4984 in->stream.create_mmap_buffer = in_create_mmap_buffer;
4985 in->stream.get_mmap_position = in_get_mmap_position;
4986 in->af_period_multiplier = 1;
4987 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07004988 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07004989 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07004990 (config->sample_rate == 8000 ||
4991 config->sample_rate == 16000 ||
4992 config->sample_rate == 32000 ||
4993 config->sample_rate == 48000) &&
4994 channel_count == 1) {
4995 in->usecase = USECASE_AUDIO_RECORD_VOIP;
4996 in->config = pcm_config_audio_capture;
4997 frame_size = audio_stream_in_frame_size(&in->stream);
4998 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
4999 config->sample_rate,
5000 config->format,
5001 channel_count, false /*is_low_latency*/);
5002 in->config.period_size = buffer_size / frame_size;
5003 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
5004 in->config.rate = config->sample_rate;
5005 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005006 } else {
5007 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005008 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005009 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5010 config->sample_rate,
5011 config->format,
5012 channel_count,
5013 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005014 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005015 in->config.rate = config->sample_rate;
5016 in->af_period_multiplier = 1;
5017 }
5018 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
5019 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005020 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08005021
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005022 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07005023 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005024
Andy Hungd13f0d32017-06-12 13:58:37 -07005025 in->error_log = error_log_create(
5026 ERROR_LOG_ENTRIES,
5027 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
5028
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005029 /* This stream could be for sound trigger lab,
5030 get sound trigger pcm if present */
5031 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005032
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005033 lock_input_stream(in);
5034 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5035 pthread_mutex_lock(&adev->lock);
5036 in->card_status = adev->card_status;
5037 pthread_mutex_unlock(&adev->lock);
5038 pthread_mutex_unlock(&in->lock);
5039
vivek mehta4a824772017-06-08 19:05:49 -07005040 stream_app_type_cfg_init(&in->app_type_cfg);
5041
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005042 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005043 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005044 return 0;
5045
5046err_open:
5047 free(in);
5048 *stream_in = NULL;
5049 return ret;
5050}
5051
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005052static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005053 struct audio_stream_in *stream)
5054{
Andy Hungd13f0d32017-06-12 13:58:37 -07005055 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005056 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005057
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005058 // must deregister from sndmonitor first to prevent races
5059 // between the callback and close_stream
5060 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005061 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07005062
5063 error_log_destroy(in->error_log);
5064 in->error_log = NULL;
5065
Andy Hung0dbb52b2017-08-09 13:51:38 -07005066 pthread_mutex_destroy(&in->pre_lock);
5067 pthread_mutex_destroy(&in->lock);
5068
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005069 free(stream);
5070
5071 return;
5072}
5073
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005074static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005075{
5076 return 0;
5077}
5078
Andy Hung31aca912014-03-20 17:14:59 -07005079/* verifies input and output devices and their capabilities.
5080 *
5081 * This verification is required when enabling extended bit-depth or
5082 * sampling rates, as not all qcom products support it.
5083 *
5084 * Suitable for calling only on initialization such as adev_open().
5085 * It fills the audio_device use_case_table[] array.
5086 *
5087 * Has a side-effect that it needs to configure audio routing / devices
5088 * in order to power up the devices and read the device parameters.
5089 * It does not acquire any hw device lock. Should restore the devices
5090 * back to "normal state" upon completion.
5091 */
5092static int adev_verify_devices(struct audio_device *adev)
5093{
5094 /* enumeration is a bit difficult because one really wants to pull
5095 * the use_case, device id, etc from the hidden pcm_device_table[].
5096 * In this case there are the following use cases and device ids.
5097 *
5098 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
5099 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005100 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07005101 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
5102 * [USECASE_AUDIO_RECORD] = {0, 0},
5103 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
5104 * [USECASE_VOICE_CALL] = {2, 2},
5105 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005106 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07005107 * USECASE_VOICE_CALL omitted, but possible for either input or output.
5108 */
5109
5110 /* should be the usecases enabled in adev_open_input_stream() */
5111 static const int test_in_usecases[] = {
5112 USECASE_AUDIO_RECORD,
5113 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
5114 };
5115 /* should be the usecases enabled in adev_open_output_stream()*/
5116 static const int test_out_usecases[] = {
5117 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
5118 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
5119 };
5120 static const usecase_type_t usecase_type_by_dir[] = {
5121 PCM_PLAYBACK,
5122 PCM_CAPTURE,
5123 };
5124 static const unsigned flags_by_dir[] = {
5125 PCM_OUT,
5126 PCM_IN,
5127 };
5128
5129 size_t i;
5130 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005131 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07005132 char info[512]; /* for possible debug info */
5133
5134 for (dir = 0; dir < 2; ++dir) {
5135 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
5136 const unsigned flags_dir = flags_by_dir[dir];
5137 const size_t testsize =
5138 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
5139 const int *testcases =
5140 dir ? test_in_usecases : test_out_usecases;
5141 const audio_devices_t audio_device =
5142 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
5143
5144 for (i = 0; i < testsize; ++i) {
5145 const audio_usecase_t audio_usecase = testcases[i];
5146 int device_id;
5147 snd_device_t snd_device;
5148 struct pcm_params **pparams;
5149 struct stream_out out;
5150 struct stream_in in;
5151 struct audio_usecase uc_info;
5152 int retval;
5153
5154 pparams = &adev->use_case_table[audio_usecase];
5155 pcm_params_free(*pparams); /* can accept null input */
5156 *pparams = NULL;
5157
5158 /* find the device ID for the use case (signed, for error) */
5159 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
5160 if (device_id < 0)
5161 continue;
5162
5163 /* prepare structures for device probing */
5164 memset(&uc_info, 0, sizeof(uc_info));
5165 uc_info.id = audio_usecase;
5166 uc_info.type = usecase_type;
5167 if (dir) {
5168 adev->active_input = &in;
5169 memset(&in, 0, sizeof(in));
5170 in.device = audio_device;
5171 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
5172 uc_info.stream.in = &in;
5173 } else {
5174 adev->active_input = NULL;
5175 }
5176 memset(&out, 0, sizeof(out));
5177 out.devices = audio_device; /* only field needed in select_devices */
5178 uc_info.stream.out = &out;
5179 uc_info.devices = audio_device;
5180 uc_info.in_snd_device = SND_DEVICE_NONE;
5181 uc_info.out_snd_device = SND_DEVICE_NONE;
5182 list_add_tail(&adev->usecase_list, &uc_info.list);
5183
5184 /* select device - similar to start_(in/out)put_stream() */
5185 retval = select_devices(adev, audio_usecase);
5186 if (retval >= 0) {
5187 *pparams = pcm_params_get(card_id, device_id, flags_dir);
5188#if LOG_NDEBUG == 0
5189 if (*pparams) {
5190 ALOGV("%s: (%s) card %d device %d", __func__,
5191 dir ? "input" : "output", card_id, device_id);
5192 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07005193 } else {
5194 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
5195 }
5196#endif
5197 }
5198
5199 /* deselect device - similar to stop_(in/out)put_stream() */
5200 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07005201 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07005202 /* 2. Disable the rx device */
5203 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07005204 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07005205 list_remove(&uc_info.list);
5206 }
5207 }
5208 adev->active_input = NULL; /* restore adev state */
5209 return 0;
5210}
5211
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005212static int adev_close(hw_device_t *device)
5213{
Andy Hung31aca912014-03-20 17:14:59 -07005214 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005215 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005216
5217 if (!adev)
5218 return 0;
5219
5220 pthread_mutex_lock(&adev_init_lock);
5221
5222 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005223 audio_extn_snd_mon_unregister_listener(adev);
5224 audio_extn_tfa_98xx_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005225 audio_route_free(adev->audio_route);
5226 free(adev->snd_dev_ref_cnt);
5227 platform_deinit(adev->platform);
5228 audio_extn_extspk_deinit(adev->extspk);
5229 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005230 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005231 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
5232 pcm_params_free(adev->use_case_table[i]);
5233 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005234 if (adev->adm_deinit)
5235 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005236 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005237 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07005238 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07005239
5240 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005241
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005242 return 0;
5243}
5244
Glenn Kasten4f993392014-05-14 07:30:48 -07005245/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5246 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5247 * just that it _might_ work.
5248 */
5249static int period_size_is_plausible_for_low_latency(int period_size)
5250{
5251 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005252 case 48:
5253 case 96:
5254 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07005255 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005256 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07005257 case 240:
5258 case 320:
5259 case 480:
5260 return 1;
5261 default:
5262 return 0;
5263 }
5264}
5265
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005266static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
5267{
5268 int card;
5269 card_status_t status;
5270
5271 if (!parms)
5272 return;
5273
5274 if (parse_snd_card_status(parms, &card, &status) < 0)
5275 return;
5276
5277 pthread_mutex_lock(&adev->lock);
5278 bool valid_cb = (card == adev->snd_card);
5279 if (valid_cb) {
5280 if (adev->card_status != status) {
5281 adev->card_status = status;
5282 platform_snd_card_update(adev->platform, status);
5283 }
5284 }
5285 pthread_mutex_unlock(&adev->lock);
5286 return;
5287}
5288
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005289/* out and adev lock held */
5290static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
5291{
5292 struct audio_usecase *uc_info;
5293 float left_p;
5294 float right_p;
5295 audio_devices_t devices;
5296
5297 uc_info = get_usecase_from_list(adev, out->usecase);
5298 if (uc_info == NULL) {
5299 ALOGE("%s: Could not find the usecase (%d) in the list",
5300 __func__, out->usecase);
5301 return -EINVAL;
5302 }
5303
5304 ALOGD("%s: enter: usecase(%d: %s)", __func__,
5305 out->usecase, use_case_table[out->usecase]);
5306
5307 if (restore) {
5308 // restore A2DP device for active usecases and unmute if required
5309 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
5310 !is_a2dp_device(uc_info->out_snd_device)) {
5311 ALOGD("%s: restoring A2DP and unmuting stream", __func__);
5312 select_devices(adev, uc_info->id);
5313 pthread_mutex_lock(&out->compr_mute_lock);
5314 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5315 (out->a2dp_compress_mute)) {
5316 out->a2dp_compress_mute = false;
5317 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5318 }
5319 pthread_mutex_unlock(&out->compr_mute_lock);
5320 }
5321 } else {
5322 // mute compress stream if suspended
5323 pthread_mutex_lock(&out->compr_mute_lock);
5324 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5325 (!out->a2dp_compress_mute)) {
5326 if (!out->standby) {
5327 ALOGD("%s: selecting speaker and muting stream", __func__);
5328 devices = out->devices;
5329 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
5330 left_p = out->volume_l;
5331 right_p = out->volume_r;
5332 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5333 compress_pause(out->compr);
5334 set_compr_volume(&out->stream, 0.0f, 0.0f);
5335 out->a2dp_compress_mute = true;
5336 select_devices(adev, out->usecase);
5337 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5338 compress_resume(out->compr);
5339 out->devices = devices;
5340 out->volume_l = left_p;
5341 out->volume_r = right_p;
5342 }
5343 }
5344 pthread_mutex_unlock(&out->compr_mute_lock);
5345 }
5346 ALOGV("%s: exit", __func__);
5347 return 0;
5348}
5349
5350int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
5351{
5352 int ret = 0;
5353
5354 lock_output_stream(out);
5355 pthread_mutex_lock(&adev->lock);
5356
5357 ret = check_a2dp_restore_l(adev, out, restore);
5358
5359 pthread_mutex_unlock(&adev->lock);
5360 pthread_mutex_unlock(&out->lock);
5361 return ret;
5362}
5363
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005364static int adev_open(const hw_module_t *module, const char *name,
5365 hw_device_t **device)
5366{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005367 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005368
Eric Laurent2bafff12016-03-17 12:17:23 -07005369 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005370 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005371 pthread_mutex_lock(&adev_init_lock);
5372 if (audio_device_ref_count != 0) {
5373 *device = &adev->device.common;
5374 audio_device_ref_count++;
5375 ALOGV("%s: returning existing instance of adev", __func__);
5376 ALOGV("%s: exit", __func__);
5377 pthread_mutex_unlock(&adev_init_lock);
5378 return 0;
5379 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005380 adev = calloc(1, sizeof(struct audio_device));
5381
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005382 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5383
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005384 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5385 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5386 adev->device.common.module = (struct hw_module_t *)module;
5387 adev->device.common.close = adev_close;
5388
5389 adev->device.init_check = adev_init_check;
5390 adev->device.set_voice_volume = adev_set_voice_volume;
5391 adev->device.set_master_volume = adev_set_master_volume;
5392 adev->device.get_master_volume = adev_get_master_volume;
5393 adev->device.set_master_mute = adev_set_master_mute;
5394 adev->device.get_master_mute = adev_get_master_mute;
5395 adev->device.set_mode = adev_set_mode;
5396 adev->device.set_mic_mute = adev_set_mic_mute;
5397 adev->device.get_mic_mute = adev_get_mic_mute;
5398 adev->device.set_parameters = adev_set_parameters;
5399 adev->device.get_parameters = adev_get_parameters;
5400 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5401 adev->device.open_output_stream = adev_open_output_stream;
5402 adev->device.close_output_stream = adev_close_output_stream;
5403 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005404
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005405 adev->device.close_input_stream = adev_close_input_stream;
5406 adev->device.dump = adev_dump;
jiabin8962a4d2018-03-19 18:21:24 -07005407 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005408
5409 /* Set the default route before the PCM stream is opened */
5410 pthread_mutex_lock(&adev->lock);
5411 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005412 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005413 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005414 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005415 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005416 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005417 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005418 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005419 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005420 pthread_mutex_unlock(&adev->lock);
5421
5422 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005423 adev->platform = platform_init(adev);
5424 if (!adev->platform) {
5425 free(adev->snd_dev_ref_cnt);
5426 free(adev);
5427 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5428 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005429 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005430 return -EINVAL;
5431 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05005432 adev->extspk = audio_extn_extspk_init(adev);
5433
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005434 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5435 if (adev->visualizer_lib == NULL) {
5436 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5437 } else {
5438 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5439 adev->visualizer_start_output =
5440 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5441 "visualizer_hal_start_output");
5442 adev->visualizer_stop_output =
5443 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5444 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07005445 }
5446
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005447 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5448 if (adev->offload_effects_lib == NULL) {
5449 ALOGW("%s: DLOPEN failed for %s", __func__,
5450 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5451 } else {
5452 ALOGV("%s: DLOPEN successful for %s", __func__,
5453 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5454 adev->offload_effects_start_output =
5455 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5456 "offload_effects_bundle_hal_start_output");
5457 adev->offload_effects_stop_output =
5458 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5459 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07005460 }
5461
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005462 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5463 if (adev->adm_lib == NULL) {
5464 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5465 } else {
5466 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5467 adev->adm_init = (adm_init_t)
5468 dlsym(adev->adm_lib, "adm_init");
5469 adev->adm_deinit = (adm_deinit_t)
5470 dlsym(adev->adm_lib, "adm_deinit");
5471 adev->adm_register_input_stream = (adm_register_input_stream_t)
5472 dlsym(adev->adm_lib, "adm_register_input_stream");
5473 adev->adm_register_output_stream = (adm_register_output_stream_t)
5474 dlsym(adev->adm_lib, "adm_register_output_stream");
5475 adev->adm_deregister_stream = (adm_deregister_stream_t)
5476 dlsym(adev->adm_lib, "adm_deregister_stream");
5477 adev->adm_request_focus = (adm_request_focus_t)
5478 dlsym(adev->adm_lib, "adm_request_focus");
5479 adev->adm_abandon_focus = (adm_abandon_focus_t)
5480 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08005481 adev->adm_set_config = (adm_set_config_t)
5482 dlsym(adev->adm_lib, "adm_set_config");
5483 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5484 dlsym(adev->adm_lib, "adm_request_focus_v2");
5485 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5486 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5487 adev->adm_on_routing_change = (adm_on_routing_change_t)
5488 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005489 }
5490
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005491 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005492 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005493
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005494 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005495
Andy Hung31aca912014-03-20 17:14:59 -07005496 if (k_enable_extended_precision)
5497 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005498
Glenn Kasten4f993392014-05-14 07:30:48 -07005499 char value[PROPERTY_VALUE_MAX];
5500 int trial;
5501 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5502 trial = atoi(value);
5503 if (period_size_is_plausible_for_low_latency(trial)) {
5504 pcm_config_low_latency.period_size = trial;
5505 pcm_config_low_latency.start_threshold = trial / 4;
5506 pcm_config_low_latency.avail_min = trial / 4;
5507 configured_low_latency_capture_period_size = trial;
5508 }
5509 }
5510 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5511 trial = atoi(value);
5512 if (period_size_is_plausible_for_low_latency(trial)) {
5513 configured_low_latency_capture_period_size = trial;
5514 }
5515 }
5516
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005517 // commented as full set of app type cfg is sent from platform
5518 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005519 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005520
5521 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5522 af_period_multiplier = atoi(value);
5523 if (af_period_multiplier < 0) {
5524 af_period_multiplier = 2;
5525 } else if (af_period_multiplier > 4) {
5526 af_period_multiplier = 4;
5527 }
5528 ALOGV("new period_multiplier = %d", af_period_multiplier);
5529 }
5530
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005531 audio_extn_tfa_98xx_init(adev);
5532
vivek mehta1a9b7c02015-06-25 11:49:38 -07005533 pthread_mutex_unlock(&adev_init_lock);
5534
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005535 if (adev->adm_init)
5536 adev->adm_data = adev->adm_init();
5537
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005538 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005539 audio_extn_snd_mon_init();
5540 pthread_mutex_lock(&adev->lock);
5541 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
5542 adev->card_status = CARD_STATUS_ONLINE;
5543 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005544 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005545
Eric Laurent2bafff12016-03-17 12:17:23 -07005546 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005547 return 0;
5548}
5549
5550static struct hw_module_methods_t hal_module_methods = {
5551 .open = adev_open,
5552};
5553
5554struct audio_module HAL_MODULE_INFO_SYM = {
5555 .common = {
5556 .tag = HARDWARE_MODULE_TAG,
5557 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5558 .hal_api_version = HARDWARE_HAL_API_VERSION,
5559 .id = AUDIO_HARDWARE_MODULE_ID,
5560 .name = "QCOM Audio HAL",
5561 .author = "Code Aurora Forum",
5562 .methods = &hal_module_methods,
5563 },
5564};