blob: cc1276bedf1d7604abd2374418187b25c0287a61 [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"
jasmine cha270b7762018-03-30 15:41:33 +080061#include "audio_extn/maxxaudio.h"
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062
Eric Laurent397db572016-05-11 11:31:47 -070063/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
64 * COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
Marco Nelissen32093f52015-04-08 15:14:02 -070065#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070066// 2 buffers causes problems with high bitrate files
67#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070068/* ToDo: Check and update a proper value in msec */
69#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
vivek mehta4a824772017-06-08 19:05:49 -070070/* treat as unsigned Q1.13 */
71#define APP_TYPE_GAIN_DEFAULT 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070072#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
vivek mehta4a824772017-06-08 19:05:49 -070073
74/* treat as unsigned Q1.13 */
vivek mehtaa68fea62017-06-08 19:04:02 -070075#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076
Eric Laurent51f3c662018-04-10 18:21:34 -070077#define RECORD_GAIN_MIN 0.0f
78#define RECORD_GAIN_MAX 1.0f
79#define RECORD_VOLUME_CTL_MAX 0x2000
80
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070081#define PROXY_OPEN_RETRY_COUNT 100
82#define PROXY_OPEN_WAIT_TIME 20
83
vivek mehtadae44712015-07-27 14:13:18 -070084#define MIN_CHANNEL_COUNT 1
85#define DEFAULT_CHANNEL_COUNT 2
86
Jean-Michel Trivic0750692015-10-12 12:12:32 -070087#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
88#define MAX_CHANNEL_COUNT 1
89#else
vivek mehtadae44712015-07-27 14:13:18 -070090#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
91#define XSTR(x) STR(x)
92#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070093#endif
Eric Laurent74b55762017-07-09 17:04:53 -070094#define MAX_HIFI_CHANNEL_COUNT 8
vivek mehtadae44712015-07-27 14:13:18 -070095
Haynes Mathew George03c40102016-01-29 17:57:48 -080096#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
97
Glenn Kasten4f993392014-05-14 07:30:48 -070098static unsigned int configured_low_latency_capture_period_size =
99 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
100
Eric Laurent0e46adf2016-12-16 12:49:24 -0800101
102#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Phil Burkbc991042017-02-24 08:06:44 -0800103#define MMAP_PERIOD_COUNT_MIN 32
104#define MMAP_PERIOD_COUNT_MAX 512
105#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
Eric Laurent0e46adf2016-12-16 12:49:24 -0800106
Andy Hung31aca912014-03-20 17:14:59 -0700107/* This constant enables extended precision handling.
108 * TODO The flag is off until more testing is done.
109 */
110static const bool k_enable_extended_precision = false;
111
Eric Laurentb23d5282013-05-14 15:27:20 -0700112struct pcm_config pcm_config_deep_buffer = {
vivek mehtadae44712015-07-27 14:13:18 -0700113 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700114 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
115 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
116 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
117 .format = PCM_FORMAT_S16_LE,
118 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
119 .stop_threshold = INT_MAX,
120 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
121};
122
123struct pcm_config pcm_config_low_latency = {
vivek mehtadae44712015-07-27 14:13:18 -0700124 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700125 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
126 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
127 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
128 .format = PCM_FORMAT_S16_LE,
129 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
130 .stop_threshold = INT_MAX,
131 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
132};
133
Haynes Mathew George03c40102016-01-29 17:57:48 -0800134static int af_period_multiplier = 4;
135struct pcm_config pcm_config_rt = {
136 .channels = DEFAULT_CHANNEL_COUNT,
137 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
138 .period_size = ULL_PERIOD_SIZE, //1 ms
139 .period_count = 512, //=> buffer size is 512ms
140 .format = PCM_FORMAT_S16_LE,
141 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
142 .stop_threshold = INT_MAX,
143 .silence_threshold = 0,
144 .silence_size = 0,
145 .avail_min = ULL_PERIOD_SIZE, //1 ms
146};
147
Eric Laurentb23d5282013-05-14 15:27:20 -0700148struct pcm_config pcm_config_hdmi_multi = {
149 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
150 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
151 .period_size = HDMI_MULTI_PERIOD_SIZE,
152 .period_count = HDMI_MULTI_PERIOD_COUNT,
153 .format = PCM_FORMAT_S16_LE,
154 .start_threshold = 0,
155 .stop_threshold = INT_MAX,
156 .avail_min = 0,
157};
158
Eric Laurent0e46adf2016-12-16 12:49:24 -0800159struct pcm_config pcm_config_mmap_playback = {
160 .channels = DEFAULT_CHANNEL_COUNT,
161 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
162 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800163 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800164 .format = PCM_FORMAT_S16_LE,
165 .start_threshold = MMAP_PERIOD_SIZE*8,
166 .stop_threshold = INT32_MAX,
167 .silence_threshold = 0,
168 .silence_size = 0,
169 .avail_min = MMAP_PERIOD_SIZE, //1 ms
170};
171
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800172struct pcm_config pcm_config_hifi = {
173 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
174 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
175 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
176 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
177 .format = PCM_FORMAT_S24_3LE,
178 .start_threshold = 0,
179 .stop_threshold = INT_MAX,
180 .avail_min = 0,
181};
182
Eric Laurentb23d5282013-05-14 15:27:20 -0700183struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700184 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700185 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
186 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700187 .stop_threshold = INT_MAX,
188 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700189};
190
Haynes Mathew George03c40102016-01-29 17:57:48 -0800191struct pcm_config pcm_config_audio_capture_rt = {
192 .channels = DEFAULT_CHANNEL_COUNT,
193 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
194 .period_size = ULL_PERIOD_SIZE,
195 .period_count = 512,
196 .format = PCM_FORMAT_S16_LE,
197 .start_threshold = 0,
198 .stop_threshold = INT_MAX,
199 .silence_threshold = 0,
200 .silence_size = 0,
201 .avail_min = ULL_PERIOD_SIZE, //1 ms
202};
203
Eric Laurent0e46adf2016-12-16 12:49:24 -0800204struct pcm_config pcm_config_mmap_capture = {
205 .channels = DEFAULT_CHANNEL_COUNT,
206 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
207 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800208 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800209 .format = PCM_FORMAT_S16_LE,
210 .start_threshold = 0,
211 .stop_threshold = INT_MAX,
212 .silence_threshold = 0,
213 .silence_size = 0,
214 .avail_min = MMAP_PERIOD_SIZE, //1 ms
215};
216
vivek mehtaa68fea62017-06-08 19:04:02 -0700217struct pcm_config pcm_config_voip = {
218 .channels = 1,
219 .period_count = 2,
220 .format = PCM_FORMAT_S16_LE,
221 .stop_threshold = INT_MAX,
222 .avail_min = 0,
223};
224
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700225#define AFE_PROXY_CHANNEL_COUNT 2
226#define AFE_PROXY_SAMPLING_RATE 48000
227
228#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
229#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
230
231struct pcm_config pcm_config_afe_proxy_playback = {
232 .channels = AFE_PROXY_CHANNEL_COUNT,
233 .rate = AFE_PROXY_SAMPLING_RATE,
234 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
235 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
236 .format = PCM_FORMAT_S16_LE,
237 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
238 .stop_threshold = INT_MAX,
239 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
240};
241
242#define AFE_PROXY_RECORD_PERIOD_SIZE 768
243#define AFE_PROXY_RECORD_PERIOD_COUNT 4
244
245struct pcm_config pcm_config_afe_proxy_record = {
246 .channels = AFE_PROXY_CHANNEL_COUNT,
247 .rate = AFE_PROXY_SAMPLING_RATE,
248 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
249 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
250 .format = PCM_FORMAT_S16_LE,
251 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
jiabin5d0261e2018-05-25 09:43:59 -0700252 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700253 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
254};
255
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700256const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700257 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
258 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800259 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700260 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700261 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700262 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800263 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700264
Eric Laurentb23d5282013-05-14 15:27:20 -0700265 [USECASE_AUDIO_RECORD] = "audio-record",
266 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800267 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George569b7482017-05-08 14:44:27 -0700268 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700269
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800270 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
271 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700272
Eric Laurentb23d5282013-05-14 15:27:20 -0700273 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700274 [USECASE_VOICE2_CALL] = "voice2-call",
275 [USECASE_VOLTE_CALL] = "volte-call",
276 [USECASE_QCHAT_CALL] = "qchat-call",
277 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800278 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
279 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700280
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700281 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
282 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
283
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700284 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
285 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
vivek mehta781065c2017-04-04 12:55:01 -0700286
287 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
288 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
289 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
290
vivek mehtaa68fea62017-06-08 19:04:02 -0700291 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
292 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Nadav Bar3d72cfc2018-01-07 12:19:24 +0200293
294 [USECASE_INCALL_MUSIC_UPLINK] = "incall-music-uplink",
Aniket Kumar Lata99546312018-03-19 21:38:38 -0700295
296 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700297};
298
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800299
300#define STRING_TO_ENUM(string) { #string, string }
301
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800302struct string_to_enum {
303 const char *name;
304 uint32_t value;
305};
306
Haynes Mathew George569b7482017-05-08 14:44:27 -0700307static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800308 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
309 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
310 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Eric Laurent74b55762017-07-09 17:04:53 -0700311 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
Haynes Mathew George569b7482017-05-08 14:44:27 -0700312 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
Eric Laurent74b55762017-07-09 17:04:53 -0700313 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
314 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
315 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
316 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
317 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
318 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
319 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
320 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
321 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800322};
323
Haynes Mathew George5191a852013-09-11 14:19:36 -0700324static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700325static struct audio_device *adev = NULL;
Andy Hung9e737de2017-05-22 10:51:22 -0700326static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700327static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700328//cache last MBDRC cal step level
329static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700330
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800331static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
332static int set_compr_volume(struct audio_stream_out *stream, float left, float right);
333
Haynes Mathew George03c40102016-01-29 17:57:48 -0800334static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
335 int flags __unused)
336{
337 int dir = 0;
338 switch (uc_id) {
339 case USECASE_AUDIO_RECORD_LOW_LATENCY:
340 dir = 1;
341 case USECASE_AUDIO_PLAYBACK_ULL:
342 break;
343 default:
344 return false;
345 }
346
347 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
348 PCM_PLAYBACK : PCM_CAPTURE);
349 if (adev->adm_is_noirq_avail)
350 return adev->adm_is_noirq_avail(adev->adm_data,
351 adev->snd_card, dev_id, dir);
352 return false;
353}
354
355static void register_out_stream(struct stream_out *out)
356{
357 struct audio_device *adev = out->dev;
358 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
359 return;
360
361 if (!adev->adm_register_output_stream)
362 return;
363
364 adev->adm_register_output_stream(adev->adm_data,
365 out->handle,
366 out->flags);
367
368 if (!adev->adm_set_config)
369 return;
370
371 if (out->realtime) {
372 adev->adm_set_config(adev->adm_data,
373 out->handle,
374 out->pcm, &out->config);
375 }
376}
377
378static void register_in_stream(struct stream_in *in)
379{
380 struct audio_device *adev = in->dev;
381 if (!adev->adm_register_input_stream)
382 return;
383
384 adev->adm_register_input_stream(adev->adm_data,
385 in->capture_handle,
386 in->flags);
387
388 if (!adev->adm_set_config)
389 return;
390
391 if (in->realtime) {
392 adev->adm_set_config(adev->adm_data,
393 in->capture_handle,
394 in->pcm,
395 &in->config);
396 }
397}
398
399static void request_out_focus(struct stream_out *out, long ns)
400{
401 struct audio_device *adev = out->dev;
402
Haynes Mathew George03c40102016-01-29 17:57:48 -0800403 if (adev->adm_request_focus_v2) {
404 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
405 } else if (adev->adm_request_focus) {
406 adev->adm_request_focus(adev->adm_data, out->handle);
407 }
408}
409
410static void request_in_focus(struct stream_in *in, long ns)
411{
412 struct audio_device *adev = in->dev;
413
Haynes Mathew George03c40102016-01-29 17:57:48 -0800414 if (adev->adm_request_focus_v2) {
415 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
416 } else if (adev->adm_request_focus) {
417 adev->adm_request_focus(adev->adm_data, in->capture_handle);
418 }
419}
420
421static void release_out_focus(struct stream_out *out, long ns __unused)
422{
423 struct audio_device *adev = out->dev;
424
425 if (adev->adm_abandon_focus)
426 adev->adm_abandon_focus(adev->adm_data, out->handle);
427}
428
429static void release_in_focus(struct stream_in *in, long ns __unused)
430{
431 struct audio_device *adev = in->dev;
432 if (adev->adm_abandon_focus)
433 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
434}
435
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700436static int parse_snd_card_status(struct str_parms * parms, int * card,
437 card_status_t * status)
438{
439 char value[32]={0};
440 char state[32]={0};
441
442 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
443
444 if (ret < 0)
445 return -1;
446
447 // sscanf should be okay as value is of max length 32.
448 // same as sizeof state.
449 if (sscanf(value, "%d,%s", card, state) < 2)
450 return -1;
451
452 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
453 CARD_STATUS_OFFLINE;
454 return 0;
455}
456
vivek mehta40125092017-08-21 18:48:51 -0700457// always call with adev lock held
458void send_gain_dep_calibration_l() {
459 if (last_known_cal_step >= 0)
460 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
461}
462
vivek mehta1a9b7c02015-06-25 11:49:38 -0700463__attribute__ ((visibility ("default")))
464bool audio_hw_send_gain_dep_calibration(int level) {
465 bool ret_val = false;
466 ALOGV("%s: enter ... ", __func__);
467
468 pthread_mutex_lock(&adev_init_lock);
469
470 if (adev != NULL && adev->platform != NULL) {
471 pthread_mutex_lock(&adev->lock);
vivek mehta40125092017-08-21 18:48:51 -0700472 last_known_cal_step = level;
473 send_gain_dep_calibration_l();
vivek mehta1a9b7c02015-06-25 11:49:38 -0700474 pthread_mutex_unlock(&adev->lock);
475 } else {
476 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
477 }
478
479 pthread_mutex_unlock(&adev_init_lock);
480
481 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
482 return ret_val;
483}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700484
jasmine cha270b7762018-03-30 15:41:33 +0800485#ifdef MAXXAUDIO_QDSP_ENABLED
486bool audio_hw_send_ma_parameter(int stream_type, float vol, bool active)
487{
488 bool ret = false;
489 ALOGV("%s: enter ...", __func__);
490
491 pthread_mutex_lock(&adev_init_lock);
492
493 if (adev != NULL && adev->platform != NULL) {
494 pthread_mutex_lock(&adev->lock);
495 ret = audio_extn_ma_set_state(adev, stream_type, vol, active);
496 pthread_mutex_unlock(&adev->lock);
497 }
498
499 pthread_mutex_unlock(&adev_init_lock);
500
501 ALOGV("%s: exit with ret %d", __func__, ret);
502 return ret;
503}
504#else
505#define audio_hw_send_ma_parameter(stream_type, vol, active) (0)
506#endif
507
vivek mehtaa8d7c922016-05-25 14:40:44 -0700508__attribute__ ((visibility ("default")))
509int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
510 int table_size) {
511 int ret_val = 0;
512 ALOGV("%s: enter ... ", __func__);
513
514 pthread_mutex_lock(&adev_init_lock);
515 if (adev == NULL) {
516 ALOGW("%s: adev is NULL .... ", __func__);
517 goto done;
518 }
519
520 pthread_mutex_lock(&adev->lock);
521 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
522 pthread_mutex_unlock(&adev->lock);
523done:
524 pthread_mutex_unlock(&adev_init_lock);
525 ALOGV("%s: exit ... ", __func__);
526 return ret_val;
527}
528
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700529static bool is_supported_format(audio_format_t format)
530{
Eric Laurent8251ac82014-07-23 11:00:25 -0700531 switch (format) {
532 case AUDIO_FORMAT_MP3:
533 case AUDIO_FORMAT_AAC_LC:
534 case AUDIO_FORMAT_AAC_HE_V1:
535 case AUDIO_FORMAT_AAC_HE_V2:
536 return true;
537 default:
538 break;
539 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700540 return false;
541}
542
juyuchenbe5c67e2018-08-29 17:19:20 +0800543static bool is_supported_24bits_audiosource(audio_source_t source)
544{
545 switch (source) {
546 case AUDIO_SOURCE_UNPROCESSED:
547#ifdef ENABLED_24BITS_CAMCORDER
548 case AUDIO_SOURCE_CAMCORDER:
549#endif
550 return true;
551 default:
552 break;
553 }
554 return false;
555}
556
Haynes Mathew George03c40102016-01-29 17:57:48 -0800557static inline bool is_mmap_usecase(audio_usecase_t uc_id)
558{
559 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
560 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
561}
562
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700563static int get_snd_codec_id(audio_format_t format)
564{
565 int id = 0;
566
Eric Laurent8251ac82014-07-23 11:00:25 -0700567 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700568 case AUDIO_FORMAT_MP3:
569 id = SND_AUDIOCODEC_MP3;
570 break;
571 case AUDIO_FORMAT_AAC:
572 id = SND_AUDIOCODEC_AAC;
573 break;
574 default:
575 ALOGE("%s: Unsupported audio format", __func__);
576 }
577
578 return id;
579}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800580
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800581static int audio_ssr_status(struct audio_device *adev)
582{
583 int ret = 0;
584 struct mixer_ctl *ctl;
585 const char *mixer_ctl_name = "Audio SSR Status";
586
587 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
588 ret = mixer_ctl_get_value(ctl, 0);
589 ALOGD("%s: value: %d", __func__, ret);
590 return ret;
591}
592
vivek mehta4a824772017-06-08 19:05:49 -0700593static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
594{
595 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
596}
597
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800598static bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
599{
600 return out_snd_device == SND_DEVICE_OUT_BT_SCO ||
601 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
602 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
603 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
604 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
605 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC;
606
607}
608
609static bool is_a2dp_device(snd_device_t out_snd_device)
610{
611 return out_snd_device == SND_DEVICE_OUT_BT_A2DP;
612}
613
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800614int enable_audio_route(struct audio_device *adev,
615 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800616{
yixuanjiang509f0a72018-09-06 18:37:23 +0800617 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800618 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800619
620 if (usecase == NULL)
621 return -EINVAL;
622
623 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
624
yixuanjiang509f0a72018-09-06 18:37:23 +0800625 if (usecase->type == PCM_CAPTURE)
626 snd_device = usecase->in_snd_device;
627 else
628 snd_device = usecase->out_snd_device;
Yamit Mehtae3b99562016-09-16 22:44:00 +0530629 audio_extn_utils_send_app_type_cfg(adev, usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800630 audio_extn_utils_send_audio_calibration(adev, usecase);
yixuanjiang6c5e87c2018-08-13 11:50:26 +0800631 strcpy(mixer_path, use_case_table[usecase->id]);
yixuanjiang509f0a72018-09-06 18:37:23 +0800632 platform_add_backend_name(adev->platform, mixer_path, snd_device);
633 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700634 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700635 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800636
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800637 ALOGV("%s: exit", __func__);
638 return 0;
639}
640
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800641int disable_audio_route(struct audio_device *adev,
642 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800643{
yixuanjiang509f0a72018-09-06 18:37:23 +0800644 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800645 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800646
647 if (usecase == NULL)
648 return -EINVAL;
649
650 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
yixuanjiang509f0a72018-09-06 18:37:23 +0800651 if (usecase->type == PCM_CAPTURE)
652 snd_device = usecase->in_snd_device;
653 else
654 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800655 strcpy(mixer_path, use_case_table[usecase->id]);
yixuanjiang509f0a72018-09-06 18:37:23 +0800656 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700657 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700658 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000659 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800660
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800661 ALOGV("%s: exit", __func__);
662 return 0;
663}
664
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800665int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700666 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800667{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700668 int i, num_devices = 0;
669 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800670 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800671 if (snd_device < SND_DEVICE_MIN ||
672 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800673 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800674 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800675 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700676
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700677 platform_send_audio_calibration(adev->platform, snd_device);
678
vivek mehtade4849c2016-03-03 17:23:38 -0800679 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700680 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700681 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800682 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700683 }
684
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700685 /* due to the possibility of calibration overwrite between listen
686 and audio, notify sound trigger hal before audio calibration is sent */
687 audio_extn_sound_trigger_update_device_status(snd_device,
688 ST_EVENT_SND_DEVICE_BUSY);
689
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700690 if (audio_extn_spkr_prot_is_enabled())
691 audio_extn_spkr_prot_calib_cancel(adev);
692
zhaoyang yin4211fad2015-06-04 21:13:25 +0800693 audio_extn_dsm_feedback_enable(adev, snd_device, true);
694
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700695 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800696 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
juyuchen1d05ba32018-03-31 16:03:51 +0800697 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700698 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
699 audio_extn_spkr_prot_is_enabled()) {
Aniket Kumar Lata9d6679a2018-04-11 18:13:23 -0700700 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800701 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700702 }
703 if (audio_extn_spkr_prot_start_processing(snd_device)) {
704 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800705 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700706 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700707 } else if (platform_can_split_snd_device(snd_device,
708 &num_devices,
709 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700710 for (i = 0; i < num_devices; i++) {
711 enable_snd_device(adev, new_snd_devices[i]);
712 }
vivek mehtab6506412015-08-07 16:55:17 -0700713 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700714 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800715 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
716 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
717 ALOGE(" %s: Invalid sound device returned", __func__);
718 goto on_error;
719 }
Ed Tam70b5c142016-03-21 19:14:29 -0700720
Eric Laurent2e140aa2016-06-30 17:14:46 -0700721 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Aniket Kumar Lataa158e862018-05-11 17:28:40 -0700722
723 if (is_a2dp_device(snd_device) &&
724 (audio_extn_a2dp_start_playback() < 0)) {
725 ALOGE("%s: failed to configure A2DP control path", __func__);
726 goto on_error;
727 }
728
vivek mehtade4849c2016-03-03 17:23:38 -0800729 audio_route_apply_and_update_path(adev->audio_route, device_name);
730 }
731on_success:
732 adev->snd_dev_ref_cnt[snd_device]++;
733 ret_val = 0;
734on_error:
735 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800736}
737
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800738int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700739 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800740{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700741 int i, num_devices = 0;
742 snd_device_t new_snd_devices[2];
743
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800744 if (snd_device < SND_DEVICE_MIN ||
745 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800746 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800747 return -EINVAL;
748 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700749 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
750 ALOGE("%s: device ref cnt is already 0", __func__);
751 return -EINVAL;
752 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800753 audio_extn_tfa_98xx_disable_speaker(snd_device);
754
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700755 adev->snd_dev_ref_cnt[snd_device]--;
756 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800757 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800758
759 if (is_a2dp_device(snd_device))
760 audio_extn_a2dp_stop_playback();
761
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700762 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800763 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700764 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700765 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
766 audio_extn_spkr_prot_is_enabled()) {
767 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700768
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700769 // FIXME b/65363602: bullhead is the only Nexus with audio_extn_spkr_prot_is_enabled()
770 // and does not use speaker swap. As this code causes a problem with device enable ref
771 // counting we remove it for now.
vivek mehtae59cfb22017-06-16 15:57:11 -0700772 // when speaker device is disabled, reset swap.
773 // will be renabled on usecase start
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700774 // platform_set_swap_channels(adev, false);
vivek mehtae59cfb22017-06-16 15:57:11 -0700775
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700776 } else if (platform_can_split_snd_device(snd_device,
777 &num_devices,
778 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700779 for (i = 0; i < num_devices; i++) {
780 disable_snd_device(adev, new_snd_devices[i]);
781 }
vivek mehtab6506412015-08-07 16:55:17 -0700782 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700783 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800784 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
785 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
786 ALOGE(" %s: Invalid sound device returned", __func__);
787 return -EINVAL;
788 }
789
Eric Laurent2e140aa2016-06-30 17:14:46 -0700790 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800791 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700792 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700793 audio_extn_sound_trigger_update_device_status(snd_device,
794 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700795 }
vivek mehtab6506412015-08-07 16:55:17 -0700796
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800797 return 0;
798}
799
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700800/*
801 legend:
802 uc - existing usecase
803 new_uc - new usecase
804 d1, d11, d2 - SND_DEVICE enums
805 a1, a2 - corresponding ANDROID device enums
806 B, B1, B2 - backend strings
807
808case 1
809 uc->dev d1 (a1) B1
810 new_uc->dev d1 (a1), d2 (a2) B1, B2
811
812 resolution: disable and enable uc->dev on d1
813
814case 2
815 uc->dev d1 (a1) B1
816 new_uc->dev d11 (a1) B1
817
818 resolution: need to switch uc since d1 and d11 are related
819 (e.g. speaker and voice-speaker)
820 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
821
822case 3
823 uc->dev d1 (a1) B1
824 new_uc->dev d2 (a2) B2
825
826 resolution: no need to switch uc
827
828case 4
829 uc->dev d1 (a1) B
830 new_uc->dev d2 (a2) B
831
832 resolution: disable enable uc-dev on d2 since backends match
833 we cannot enable two streams on two different devices if they
834 share the same backend. e.g. if offload is on speaker device using
835 QUAD_MI2S backend and a low-latency stream is started on voice-handset
836 using the same backend, offload must also be switched to voice-handset.
837
838case 5
839 uc->dev d1 (a1) B
840 new_uc->dev d1 (a1), d2 (a2) B
841
842 resolution: disable enable uc-dev on d2 since backends match
843 we cannot enable two streams on two different devices if they
844 share the same backend.
845
846case 6
847 uc->dev d1 a1 B1
848 new_uc->dev d2 a1 B2
849
850 resolution: no need to switch
851
852case 7
853
854 uc->dev d1 (a1), d2 (a2) B1, B2
855 new_uc->dev d1 B1
856
857 resolution: no need to switch
858
859*/
860static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
861 struct audio_usecase *new_uc,
862 snd_device_t new_snd_device)
863{
864 audio_devices_t a1 = uc->stream.out->devices;
865 audio_devices_t a2 = new_uc->stream.out->devices;
866
867 snd_device_t d1 = uc->out_snd_device;
868 snd_device_t d2 = new_snd_device;
869
870 // Treat as a special case when a1 and a2 are not disjoint
871 if ((a1 != a2) && (a1 & a2)) {
872 snd_device_t d3[2];
873 int num_devices = 0;
874 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
875 &num_devices,
876 d3);
877 if (ret < 0) {
878 if (ret != -ENOSYS) {
879 ALOGW("%s failed to split snd_device %d",
880 __func__,
881 popcount(a1) > 1 ? d1 : d2);
882 }
883 goto end;
884 }
885
886 // NB: case 7 is hypothetical and isn't a practical usecase yet.
887 // But if it does happen, we need to give priority to d2 if
888 // the combo devices active on the existing usecase share a backend.
889 // This is because we cannot have a usecase active on a combo device
890 // and a new usecase requests one device in this combo pair.
891 if (platform_check_backends_match(d3[0], d3[1])) {
892 return d2; // case 5
893 } else {
894 return d1; // case 1
895 }
896 } else {
897 if (platform_check_backends_match(d1, d2)) {
898 return d2; // case 2, 4
899 } else {
900 return d1; // case 6, 3
901 }
902 }
903
904end:
905 return d2; // return whatever was calculated before.
906}
907
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700908static void check_and_route_playback_usecases(struct audio_device *adev,
909 struct audio_usecase *uc_info,
910 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700911{
912 struct listnode *node;
913 struct audio_usecase *usecase;
914 bool switch_device[AUDIO_USECASE_MAX];
915 int i, num_uc_to_switch = 0;
916
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700917 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
918 uc_info,
919 snd_device);
David Linee3fe402017-03-13 10:00:42 -0700920
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800921 /* For a2dp device reconfigure all active sessions
922 * with new AFE encoder format based on a2dp state
923 */
924 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Aniket Kumar Lata9723a962018-05-16 17:41:55 -0700925 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
926 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800927 audio_extn_a2dp_is_force_device_switch()) {
928 force_routing = true;
929 }
930
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700931 /*
932 * This function is to make sure that all the usecases that are active on
933 * the hardware codec backend are always routed to any one device that is
934 * handled by the hardware codec.
935 * For example, if low-latency and deep-buffer usecases are currently active
936 * on speaker and out_set_parameters(headset) is received on low-latency
937 * output, then we have to make sure deep-buffer is also switched to headset,
938 * because of the limitation that both the devices cannot be enabled
939 * at the same time as they share the same backend.
940 */
941 /* Disable all the usecases on the shared backend other than the
942 specified usecase */
943 for (i = 0; i < AUDIO_USECASE_MAX; i++)
944 switch_device[i] = false;
945
946 list_for_each(node, &adev->usecase_list) {
947 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700948 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
949 continue;
950
951 if (force_routing ||
952 (usecase->out_snd_device != snd_device &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -0700953 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
954 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700955 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700956 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
957 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700958 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700959 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700960 switch_device[usecase->id] = true;
961 num_uc_to_switch++;
962 }
963 }
964
965 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700966 list_for_each(node, &adev->usecase_list) {
967 usecase = node_to_item(node, struct audio_usecase, list);
968 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700969 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900970 }
971 }
972
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700973 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900974 list_for_each(node, &adev->usecase_list) {
975 usecase = node_to_item(node, struct audio_usecase, list);
976 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700977 d_device = derive_playback_snd_device(usecase, uc_info,
978 snd_device);
979 enable_snd_device(adev, d_device);
980 /* Update the out_snd_device before enabling the audio route */
981 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700982 }
983 }
984
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700985 /* Re-route all the usecases on the shared backend other than the
986 specified usecase to new snd devices */
987 list_for_each(node, &adev->usecase_list) {
988 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700989 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700990 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700991 }
992 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700993 }
994}
995
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700996static void check_and_route_capture_usecases(struct audio_device *adev,
997 struct audio_usecase *uc_info,
998 snd_device_t snd_device)
999{
1000 struct listnode *node;
1001 struct audio_usecase *usecase;
1002 bool switch_device[AUDIO_USECASE_MAX];
1003 int i, num_uc_to_switch = 0;
1004
vivek mehta4ed66e62016-04-15 23:33:34 -07001005 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
1006
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001007 /*
1008 * This function is to make sure that all the active capture usecases
1009 * are always routed to the same input sound device.
1010 * For example, if audio-record and voice-call usecases are currently
1011 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1012 * is received for voice call then we have to make sure that audio-record
1013 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1014 * because of the limitation that two devices cannot be enabled
1015 * at the same time if they share the same backend.
1016 */
1017 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1018 switch_device[i] = false;
1019
1020 list_for_each(node, &adev->usecase_list) {
1021 usecase = node_to_item(node, struct audio_usecase, list);
1022 if (usecase->type != PCM_PLAYBACK &&
1023 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -07001024 usecase->in_snd_device != snd_device &&
1025 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001026 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1027 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001028 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001029 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001030 switch_device[usecase->id] = true;
1031 num_uc_to_switch++;
1032 }
1033 }
1034
1035 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001036 list_for_each(node, &adev->usecase_list) {
1037 usecase = node_to_item(node, struct audio_usecase, list);
1038 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001039 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001040 }
1041 }
1042
1043 list_for_each(node, &adev->usecase_list) {
1044 usecase = node_to_item(node, struct audio_usecase, list);
1045 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001046 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001047 }
1048 }
1049
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001050 /* Re-route all the usecases on the shared backend other than the
1051 specified usecase to new snd devices */
1052 list_for_each(node, &adev->usecase_list) {
1053 usecase = node_to_item(node, struct audio_usecase, list);
1054 /* Update the in_snd_device only before enabling the audio route */
1055 if (switch_device[usecase->id] ) {
1056 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001057 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001058 }
1059 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001060 }
1061}
1062
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001063/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001064static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001065{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001066 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001067 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001068
1069 switch (channels) {
1070 /*
1071 * Do not handle stereo output in Multi-channel cases
1072 * Stereo case is handled in normal playback path
1073 */
1074 case 6:
1075 ALOGV("%s: HDMI supports 5.1", __func__);
1076 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1077 break;
1078 case 8:
1079 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
1080 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1081 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
1082 break;
1083 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001084 ALOGE("HDMI does not support multi channel playback");
1085 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001086 break;
1087 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001088 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001089}
1090
Andy Hung18859412017-08-09 11:47:21 -07001091static ssize_t read_usb_sup_sample_rates(bool is_playback,
1092 uint32_t *supported_sample_rates,
1093 uint32_t max_rates)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001094{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001095 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1096 supported_sample_rates,
1097 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001098#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001099 for (ssize_t i=0; i<count; i++) {
1100 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1101 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001102 }
1103#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001104 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001105}
1106
Haynes Mathew George569b7482017-05-08 14:44:27 -07001107static int read_usb_sup_channel_masks(bool is_playback,
1108 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001109 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001110{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001111 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001112 int channel_count;
1113 uint32_t num_masks = 0;
1114 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1115 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001116 }
Eric Laurent74b55762017-07-09 17:04:53 -07001117 if (is_playback) {
Andy Hung6c1afb12017-12-22 11:34:41 -08001118 // start from 2 channels as framework currently doesn't support mono.
1119 // TODO: consider only supporting channel index masks beyond stereo here.
1120 for (channel_count = FCC_2;
1121 channel_count <= channels && num_masks < max_masks;
1122 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001123 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1124 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001125 for (channel_count = FCC_2;
1126 channel_count <= channels && num_masks < max_masks;
1127 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001128 supported_channel_masks[num_masks++] =
1129 audio_channel_mask_for_index_assignment_from_count(channel_count);
1130 }
1131 } else {
1132 // For capture we report all supported channel masks from 1 channel up.
1133 channel_count = MIN_CHANNEL_COUNT;
1134 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1135 // indexed mask
1136 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1137 supported_channel_masks[num_masks++] =
1138 audio_channel_in_mask_from_count(channel_count);
1139 }
1140 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001141#ifdef NDEBUG
1142 for (size_t i = 0; i < num_masks; ++i) {
1143 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1144 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
1145 }
1146#endif
Eric Laurent74b55762017-07-09 17:04:53 -07001147 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001148}
1149
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001150static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001151 audio_format_t *supported_formats,
1152 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001153{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001154 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001155 switch (bitwidth) {
1156 case 24:
1157 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001158 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001159 break;
1160 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001161 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001162 break;
1163 case 16:
1164 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001165 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001166 break;
1167 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001168 ALOGV("%s: %s supported format %d", __func__,
1169 is_playback ? "P" : "C", bitwidth);
1170 return 1;
1171}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001172
Haynes Mathew George569b7482017-05-08 14:44:27 -07001173static int read_usb_sup_params_and_compare(bool is_playback,
1174 audio_format_t *format,
1175 audio_format_t *supported_formats,
1176 uint32_t max_formats,
1177 audio_channel_mask_t *mask,
1178 audio_channel_mask_t *supported_channel_masks,
1179 uint32_t max_masks,
1180 uint32_t *rate,
1181 uint32_t *supported_sample_rates,
1182 uint32_t max_rates) {
1183 int ret = 0;
1184 int num_formats;
1185 int num_masks;
1186 int num_rates;
1187 int i;
1188
1189 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1190 max_formats);
1191 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1192 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001193
Haynes Mathew George569b7482017-05-08 14:44:27 -07001194 num_rates = read_usb_sup_sample_rates(is_playback,
1195 supported_sample_rates, max_rates);
1196
1197#define LUT(table, len, what, dflt) \
1198 for (i=0; i<len && (table[i] != what); i++); \
1199 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1200
1201 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1202 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1203 LUT(supported_sample_rates, num_rates, *rate, 0);
1204
1205#undef LUT
1206 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001207}
1208
Andy Hungd9653bd2017-08-01 19:31:39 -07001209static bool is_usb_ready(struct audio_device *adev, bool is_playback)
1210{
1211 // Check if usb is ready.
1212 // The usb device may have been removed quickly after insertion and hence
1213 // no longer available. This will show up as empty channel masks, or rates.
1214
1215 pthread_mutex_lock(&adev->lock);
1216 uint32_t supported_sample_rate;
1217
1218 // we consider usb ready if we can fetch at least one sample rate.
1219 const bool ready = read_usb_sup_sample_rates(
1220 is_playback, &supported_sample_rate, 1 /* max_rates */) > 0;
1221 pthread_mutex_unlock(&adev->lock);
1222 return ready;
1223}
1224
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001225static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1226{
1227 struct audio_usecase *usecase;
1228 struct listnode *node;
1229
1230 list_for_each(node, &adev->usecase_list) {
1231 usecase = node_to_item(node, struct audio_usecase, list);
1232 if (usecase->type == VOICE_CALL) {
1233 ALOGV("%s: usecase id %d", __func__, usecase->id);
1234 return usecase->id;
1235 }
1236 }
1237 return USECASE_INVALID;
1238}
1239
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001240struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1241 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001242{
1243 struct audio_usecase *usecase;
1244 struct listnode *node;
1245
1246 list_for_each(node, &adev->usecase_list) {
1247 usecase = node_to_item(node, struct audio_usecase, list);
1248 if (usecase->id == uc_id)
1249 return usecase;
1250 }
1251 return NULL;
1252}
1253
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001254static bool force_device_switch(struct audio_usecase *usecase)
1255{
1256 if (usecase->stream.out == NULL) {
1257 ALOGE("%s: stream.out is NULL", __func__);
1258 return false;
1259 }
1260
1261 // Force all A2DP output devices to reconfigure for proper AFE encode format
1262 // Also handle a case where in earlier A2DP start failed as A2DP stream was
1263 // in suspended state, hence try to trigger a retry when we again get a routing request.
1264 if ((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
1265 audio_extn_a2dp_is_force_device_switch()) {
1266 ALOGD("%s: Force A2DP device switch to update new encoder config", __func__);
1267 return true;
1268 }
1269
1270 return false;
1271}
1272
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001273int select_devices(struct audio_device *adev,
1274 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001275{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001276 snd_device_t out_snd_device = SND_DEVICE_NONE;
1277 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001278 struct audio_usecase *usecase = NULL;
1279 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001280 struct audio_usecase *hfp_usecase = NULL;
1281 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001282 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001283 int status = 0;
Eric Laurentf4520b02017-09-20 18:31:58 -07001284 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1285 USECASE_AUDIO_PLAYBACK_VOIP);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001286
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001287 usecase = get_usecase_from_list(adev, uc_id);
1288 if (usecase == NULL) {
1289 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1290 return -EINVAL;
1291 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001292
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001293 if ((usecase->type == VOICE_CALL) ||
1294 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001295 out_snd_device = platform_get_output_snd_device(adev->platform,
1296 usecase->stream.out->devices);
1297 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001298 usecase->devices = usecase->stream.out->devices;
1299 } else {
1300 /*
1301 * If the voice call is active, use the sound devices of voice call usecase
1302 * so that it would not result any device switch. All the usecases will
1303 * be switched to new device when select_devices() is called for voice call
1304 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001305 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001306 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001307 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001308 vc_usecase = get_usecase_from_list(adev,
1309 get_voice_usecase_id_from_list(adev));
1310 if ((vc_usecase != NULL) &&
1311 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1312 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001313 in_snd_device = vc_usecase->in_snd_device;
1314 out_snd_device = vc_usecase->out_snd_device;
1315 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001316 } else if (audio_extn_hfp_is_active(adev)) {
1317 hfp_ucid = audio_extn_hfp_get_usecase();
1318 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1319 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1320 in_snd_device = hfp_usecase->in_snd_device;
1321 out_snd_device = hfp_usecase->out_snd_device;
1322 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001323 }
1324 if (usecase->type == PCM_PLAYBACK) {
1325 usecase->devices = usecase->stream.out->devices;
1326 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001327 if (out_snd_device == SND_DEVICE_NONE) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001328 struct stream_out *voip_out = adev->primary_output;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001329
Eric Laurentb23d5282013-05-14 15:27:20 -07001330 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001331 usecase->stream.out->devices);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001332
1333 if (voip_usecase)
1334 voip_out = voip_usecase->stream.out;
1335
1336 if (usecase->stream.out == voip_out &&
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001337 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001338 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001339 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001340 select_devices(adev, adev->active_input->usecase);
1341 }
1342 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001343 } else if (usecase->type == PCM_CAPTURE) {
1344 usecase->devices = usecase->stream.in->device;
1345 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001346 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001347 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001348 if (adev->active_input &&
1349 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1350 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001351
1352 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1353 USECASE_AUDIO_PLAYBACK_VOIP);
1354
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001355 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001356 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1357 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001358 } else if (voip_usecase) {
1359 out_device = voip_usecase->stream.out->devices;
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001360 } else if (adev->primary_output) {
1361 out_device = adev->primary_output->devices;
1362 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001363 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001364 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001365 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001366 }
1367 }
1368
1369 if (out_snd_device == usecase->out_snd_device &&
1370 in_snd_device == usecase->in_snd_device) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001371 if (!force_device_switch(usecase))
1372 return 0;
1373 }
1374
1375 if (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready()) {
1376 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1377 return 0;
1378 }
1379
Aniket Kumar Lata9723a962018-05-16 17:41:55 -07001380 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
1381 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001382 (!audio_extn_a2dp_is_ready())) {
1383 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
juyuchen9baad392018-06-05 19:02:10 +08001384 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
1385 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
1386 else
1387 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001388 }
1389
juyuchen66c4ecf2018-08-06 15:39:34 +08001390 if (usecase->id == USECASE_INCALL_MUSIC_UPLINK) {
1391 out_snd_device = SND_DEVICE_OUT_VOICE_MUSIC_TX;
1392 }
1393
Eric Laurent2bafff12016-03-17 12:17:23 -07001394 if (out_snd_device != SND_DEVICE_NONE &&
1395 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1396 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1397 __func__,
1398 use_case_table[uc_id],
1399 adev->last_logged_snd_device[uc_id][0],
1400 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1401 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1402 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1403 -1,
1404 out_snd_device,
1405 platform_get_snd_device_name(out_snd_device),
1406 platform_get_snd_device_acdb_id(out_snd_device));
1407 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1408 }
1409 if (in_snd_device != SND_DEVICE_NONE &&
1410 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1411 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1412 __func__,
1413 use_case_table[uc_id],
1414 adev->last_logged_snd_device[uc_id][1],
1415 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1416 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1417 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1418 -1,
1419 in_snd_device,
1420 platform_get_snd_device_name(in_snd_device),
1421 platform_get_snd_device_acdb_id(in_snd_device));
1422 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1423 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001424
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001425 /*
1426 * Limitation: While in call, to do a device switch we need to disable
1427 * and enable both RX and TX devices though one of them is same as current
1428 * device.
1429 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001430 if ((usecase->type == VOICE_CALL) &&
1431 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1432 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001433 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001434 /* Disable sidetone only if voice call already exists */
1435 if (voice_is_call_state_active(adev))
1436 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001437 }
1438
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001439 /* Disable current sound devices */
1440 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001441 disable_audio_route(adev, usecase);
1442 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001443 }
1444
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001445 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001446 disable_audio_route(adev, usecase);
1447 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001448 }
1449
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001450 /* Applicable only on the targets that has external modem.
1451 * New device information should be sent to modem before enabling
1452 * the devices to reduce in-call device switch time.
1453 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001454 if ((usecase->type == VOICE_CALL) &&
1455 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1456 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001457 status = platform_switch_voice_call_enable_device_config(adev->platform,
1458 out_snd_device,
1459 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001460 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001461
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001462 /* Enable new sound devices */
1463 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001464 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001465 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) ||
1466 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001467 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001468 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001469 }
1470
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001471 if (in_snd_device != SND_DEVICE_NONE) {
1472 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001473 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001474 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001475
Eric Laurentb23d5282013-05-14 15:27:20 -07001476 if (usecase->type == VOICE_CALL)
1477 status = platform_switch_voice_call_device_post(adev->platform,
1478 out_snd_device,
1479 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001480
sangwoo170731f2013-06-08 15:36:36 +09001481 usecase->in_snd_device = in_snd_device;
1482 usecase->out_snd_device = out_snd_device;
1483
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001484 audio_extn_tfa_98xx_set_mode();
1485
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001486 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001487
Jasmine Cha70771b62018-05-15 15:02:43 +08001488 audio_extn_ma_set_device(usecase);
jasmine cha270b7762018-03-30 15:41:33 +08001489
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001490 /* Applicable only on the targets that has external modem.
1491 * Enable device command should be sent to modem only after
1492 * enabling voice call mixer controls
1493 */
vivek mehta765eb642015-08-07 19:46:06 -07001494 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001495 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1496 out_snd_device,
1497 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001498 /* Enable sidetone only if voice call already exists */
1499 if (voice_is_call_state_active(adev))
1500 voice_set_sidetone(adev, out_snd_device, true);
1501 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001502
Eric Laurentf4520b02017-09-20 18:31:58 -07001503 if (usecase == voip_usecase) {
1504 struct stream_out *voip_out = voip_usecase->stream.out;
1505 audio_extn_utils_send_app_type_gain(adev,
1506 voip_out->app_type_cfg.app_type,
1507 &voip_out->app_type_cfg.gain[0]);
1508 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001509 return status;
1510}
1511
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001512static int stop_input_stream(struct stream_in *in)
1513{
1514 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001515 struct audio_usecase *uc_info;
1516 struct audio_device *adev = in->dev;
1517
Eric Laurent994a6932013-07-17 11:51:42 -07001518 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001519 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001520
1521 if (adev->active_input) {
1522 if (adev->active_input->usecase == in->usecase) {
1523 adev->active_input = NULL;
1524 } else {
1525 ALOGW("%s adev->active_input->usecase %s, v/s in->usecase %s",
1526 __func__,
1527 use_case_table[adev->active_input->usecase],
1528 use_case_table[in->usecase]);
1529 }
1530 }
1531
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001532 uc_info = get_usecase_from_list(adev, in->usecase);
1533 if (uc_info == NULL) {
1534 ALOGE("%s: Could not find the usecase (%d) in the list",
1535 __func__, in->usecase);
1536 return -EINVAL;
1537 }
1538
vivek mehta781065c2017-04-04 12:55:01 -07001539 /* Close in-call recording streams */
1540 voice_check_and_stop_incall_rec_usecase(adev, in);
1541
Eric Laurent150dbfe2013-02-27 14:31:02 -08001542 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001543 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001544
1545 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001546 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001547
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001548 list_remove(&uc_info->list);
1549 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001550
Eric Laurent994a6932013-07-17 11:51:42 -07001551 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001552 return ret;
1553}
1554
1555int start_input_stream(struct stream_in *in)
1556{
1557 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001558 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001559 struct audio_usecase *uc_info;
1560 struct audio_device *adev = in->dev;
1561
Eric Laurent994a6932013-07-17 11:51:42 -07001562 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001563
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001564 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1565 return -EIO;
1566
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001567 if (in->card_status == CARD_STATUS_OFFLINE ||
1568 adev->card_status == CARD_STATUS_OFFLINE) {
1569 ALOGW("in->card_status or adev->card_status offline, try again");
1570 ret = -EAGAIN;
1571 goto error_config;
1572 }
1573
vivek mehta781065c2017-04-04 12:55:01 -07001574 /* Check if source matches incall recording usecase criteria */
1575 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1576 if (ret)
1577 goto error_config;
1578 else
1579 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1580
Eric Laurentb23d5282013-05-14 15:27:20 -07001581 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001582 if (in->pcm_device_id < 0) {
1583 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1584 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001585 ret = -EINVAL;
1586 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001587 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001588
1589 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001590 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1591 uc_info->id = in->usecase;
1592 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001593 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001594 uc_info->devices = in->device;
1595 uc_info->in_snd_device = SND_DEVICE_NONE;
1596 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001597
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001598 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001599
Wei Wangf4837d52017-11-21 14:51:20 -08001600 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001601 audio_extn_perf_lock_acquire();
1602
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001603 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001604
Eric Laurent0e46adf2016-12-16 12:49:24 -08001605 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001606 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001607 ALOGE("%s: pcm stream not ready", __func__);
1608 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001609 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001610 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001611 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001612 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1613 goto error_open;
1614 }
1615 } else {
1616 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1617 unsigned int pcm_open_retry_count = 0;
1618
1619 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1620 flags |= PCM_MMAP | PCM_NOIRQ;
1621 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1622 } else if (in->realtime) {
1623 flags |= PCM_MMAP | PCM_NOIRQ;
1624 }
1625
1626 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1627 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1628
1629 while (1) {
1630 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1631 flags, &in->config);
1632 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1633 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1634 if (in->pcm != NULL) {
1635 pcm_close(in->pcm);
1636 in->pcm = NULL;
1637 }
1638 if (pcm_open_retry_count-- == 0) {
1639 ret = -EIO;
1640 goto error_open;
1641 }
1642 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1643 continue;
1644 }
1645 break;
1646 }
1647
1648 ALOGV("%s: pcm_prepare", __func__);
1649 ret = pcm_prepare(in->pcm);
1650 if (ret < 0) {
1651 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001652 pcm_close(in->pcm);
1653 in->pcm = NULL;
1654 goto error_open;
1655 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001656 if (in->realtime) {
1657 ret = pcm_start(in->pcm);
1658 if (ret < 0) {
1659 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1660 pcm_close(in->pcm);
1661 in->pcm = NULL;
1662 goto error_open;
1663 }
1664 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001665 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001666 register_in_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001667 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001668 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001669 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001670
Eric Laurent0e46adf2016-12-16 12:49:24 -08001671 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001672
1673error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001674 stop_input_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001675 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001676 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001677
1678error_config:
1679 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001680 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001681 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001682}
1683
Eric Laurenta1478072015-09-21 17:21:52 -07001684void lock_input_stream(struct stream_in *in)
1685{
1686 pthread_mutex_lock(&in->pre_lock);
1687 pthread_mutex_lock(&in->lock);
1688 pthread_mutex_unlock(&in->pre_lock);
1689}
1690
1691void lock_output_stream(struct stream_out *out)
1692{
1693 pthread_mutex_lock(&out->pre_lock);
1694 pthread_mutex_lock(&out->lock);
1695 pthread_mutex_unlock(&out->pre_lock);
1696}
1697
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001698/* must be called with out->lock locked */
1699static int send_offload_cmd_l(struct stream_out* out, int command)
1700{
1701 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1702
1703 ALOGVV("%s %d", __func__, command);
1704
1705 cmd->cmd = command;
1706 list_add_tail(&out->offload_cmd_list, &cmd->node);
1707 pthread_cond_signal(&out->offload_cond);
1708 return 0;
1709}
1710
1711/* must be called iwth out->lock locked */
1712static void stop_compressed_output_l(struct stream_out *out)
1713{
1714 out->offload_state = OFFLOAD_STATE_IDLE;
1715 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001716 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001717 if (out->compr != NULL) {
1718 compress_stop(out->compr);
1719 while (out->offload_thread_blocked) {
1720 pthread_cond_wait(&out->cond, &out->lock);
1721 }
1722 }
1723}
1724
1725static void *offload_thread_loop(void *context)
1726{
1727 struct stream_out *out = (struct stream_out *) context;
1728 struct listnode *item;
1729
1730 out->offload_state = OFFLOAD_STATE_IDLE;
1731 out->playback_started = 0;
1732
1733 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1734 set_sched_policy(0, SP_FOREGROUND);
1735 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1736
1737 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001738 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001739 for (;;) {
1740 struct offload_cmd *cmd = NULL;
1741 stream_callback_event_t event;
1742 bool send_callback = false;
1743
1744 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1745 __func__, list_empty(&out->offload_cmd_list),
1746 out->offload_state);
1747 if (list_empty(&out->offload_cmd_list)) {
1748 ALOGV("%s SLEEPING", __func__);
1749 pthread_cond_wait(&out->offload_cond, &out->lock);
1750 ALOGV("%s RUNNING", __func__);
1751 continue;
1752 }
1753
1754 item = list_head(&out->offload_cmd_list);
1755 cmd = node_to_item(item, struct offload_cmd, node);
1756 list_remove(item);
1757
1758 ALOGVV("%s STATE %d CMD %d out->compr %p",
1759 __func__, out->offload_state, cmd->cmd, out->compr);
1760
1761 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1762 free(cmd);
1763 break;
1764 }
1765
1766 if (out->compr == NULL) {
1767 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001768 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001769 pthread_cond_signal(&out->cond);
1770 continue;
1771 }
1772 out->offload_thread_blocked = true;
1773 pthread_mutex_unlock(&out->lock);
1774 send_callback = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001775 switch (cmd->cmd) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001776 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1777 compress_wait(out->compr, -1);
1778 send_callback = true;
1779 event = STREAM_CBK_EVENT_WRITE_READY;
1780 break;
1781 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001782 compress_next_track(out->compr);
1783 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001784 send_callback = true;
1785 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001786 /* Resend the metadata for next iteration */
1787 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001788 break;
1789 case OFFLOAD_CMD_DRAIN:
1790 compress_drain(out->compr);
1791 send_callback = true;
1792 event = STREAM_CBK_EVENT_DRAIN_READY;
1793 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001794 case OFFLOAD_CMD_ERROR:
1795 send_callback = true;
1796 event = STREAM_CBK_EVENT_ERROR;
1797 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001798 default:
1799 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1800 break;
1801 }
Eric Laurenta1478072015-09-21 17:21:52 -07001802 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001803 out->offload_thread_blocked = false;
1804 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001805 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001806 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001807 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001808 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001809 free(cmd);
1810 }
1811
1812 pthread_cond_signal(&out->cond);
1813 while (!list_empty(&out->offload_cmd_list)) {
1814 item = list_head(&out->offload_cmd_list);
1815 list_remove(item);
1816 free(node_to_item(item, struct offload_cmd, node));
1817 }
1818 pthread_mutex_unlock(&out->lock);
1819
1820 return NULL;
1821}
1822
1823static int create_offload_callback_thread(struct stream_out *out)
1824{
1825 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1826 list_init(&out->offload_cmd_list);
1827 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1828 offload_thread_loop, out);
1829 return 0;
1830}
1831
1832static int destroy_offload_callback_thread(struct stream_out *out)
1833{
Eric Laurenta1478072015-09-21 17:21:52 -07001834 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001835 stop_compressed_output_l(out);
1836 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1837
1838 pthread_mutex_unlock(&out->lock);
1839 pthread_join(out->offload_thread, (void **) NULL);
1840 pthread_cond_destroy(&out->offload_cond);
1841
1842 return 0;
1843}
1844
Eric Laurent07eeafd2013-10-06 12:52:49 -07001845static bool allow_hdmi_channel_config(struct audio_device *adev)
1846{
1847 struct listnode *node;
1848 struct audio_usecase *usecase;
1849 bool ret = true;
1850
1851 list_for_each(node, &adev->usecase_list) {
1852 usecase = node_to_item(node, struct audio_usecase, list);
1853 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1854 /*
1855 * If voice call is already existing, do not proceed further to avoid
1856 * disabling/enabling both RX and TX devices, CSD calls, etc.
1857 * Once the voice call done, the HDMI channels can be configured to
1858 * max channels of remaining use cases.
1859 */
1860 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001861 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001862 __func__);
1863 ret = false;
1864 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001865 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1866 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001867 "no change in HDMI channels", __func__);
1868 ret = false;
1869 break;
1870 }
1871 }
1872 }
1873 return ret;
1874}
1875
1876static int check_and_set_hdmi_channels(struct audio_device *adev,
1877 unsigned int channels)
1878{
1879 struct listnode *node;
1880 struct audio_usecase *usecase;
1881
1882 /* Check if change in HDMI channel config is allowed */
1883 if (!allow_hdmi_channel_config(adev))
1884 return 0;
1885
1886 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001887 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001888 return 0;
1889 }
1890
1891 platform_set_hdmi_channels(adev->platform, channels);
1892 adev->cur_hdmi_channels = channels;
1893
1894 /*
1895 * Deroute all the playback streams routed to HDMI so that
1896 * the back end is deactivated. Note that backend will not
1897 * be deactivated if any one stream is connected to it.
1898 */
1899 list_for_each(node, &adev->usecase_list) {
1900 usecase = node_to_item(node, struct audio_usecase, list);
1901 if (usecase->type == PCM_PLAYBACK &&
1902 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001903 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001904 }
1905 }
1906
1907 /*
1908 * Enable all the streams disabled above. Now the HDMI backend
1909 * will be activated with new channel configuration
1910 */
1911 list_for_each(node, &adev->usecase_list) {
1912 usecase = node_to_item(node, struct audio_usecase, list);
1913 if (usecase->type == PCM_PLAYBACK &&
1914 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001915 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001916 }
1917 }
1918
1919 return 0;
1920}
1921
Haynes Mathew George65f6b432018-02-27 17:44:55 -08001922static int check_and_set_usb_service_interval(struct audio_device *adev,
1923 struct audio_usecase *uc_info,
1924 bool min)
1925{
1926 struct listnode *node;
1927 struct audio_usecase *usecase;
1928 bool switch_usecases = false;
1929 bool reconfig = false;
1930
1931 if ((uc_info->id != USECASE_AUDIO_PLAYBACK_MMAP) &&
1932 (uc_info->id != USECASE_AUDIO_PLAYBACK_ULL))
1933 return -1;
1934
1935 /* set if the valid usecase do not already exist */
1936 list_for_each(node, &adev->usecase_list) {
1937 usecase = node_to_item(node, struct audio_usecase, list);
1938 if (usecase->type == PCM_PLAYBACK &&
1939 (audio_is_usb_out_device(usecase->devices & AUDIO_DEVICE_OUT_ALL_USB))) {
1940 switch (usecase->id) {
1941 case USECASE_AUDIO_PLAYBACK_MMAP:
1942 case USECASE_AUDIO_PLAYBACK_ULL:
1943 // cannot reconfig while mmap/ull is present.
1944 return -1;
1945 default:
1946 switch_usecases = true;
1947 break;
1948 }
1949 }
1950 if (switch_usecases)
1951 break;
1952 }
1953 /*
1954 * client can try to set service interval in start_output_stream
1955 * to min or to 0 (i.e reset) in stop_output_stream .
1956 */
1957 unsigned long service_interval =
1958 audio_extn_usb_find_service_interval(min, true /*playback*/);
1959 int ret = platform_set_usb_service_interval(adev->platform,
1960 true /*playback*/,
1961 service_interval,
1962 &reconfig);
1963 /* no change or not supported or no active usecases */
1964 if (ret || !reconfig || !switch_usecases)
1965 return -1;
1966 return 0;
1967#undef VALID_USECASE
1968}
1969
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001970static int stop_output_stream(struct stream_out *out)
1971{
1972 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001973 struct audio_usecase *uc_info;
1974 struct audio_device *adev = out->dev;
HW Lee88512e92018-06-12 15:26:09 +08001975 bool has_voip_usecase =
1976 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001977
Eric Laurent994a6932013-07-17 11:51:42 -07001978 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001979 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001980 uc_info = get_usecase_from_list(adev, out->usecase);
1981 if (uc_info == NULL) {
1982 ALOGE("%s: Could not find the usecase (%d) in the list",
1983 __func__, out->usecase);
1984 return -EINVAL;
1985 }
1986
Haynes Mathew George41f86652014-06-17 14:22:15 -07001987 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1988 if (adev->visualizer_stop_output != NULL)
1989 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1990 if (adev->offload_effects_stop_output != NULL)
1991 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08001992 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
1993 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
1994 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07001995 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001996
Eric Laurent150dbfe2013-02-27 14:31:02 -08001997 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001998 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001999
2000 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002001 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002002
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002003 list_remove(&uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002004
Eric Laurent0499d4f2014-08-25 22:39:29 -05002005 audio_extn_extspk_update(adev->extspk);
2006
Eric Laurent07eeafd2013-10-06 12:52:49 -07002007 /* Must be called after removing the usecase from list */
2008 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2009 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
HW Lee88512e92018-06-12 15:26:09 +08002010 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002011 ret = check_and_set_usb_service_interval(adev, uc_info, false /*min*/);
2012 if (ret == 0) {
2013 /* default service interval was successfully updated,
2014 reopen USB backend with new service interval */
2015 check_and_route_playback_usecases(adev, uc_info, uc_info->out_snd_device);
2016 }
2017 ret = 0;
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07002018 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002019
HW Lee88512e92018-06-12 15:26:09 +08002020 if (has_voip_usecase ||
2021 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
2022 struct listnode *node;
2023 struct audio_usecase *usecase;
2024 list_for_each(node, &adev->usecase_list) {
2025 usecase = node_to_item(node, struct audio_usecase, list);
2026 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
2027 continue;
2028
2029 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
2030 __func__, usecase->id, use_case_table[usecase->id],
2031 out->usecase, use_case_table[out->usecase]);
2032 select_devices(adev, usecase->id);
2033 }
2034 }
2035
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002036 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07002037 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002038 return ret;
2039}
2040
2041int start_output_stream(struct stream_out *out)
2042{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002043 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002044 struct audio_usecase *uc_info;
2045 struct audio_device *adev = out->dev;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002046 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002047
Eric Laurent994a6932013-07-17 11:51:42 -07002048 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002049 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002050
2051 if (out->card_status == CARD_STATUS_OFFLINE ||
2052 adev->card_status == CARD_STATUS_OFFLINE) {
2053 ALOGW("out->card_status or adev->card_status offline, try again");
2054 ret = -EAGAIN;
2055 goto error_config;
2056 }
2057
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002058 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2059 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002060 if (out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002061 a2dp_combo = true;
2062 } else {
2063 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2064 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2065 ret = -EAGAIN;
2066 goto error_config;
2067 }
2068 }
2069 }
2070 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002071 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002072 if (out->pcm_device_id < 0) {
2073 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2074 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002075 ret = -EINVAL;
2076 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002077 }
2078
2079 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
2080 uc_info->id = out->usecase;
2081 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002082 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002083 uc_info->devices = out->devices;
2084 uc_info->in_snd_device = SND_DEVICE_NONE;
2085 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002086
Eric Laurent07eeafd2013-10-06 12:52:49 -07002087 /* This must be called before adding this usecase to the list */
2088 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2089 check_and_set_hdmi_channels(adev, out->config.channels);
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002090 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
2091 check_and_set_usb_service_interval(adev, uc_info, true /*min*/);
2092 /* USB backend is not reopened immediately.
2093 This is eventually done as part of select_devices */
2094 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002095
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002096 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002097
Wei Wangf4837d52017-11-21 14:51:20 -08002098 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002099 audio_extn_perf_lock_acquire();
2100
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002101 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2102 (!audio_extn_a2dp_is_ready())) {
2103 if (!a2dp_combo) {
2104 check_a2dp_restore_l(adev, out, false);
2105 } else {
2106 audio_devices_t dev = out->devices;
juyuchen9baad392018-06-05 19:02:10 +08002107 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2108 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2109 else
2110 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002111 select_devices(adev, out->usecase);
2112 out->devices = dev;
2113 }
2114 } else {
2115 select_devices(adev, out->usecase);
2116 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002117
Eric Laurent0499d4f2014-08-25 22:39:29 -05002118 audio_extn_extspk_update(adev->extspk);
2119
Andy Hung31aca912014-03-20 17:14:59 -07002120 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002121 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002122 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2123 out->pcm = NULL;
2124 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
2125 COMPRESS_IN, &out->compr_config);
2126 if (out->compr && !is_compress_ready(out->compr)) {
2127 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2128 compress_close(out->compr);
2129 out->compr = NULL;
2130 ret = -EIO;
2131 goto error_open;
2132 }
2133 if (out->offload_callback)
2134 compress_nonblock(out->compr, out->non_blocking);
2135
Aniket Kumar Lata72a3cea2018-04-06 13:56:37 -07002136 if (adev->visualizer_start_output != NULL) {
2137 int capture_device_id =
2138 platform_get_pcm_device_id(USECASE_AUDIO_RECORD_AFE_PROXY,
2139 PCM_CAPTURE);
2140 adev->visualizer_start_output(out->handle, out->pcm_device_id,
2141 adev->snd_card, capture_device_id);
2142 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002143 if (adev->offload_effects_start_output != NULL)
2144 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
2145 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002146 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002147 ALOGE("%s: pcm stream not ready", __func__);
2148 goto error_open;
2149 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002150 ret = pcm_start(out->pcm);
2151 if (ret < 0) {
2152 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2153 goto error_open;
2154 }
2155 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07002156 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002157 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002158
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002159 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2160 flags |= PCM_MMAP | PCM_NOIRQ;
2161 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002162 } else if (out->realtime) {
2163 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07002164 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002165
2166 while (1) {
2167 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2168 flags, &out->config);
2169 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2170 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2171 if (out->pcm != NULL) {
2172 pcm_close(out->pcm);
2173 out->pcm = NULL;
2174 }
2175 if (pcm_open_retry_count-- == 0) {
2176 ret = -EIO;
2177 goto error_open;
2178 }
2179 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2180 continue;
2181 }
2182 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002183 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002184 ALOGV("%s: pcm_prepare", __func__);
2185 if (pcm_is_ready(out->pcm)) {
2186 ret = pcm_prepare(out->pcm);
2187 if (ret < 0) {
2188 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2189 pcm_close(out->pcm);
2190 out->pcm = NULL;
2191 goto error_open;
2192 }
2193 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002194 if (out->realtime) {
2195 ret = pcm_start(out->pcm);
2196 if (ret < 0) {
2197 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
2198 pcm_close(out->pcm);
2199 out->pcm = NULL;
2200 goto error_open;
2201 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002202 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002203 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002204 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08002205 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002206 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002207 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07002208
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002209 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2210 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2211 audio_low_latency_hint_start();
2212 }
2213
vivek mehtae59cfb22017-06-16 15:57:11 -07002214 // consider a scenario where on pause lower layers are tear down.
2215 // so on resume, swap mixer control need to be sent only when
2216 // backend is active, hence rather than sending from enable device
2217 // sending it from start of streamtream
2218
2219 platform_set_swap_channels(adev, true);
2220
Eric Laurent994a6932013-07-17 11:51:42 -07002221 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002222 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002223error_open:
Wei Wangf4837d52017-11-21 14:51:20 -08002224 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002225 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002226 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002227error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002228 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002229}
2230
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002231static int check_input_parameters(uint32_t sample_rate,
2232 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07002233 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002234{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002235 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2236 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002237 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2238 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002239 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2240 return -EINVAL;
2241 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002242
Eric Laurent74b55762017-07-09 17:04:53 -07002243 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2244 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002245 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002246 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002247 return -EINVAL;
2248 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002249
2250 switch (sample_rate) {
2251 case 8000:
2252 case 11025:
2253 case 12000:
2254 case 16000:
2255 case 22050:
2256 case 24000:
2257 case 32000:
2258 case 44100:
2259 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002260 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002261 break;
2262 default:
vivek mehtadae44712015-07-27 14:13:18 -07002263 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002264 return -EINVAL;
2265 }
2266
2267 return 0;
2268}
2269
Kevin Rocarda325aa22018-04-03 09:15:52 -07002270/** Add a value in a list if not already present.
2271 * @return true if value was successfully inserted or already present,
2272 * false if the list is full and does not contain the value.
2273 */
2274static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
2275 for (size_t i = 0; i < list_length; i++) {
2276 if (list[i] == value) return true; // value is already present
2277 if (list[i] == 0) { // no values in this slot
2278 list[i] = value;
2279 return true; // value inserted
2280 }
2281 }
2282 return false; // could not insert value
2283}
2284
2285/** Add channel_mask in supported_channel_masks if not already present.
2286 * @return true if channel_mask was successfully inserted or already present,
2287 * false if supported_channel_masks is full and does not contain channel_mask.
2288 */
2289static void register_channel_mask(audio_channel_mask_t channel_mask,
2290 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
2291 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
2292 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
2293}
2294
2295/** Add format in supported_formats if not already present.
2296 * @return true if format was successfully inserted or already present,
2297 * false if supported_formats is full and does not contain format.
2298 */
2299static void register_format(audio_format_t format,
2300 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
2301 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
2302 "%s: stream can not declare supporting its format %x", __func__, format);
2303}
2304/** Add sample_rate in supported_sample_rates if not already present.
2305 * @return true if sample_rate was successfully inserted or already present,
2306 * false if supported_sample_rates is full and does not contain sample_rate.
2307 */
2308static void register_sample_rate(uint32_t sample_rate,
2309 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
2310 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
2311 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
2312}
2313
vivek mehtaa68fea62017-06-08 19:04:02 -07002314static size_t get_stream_buffer_size(size_t duration_ms,
2315 uint32_t sample_rate,
2316 audio_format_t format,
2317 int channel_count,
2318 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002319{
2320 size_t size = 0;
2321
vivek mehtaa68fea62017-06-08 19:04:02 -07002322 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002323 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002324 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002325
2326 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002327
Glenn Kasten4f993392014-05-14 07:30:48 -07002328 /* make sure the size is multiple of 32 bytes
2329 * At 48 kHz mono 16-bit PCM:
2330 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2331 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2332 */
2333 size += 0x1f;
2334 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002335
2336 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002337}
2338
2339static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2340{
2341 struct stream_out *out = (struct stream_out *)stream;
2342
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002343 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002344}
2345
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002346static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002347{
2348 return -ENOSYS;
2349}
2350
2351static size_t out_get_buffer_size(const struct audio_stream *stream)
2352{
2353 struct stream_out *out = (struct stream_out *)stream;
2354
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002355 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2356 return out->compr_config.fragment_size;
2357 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002358 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002359 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002360}
2361
2362static uint32_t out_get_channels(const struct audio_stream *stream)
2363{
2364 struct stream_out *out = (struct stream_out *)stream;
2365
2366 return out->channel_mask;
2367}
2368
2369static audio_format_t out_get_format(const struct audio_stream *stream)
2370{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002371 struct stream_out *out = (struct stream_out *)stream;
2372
2373 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002374}
2375
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002376static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002377{
2378 return -ENOSYS;
2379}
2380
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002381/* must be called with out->lock locked */
2382static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002383{
2384 struct stream_out *out = (struct stream_out *)stream;
2385 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002386 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002387
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002388 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002389 if (adev->adm_deregister_stream)
2390 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002391 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002392 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002393 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2394 if (out->pcm) {
2395 pcm_close(out->pcm);
2396 out->pcm = NULL;
2397 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002398 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002399 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002400 out->playback_started = false;
2401 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002402 } else {
2403 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002404 out->gapless_mdata.encoder_delay = 0;
2405 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002406 if (out->compr != NULL) {
2407 compress_close(out->compr);
2408 out->compr = NULL;
2409 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002410 }
Phil Burkbc991042017-02-24 08:06:44 -08002411 if (do_stop) {
2412 stop_output_stream(out);
2413 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002414 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002415 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002416 return 0;
2417}
2418
2419static int out_standby(struct audio_stream *stream)
2420{
2421 struct stream_out *out = (struct stream_out *)stream;
2422
2423 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2424 out->usecase, use_case_table[out->usecase]);
2425
2426 lock_output_stream(out);
2427 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002428 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002429 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002430 return 0;
2431}
2432
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002433static int out_on_error(struct audio_stream *stream)
2434{
2435 struct stream_out *out = (struct stream_out *)stream;
2436 struct audio_device *adev = out->dev;
2437 bool do_standby = false;
2438
2439 lock_output_stream(out);
2440 if (!out->standby) {
2441 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2442 stop_compressed_output_l(out);
2443 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2444 } else
2445 do_standby = true;
2446 }
2447 pthread_mutex_unlock(&out->lock);
2448
2449 if (do_standby)
2450 return out_standby(&out->stream.common);
2451
2452 return 0;
2453}
2454
Andy Hung7401c7c2016-09-21 12:41:21 -07002455static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002456{
Andy Hung7401c7c2016-09-21 12:41:21 -07002457 struct stream_out *out = (struct stream_out *)stream;
2458
2459 // We try to get the lock for consistency,
2460 // but it isn't necessary for these variables.
2461 // If we're not in standby, we may be blocked on a write.
2462 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2463 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2464 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2465
2466 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002467 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002468 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002469
2470 // dump error info
2471 (void)error_log_dump(
2472 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002473
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002474 return 0;
2475}
2476
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002477static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2478{
2479 int ret = 0;
2480 char value[32];
2481 struct compr_gapless_mdata tmp_mdata;
2482
2483 if (!out || !parms) {
2484 return -EINVAL;
2485 }
2486
2487 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2488 if (ret >= 0) {
2489 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2490 } else {
2491 return -EINVAL;
2492 }
2493
2494 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2495 if (ret >= 0) {
2496 tmp_mdata.encoder_padding = atoi(value);
2497 } else {
2498 return -EINVAL;
2499 }
2500
2501 out->gapless_mdata = tmp_mdata;
2502 out->send_new_metadata = 1;
2503 ALOGV("%s new encoder delay %u and padding %u", __func__,
2504 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2505
2506 return 0;
2507}
2508
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002509static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2510{
2511 return out == adev->primary_output || out == adev->voice_tx_output;
2512}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002513
Kevin Rocard1e02c882017-08-09 15:26:07 -07002514static int get_alive_usb_card(struct str_parms* parms) {
2515 int card;
2516 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2517 !audio_extn_usb_alive(card)) {
2518 return card;
2519 }
2520 return -ENODEV;
2521}
2522
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002523static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2524{
2525 struct stream_out *out = (struct stream_out *)stream;
2526 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002527 struct audio_usecase *usecase;
2528 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002529 struct str_parms *parms;
2530 char value[32];
2531 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002532 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002533 int status = 0;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002534 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002535
Eric Laurent2e140aa2016-06-30 17:14:46 -07002536 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002537 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002538 parms = str_parms_create_str(kvpairs);
2539 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2540 if (ret >= 0) {
2541 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002542
Eric Laurenta1478072015-09-21 17:21:52 -07002543 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002544
2545 // The usb driver needs to be closed after usb device disconnection
2546 // otherwise audio is no longer played on the new usb devices.
2547 // By forcing the stream in standby, the usb stack refcount drops to 0
2548 // and the driver is closed.
2549 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD && val == AUDIO_DEVICE_NONE &&
2550 audio_is_usb_out_device(out->devices)) {
2551 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2552 out_standby_l(&out->stream.common);
2553 }
2554
Eric Laurent150dbfe2013-02-27 14:31:02 -08002555 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002556
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002557 /*
2558 * When HDMI cable is unplugged the music playback is paused and
2559 * the policy manager sends routing=0. But the audioflinger
2560 * continues to write data until standby time (3sec).
2561 * As the HDMI core is turned off, the write gets blocked.
2562 * Avoid this by routing audio to speaker until standby.
2563 */
2564 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2565 val == AUDIO_DEVICE_NONE) {
2566 val = AUDIO_DEVICE_OUT_SPEAKER;
2567 }
2568
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002569 /*
2570 * When A2DP is disconnected the
2571 * music playback is paused and the policy manager sends routing=0
2572 * But the audioflingercontinues to write data until standby time
2573 * (3sec). As BT is turned off, the write gets blocked.
2574 * Avoid this by routing audio to speaker until standby.
2575 */
2576 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2577 (val == AUDIO_DEVICE_NONE) &&
2578 !audio_extn_a2dp_is_ready()) {
2579 val = AUDIO_DEVICE_OUT_SPEAKER;
2580 }
2581
2582 /* To avoid a2dp to sco overlapping / BT device improper state
2583 * check with BT lib about a2dp streaming support before routing
2584 */
2585 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2586 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002587 if (val & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002588 //combo usecase just by pass a2dp
2589 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2590 bypass_a2dp = true;
2591 } else {
2592 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2593 /* update device to a2dp and don't route as BT returned error
2594 * However it is still possible a2dp routing called because
2595 * of current active device disconnection (like wired headset)
2596 */
2597 out->devices = val;
2598 pthread_mutex_unlock(&out->lock);
2599 pthread_mutex_unlock(&adev->lock);
2600 status = -ENOSYS;
2601 goto routing_fail;
2602 }
2603 }
2604 }
2605
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002606 audio_devices_t new_dev = val;
2607
2608 // Workaround: If routing to an non existing usb device, fail gracefully
2609 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002610 int card;
2611 if (audio_is_usb_out_device(new_dev) &&
2612 (card = get_alive_usb_card(parms)) >= 0) {
2613
2614 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002615 pthread_mutex_unlock(&adev->lock);
2616 pthread_mutex_unlock(&out->lock);
2617 status = -ENOSYS;
2618 goto routing_fail;
2619 }
2620
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002621 /*
2622 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002623 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002624 * the select_devices(). But how do we undo this?
2625 *
2626 * For example, music playback is active on headset (deep-buffer usecase)
2627 * and if we go to ringtones and select a ringtone, low-latency usecase
2628 * will be started on headset+speaker. As we can't enable headset+speaker
2629 * and headset devices at the same time, select_devices() switches the music
2630 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2631 * So when the ringtone playback is completed, how do we undo the same?
2632 *
2633 * We are relying on the out_set_parameters() call on deep-buffer output,
2634 * once the ringtone playback is ended.
2635 * NOTE: We should not check if the current devices are same as new devices.
2636 * Because select_devices() must be called to switch back the music
2637 * playback to headset.
2638 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002639 if (new_dev != AUDIO_DEVICE_NONE) {
2640 bool same_dev = out->devices == new_dev;
2641 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002642
Eric Laurenta7657192014-10-09 21:09:33 -07002643 if (output_drives_call(adev, out)) {
Vignesh Kulothungana5c9da12017-11-10 11:41:24 -08002644 if (!voice_is_call_state_active(adev)) {
Eric Laurenta7657192014-10-09 21:09:33 -07002645 if (adev->mode == AUDIO_MODE_IN_CALL) {
2646 adev->current_call_output = out;
2647 ret = voice_start_call(adev);
2648 }
2649 } else {
2650 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002651 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002652 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002653 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002654
2655 if (!out->standby) {
2656 if (!same_dev) {
2657 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002658 // inform adm before actual routing to prevent glitches.
2659 if (adev->adm_on_routing_change) {
2660 adev->adm_on_routing_change(adev->adm_data,
2661 out->handle);
2662 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002663 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002664 if (!bypass_a2dp) {
2665 select_devices(adev, out->usecase);
2666 } else {
juyuchen9baad392018-06-05 19:02:10 +08002667 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2668 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2669 else
2670 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002671 select_devices(adev, out->usecase);
2672 out->devices = new_dev;
2673 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002674 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002675
2676 // on device switch force swap, lower functions will make sure
2677 // to check if swap is allowed or not.
2678
2679 if (!same_dev)
2680 platform_set_swap_channels(adev, true);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002681
2682 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2683 out->a2dp_compress_mute &&
2684 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
2685 pthread_mutex_lock(&out->compr_mute_lock);
2686 out->a2dp_compress_mute = false;
2687 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
2688 pthread_mutex_unlock(&out->compr_mute_lock);
2689 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002690 }
2691
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002692 }
2693
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002694 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002695 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002696
2697 /*handles device and call state changes*/
2698 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002699 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002700 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002701
2702 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2703 parse_compress_metadata(out, parms);
2704 }
2705
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002706 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002707 ALOGV("%s: exit: code(%d)", __func__, status);
2708 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002709}
2710
Haynes Mathew George569b7482017-05-08 14:44:27 -07002711static bool stream_get_parameter_channels(struct str_parms *query,
2712 struct str_parms *reply,
2713 audio_channel_mask_t *supported_channel_masks) {
2714 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002715 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002716 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002717 size_t i, j;
2718
2719 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2720 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002721 value[0] = '\0';
2722 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002723 while (supported_channel_masks[i] != 0) {
2724 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2725 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002726 if (!first) {
2727 strcat(value, "|");
2728 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002729 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002730 first = false;
2731 break;
2732 }
2733 }
2734 i++;
2735 }
2736 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002737 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002738 return ret >= 0;
2739}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002740
Haynes Mathew George569b7482017-05-08 14:44:27 -07002741static bool stream_get_parameter_formats(struct str_parms *query,
2742 struct str_parms *reply,
2743 audio_format_t *supported_formats) {
2744 int ret = -1;
2745 char value[256];
2746 int i;
2747
2748 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2749 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002750 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002751 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002752 case AUDIO_FORMAT_PCM_16_BIT:
2753 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2754 break;
2755 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2756 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2757 break;
2758 case AUDIO_FORMAT_PCM_32_BIT:
2759 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2760 break;
2761 default:
2762 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002763 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002764 break;
2765 }
2766 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002767 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002768 return ret >= 0;
2769}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002770
Haynes Mathew George569b7482017-05-08 14:44:27 -07002771static bool stream_get_parameter_rates(struct str_parms *query,
2772 struct str_parms *reply,
2773 uint32_t *supported_sample_rates) {
2774
2775 int i;
2776 char value[256];
2777 int ret = -1;
2778 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2779 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002780 value[0] = '\0';
2781 i=0;
2782 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002783 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002784 int avail = sizeof(value) - cursor;
2785 ret = snprintf(value + cursor, avail, "%s%d",
2786 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002787 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002788 if (ret < 0 || ret >= avail) {
2789 // if cursor is at the last element of the array
2790 // overwrite with \0 is duplicate work as
2791 // snprintf already put a \0 in place.
2792 // else
2793 // we had space to write the '|' at value[cursor]
2794 // (which will be overwritten) or no space to fill
2795 // the first element (=> cursor == 0)
2796 value[cursor] = '\0';
2797 break;
2798 }
2799 cursor += ret;
2800 ++i;
2801 }
2802 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2803 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002804 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002805 return ret >= 0;
2806}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002807
Haynes Mathew George569b7482017-05-08 14:44:27 -07002808static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2809{
2810 struct stream_out *out = (struct stream_out *)stream;
2811 struct str_parms *query = str_parms_create_str(keys);
2812 char *str;
2813 struct str_parms *reply = str_parms_create();
2814 bool replied = false;
2815 ALOGV("%s: enter: keys - %s", __func__, keys);
2816
2817 replied |= stream_get_parameter_channels(query, reply,
2818 &out->supported_channel_masks[0]);
2819 replied |= stream_get_parameter_formats(query, reply,
2820 &out->supported_formats[0]);
2821 replied |= stream_get_parameter_rates(query, reply,
2822 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002823 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002824 str = str_parms_to_str(reply);
2825 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002826 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002827 }
2828 str_parms_destroy(query);
2829 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002830 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002831 return str;
2832}
2833
2834static uint32_t out_get_latency(const struct audio_stream_out *stream)
2835{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002836 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002837 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002838 uint32_t latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002839
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002840 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2841 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002842 else if ((out->realtime) ||
2843 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002844 // since the buffer won't be filled up faster than realtime,
2845 // return a smaller number
2846 period_ms = (out->af_period_multiplier * out->config.period_size *
2847 1000) / (out->config.rate);
2848 hw_delay = platform_render_latency(out->usecase)/1000;
2849 return period_ms + hw_delay;
2850 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002851
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002852 latency = (out->config.period_count * out->config.period_size * 1000) /
2853 (out->config.rate);
2854
2855 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
2856 latency += audio_extn_a2dp_get_encoder_latency();
2857
2858 return latency;
2859}
2860
2861static int set_compr_volume(struct audio_stream_out *stream, float left,
2862 float right)
2863{
2864 struct stream_out *out = (struct stream_out *)stream;
2865 int volume[2];
2866 char mixer_ctl_name[128];
2867 struct audio_device *adev = out->dev;
2868 struct mixer_ctl *ctl;
2869 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2870 PCM_PLAYBACK);
2871
2872 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2873 "Compress Playback %d Volume", pcm_device_id);
2874 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2875 if (!ctl) {
2876 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2877 __func__, mixer_ctl_name);
2878 return -EINVAL;
2879 }
2880 ALOGV("%s: ctl for mixer cmd - %s, left %f, right %f",
2881 __func__, mixer_ctl_name, left, right);
2882 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2883 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2884 mixer_ctl_set_array(ctl, volume, sizeof(volume) / sizeof(volume[0]));
2885
2886 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002887}
2888
2889static int out_set_volume(struct audio_stream_out *stream, float left,
2890 float right)
2891{
Eric Laurenta9024de2013-04-04 09:19:12 -07002892 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002893 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002894
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002895 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002896 /* only take left channel into account: the API is for stereo anyway */
2897 out->muted = (left == 0.0f);
2898 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002899 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002900 pthread_mutex_lock(&out->compr_mute_lock);
2901 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
2902 if (!out->a2dp_compress_mute)
2903 ret = set_compr_volume(stream, left, right);
2904 out->volume_l = left;
2905 out->volume_r = right;
2906 pthread_mutex_unlock(&out->compr_mute_lock);
2907 return ret;
vivek mehtaa68fea62017-06-08 19:04:02 -07002908 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002909 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2910 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2911 if (!out->standby) {
2912 // if in standby, cached volume will be sent after stream is opened
2913 audio_extn_utils_send_app_type_gain(out->dev,
2914 out->app_type_cfg.app_type,
2915 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002916 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002917 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002918 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002919
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002920 return -ENOSYS;
2921}
2922
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002923// note: this call is safe only if the stream_cb is
2924// removed first in close_output_stream (as is done now).
2925static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2926{
2927 if (!stream || !parms)
2928 return;
2929
2930 struct stream_out *out = (struct stream_out *)stream;
2931 struct audio_device *adev = out->dev;
2932
2933 card_status_t status;
2934 int card;
2935 if (parse_snd_card_status(parms, &card, &status) < 0)
2936 return;
2937
2938 pthread_mutex_lock(&adev->lock);
2939 bool valid_cb = (card == adev->snd_card);
2940 pthread_mutex_unlock(&adev->lock);
2941
2942 if (!valid_cb)
2943 return;
2944
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002945 lock_output_stream(out);
2946 if (out->card_status != status)
2947 out->card_status = status;
2948 pthread_mutex_unlock(&out->lock);
2949
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002950 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2951 use_case_table[out->usecase],
2952 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2953
2954 if (status == CARD_STATUS_OFFLINE)
2955 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002956
2957 return;
2958}
2959
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002960#ifdef NO_AUDIO_OUT
2961static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002962 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002963{
2964 struct stream_out *out = (struct stream_out *)stream;
2965
2966 /* No Output device supported other than BT for playback.
2967 * Sleep for the amount of buffer duration
2968 */
Eric Laurenta1478072015-09-21 17:21:52 -07002969 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002970 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2971 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002972 out_get_sample_rate(&out->stream.common));
2973 pthread_mutex_unlock(&out->lock);
2974 return bytes;
2975}
2976#endif
2977
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002978static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2979 size_t bytes)
2980{
2981 struct stream_out *out = (struct stream_out *)stream;
2982 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002983 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002984 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002985
Eric Laurenta1478072015-09-21 17:21:52 -07002986 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002987 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07002988 const size_t frame_size = audio_stream_out_frame_size(stream);
2989 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002990
Eric Laurent0e46adf2016-12-16 12:49:24 -08002991 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2992 error_code = ERROR_CODE_WRITE;
2993 goto exit;
2994 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002995
2996 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2997 (audio_extn_a2dp_is_suspended())) {
juyuchen9baad392018-06-05 19:02:10 +08002998 if (!(out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002999 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3000 ret = -EIO;
3001 goto exit;
3002 }
3003 }
3004 }
3005
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003006 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003007 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003008 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003009 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07003010
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003011 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003012 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003013 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07003014 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003015 goto exit;
3016 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07003017
vivek mehta40125092017-08-21 18:48:51 -07003018 // after standby always force set last known cal step
3019 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
3020 ALOGD("%s: retry previous failed cal level set", __func__);
3021 send_gain_dep_calibration_l();
3022 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003023 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003024
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003025 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003026 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003027 if (out->send_new_metadata) {
3028 ALOGVV("send new gapless metadata");
3029 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3030 out->send_new_metadata = 0;
3031 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003032 unsigned int avail;
3033 struct timespec tstamp;
3034 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
3035 /* Do not limit write size if the available frames count is unknown */
3036 if (ret != 0) {
3037 avail = bytes;
3038 }
3039 if (avail == 0) {
3040 ret = 0;
3041 } else {
3042 if (avail > bytes) {
3043 avail = bytes;
3044 }
3045 ret = compress_write(out->compr, buffer, avail);
3046 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
3047 __func__, avail, ret);
3048 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003049
Eric Laurent6e895242013-09-05 16:10:57 -07003050 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003051 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
3052 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003053 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003054 compress_start(out->compr);
3055 out->playback_started = 1;
3056 out->offload_state = OFFLOAD_STATE_PLAYING;
3057 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003058 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07003059 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07003060 } else {
3061 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07003062 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003063 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07003064 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003065 return ret;
3066 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07003067 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003068 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003069 size_t bytes_to_write = bytes;
3070
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003071 if (out->muted)
3072 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07003073 // FIXME: this can be removed once audio flinger mixer supports mono output
Nadav Bar3d72cfc2018-01-07 12:19:24 +02003074 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP || out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003075 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3076 int16_t *src = (int16_t *)buffer;
3077 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003078
Eric Laurentad2dde92017-09-20 18:27:31 -07003079 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
3080 out->format != AUDIO_FORMAT_PCM_16_BIT,
3081 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003082
Eric Laurentad2dde92017-09-20 18:27:31 -07003083 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
3084 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
3085 }
3086 bytes_to_write /= 2;
3087 }
3088 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes_to_write);
3089
Glenn Kasten5a59dff2018-02-22 08:05:35 -08003090 long ns = (frames * (int64_t) NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003091 request_out_focus(out, ns);
3092
3093 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3094 if (use_mmap)
Eric Laurentad2dde92017-09-20 18:27:31 -07003095 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003096 else
Eric Laurentad2dde92017-09-20 18:27:31 -07003097 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003098
Haynes Mathew George03c40102016-01-29 17:57:48 -08003099 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07003100 } else {
3101 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003102 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003103 }
3104
3105exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07003106 // For PCM we always consume the buffer and return #bytes regardless of ret.
3107 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003108 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07003109 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003110 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07003111
Andy Hung7401c7c2016-09-21 12:41:21 -07003112 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07003113 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07003114 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3115 ALOGE_IF(out->pcm != NULL,
3116 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07003117 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003118 // usleep not guaranteed for values over 1 second but we don't limit here.
3119 }
3120 }
Andy Hungda9b56b2016-09-16 20:06:35 -07003121
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003122 pthread_mutex_unlock(&out->lock);
3123
3124 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07003125 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003126 if (sleeptime_us != 0)
3127 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003128 }
3129 return bytes;
3130}
3131
3132static int out_get_render_position(const struct audio_stream_out *stream,
3133 uint32_t *dsp_frames)
3134{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003135 struct stream_out *out = (struct stream_out *)stream;
3136 *dsp_frames = 0;
3137 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07003138 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003139 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003140 unsigned long frames = 0;
3141 // TODO: check return value
3142 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
3143 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003144 ALOGVV("%s rendered frames %d sample_rate %d",
3145 __func__, *dsp_frames, out->sample_rate);
3146 }
3147 pthread_mutex_unlock(&out->lock);
3148 return 0;
3149 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003150 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003151}
3152
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003153static int out_add_audio_effect(const struct audio_stream *stream __unused,
3154 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003155{
3156 return 0;
3157}
3158
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003159static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3160 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003161{
3162 return 0;
3163}
3164
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003165static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3166 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003167{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003168 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003169}
3170
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003171static int out_get_presentation_position(const struct audio_stream_out *stream,
3172 uint64_t *frames, struct timespec *timestamp)
3173{
3174 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003175 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07003176 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003177
Eric Laurenta1478072015-09-21 17:21:52 -07003178 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003179
Eric Laurent949a0892013-09-20 09:20:13 -07003180 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3181 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003182 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07003183 compress_get_tstamp(out->compr, &dsp_frames,
3184 &out->sample_rate);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003185 // Adjustment accounts for A2DP encoder latency with offload usecases
3186 // Note: Encoder latency is returned in ms.
3187 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3188 unsigned long offset =
3189 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3190 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
3191 }
Eric Laurent949a0892013-09-20 09:20:13 -07003192 ALOGVV("%s rendered frames %ld sample_rate %d",
3193 __func__, dsp_frames, out->sample_rate);
3194 *frames = dsp_frames;
3195 ret = 0;
3196 /* this is the best we can do */
3197 clock_gettime(CLOCK_MONOTONIC, timestamp);
3198 }
3199 } else {
3200 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07003201 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003202 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3203 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003204 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003205 // This adjustment accounts for buffering after app processor.
3206 // It is based on estimated DSP latency per use case, rather than exact.
3207 signed_frames -=
3208 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3209
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003210 // Adjustment accounts for A2DP encoder latency with non-offload usecases
3211 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3212 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3213 signed_frames -=
3214 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3215 }
3216
Eric Laurent949a0892013-09-20 09:20:13 -07003217 // It would be unusual for this value to be negative, but check just in case ...
3218 if (signed_frames >= 0) {
3219 *frames = signed_frames;
3220 ret = 0;
3221 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003222 }
3223 }
3224 }
3225
3226 pthread_mutex_unlock(&out->lock);
3227
3228 return ret;
3229}
3230
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003231static int out_set_callback(struct audio_stream_out *stream,
3232 stream_callback_t callback, void *cookie)
3233{
3234 struct stream_out *out = (struct stream_out *)stream;
3235
3236 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003237 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003238 out->offload_callback = callback;
3239 out->offload_cookie = cookie;
3240 pthread_mutex_unlock(&out->lock);
3241 return 0;
3242}
3243
3244static int out_pause(struct audio_stream_out* stream)
3245{
3246 struct stream_out *out = (struct stream_out *)stream;
3247 int status = -ENOSYS;
3248 ALOGV("%s", __func__);
3249 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003250 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003251 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
3252 status = compress_pause(out->compr);
3253 out->offload_state = OFFLOAD_STATE_PAUSED;
3254 }
3255 pthread_mutex_unlock(&out->lock);
3256 }
3257 return status;
3258}
3259
3260static int out_resume(struct audio_stream_out* stream)
3261{
3262 struct stream_out *out = (struct stream_out *)stream;
3263 int status = -ENOSYS;
3264 ALOGV("%s", __func__);
3265 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3266 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07003267 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003268 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
3269 status = compress_resume(out->compr);
3270 out->offload_state = OFFLOAD_STATE_PLAYING;
3271 }
3272 pthread_mutex_unlock(&out->lock);
3273 }
3274 return status;
3275}
3276
3277static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3278{
3279 struct stream_out *out = (struct stream_out *)stream;
3280 int status = -ENOSYS;
3281 ALOGV("%s", __func__);
3282 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003283 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003284 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3285 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3286 else
3287 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3288 pthread_mutex_unlock(&out->lock);
3289 }
3290 return status;
3291}
3292
3293static int out_flush(struct audio_stream_out* stream)
3294{
3295 struct stream_out *out = (struct stream_out *)stream;
3296 ALOGV("%s", __func__);
3297 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003298 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003299 stop_compressed_output_l(out);
3300 pthread_mutex_unlock(&out->lock);
3301 return 0;
3302 }
3303 return -ENOSYS;
3304}
3305
Eric Laurent0e46adf2016-12-16 12:49:24 -08003306static int out_stop(const struct audio_stream_out* stream)
3307{
3308 struct stream_out *out = (struct stream_out *)stream;
3309 struct audio_device *adev = out->dev;
3310 int ret = -ENOSYS;
3311
3312 ALOGV("%s", __func__);
3313 pthread_mutex_lock(&adev->lock);
3314 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3315 out->playback_started && out->pcm != NULL) {
3316 pcm_stop(out->pcm);
3317 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08003318 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003319 }
3320 pthread_mutex_unlock(&adev->lock);
3321 return ret;
3322}
3323
3324static int out_start(const struct audio_stream_out* stream)
3325{
3326 struct stream_out *out = (struct stream_out *)stream;
3327 struct audio_device *adev = out->dev;
3328 int ret = -ENOSYS;
3329
3330 ALOGV("%s", __func__);
3331 pthread_mutex_lock(&adev->lock);
3332 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3333 !out->playback_started && out->pcm != NULL) {
3334 ret = start_output_stream(out);
3335 if (ret == 0) {
3336 out->playback_started = true;
3337 }
3338 }
3339 pthread_mutex_unlock(&adev->lock);
3340 return ret;
3341}
3342
Phil Burkbc991042017-02-24 08:06:44 -08003343/*
3344 * Modify config->period_count based on min_size_frames
3345 */
3346static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
3347{
3348 int periodCountRequested = (min_size_frames + config->period_size - 1)
3349 / config->period_size;
3350 int periodCount = MMAP_PERIOD_COUNT_MIN;
3351
3352 ALOGV("%s original config.period_size = %d config.period_count = %d",
3353 __func__, config->period_size, config->period_count);
3354
3355 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
3356 periodCount *= 2;
3357 }
3358 config->period_count = periodCount;
3359
3360 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
3361}
3362
Eric Laurent0e46adf2016-12-16 12:49:24 -08003363static int out_create_mmap_buffer(const struct audio_stream_out *stream,
3364 int32_t min_size_frames,
3365 struct audio_mmap_buffer_info *info)
3366{
3367 struct stream_out *out = (struct stream_out *)stream;
3368 struct audio_device *adev = out->dev;
3369 int ret = 0;
3370 unsigned int offset1;
3371 unsigned int frames1;
3372 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003373 uint32_t mmap_size;
3374 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003375
3376 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003377 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003378 pthread_mutex_lock(&adev->lock);
3379
3380 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003381 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003382 ret = -EINVAL;
3383 goto exit;
3384 }
3385 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003386 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003387 ret = -ENOSYS;
3388 goto exit;
3389 }
3390 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3391 if (out->pcm_device_id < 0) {
3392 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3393 __func__, out->pcm_device_id, out->usecase);
3394 ret = -EINVAL;
3395 goto exit;
3396 }
Phil Burkbc991042017-02-24 08:06:44 -08003397
3398 adjust_mmap_period_count(&out->config, min_size_frames);
3399
Eric Laurent0e46adf2016-12-16 12:49:24 -08003400 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3401 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3402 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3403 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3404 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3405 step = "open";
3406 ret = -ENODEV;
3407 goto exit;
3408 }
3409 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3410 if (ret < 0) {
3411 step = "begin";
3412 goto exit;
3413 }
3414 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003415 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003416 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003417 ret = platform_get_mmap_data_fd(adev->platform,
3418 out->pcm_device_id, 0 /*playback*/,
3419 &info->shared_memory_fd,
3420 &mmap_size);
3421 if (ret < 0) {
3422 // Fall back to non exclusive mode
3423 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3424 } else {
3425 if (mmap_size < buffer_size) {
3426 step = "mmap";
3427 goto exit;
3428 }
3429 // FIXME: indicate exclusive mode support by returning a negative buffer size
3430 info->buffer_size_frames *= -1;
3431 }
3432 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003433
3434 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3435 if (ret < 0) {
3436 step = "commit";
3437 goto exit;
3438 }
Phil Burkbc991042017-02-24 08:06:44 -08003439
3440 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003441 ret = 0;
3442
3443 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3444 __func__, info->shared_memory_address, info->buffer_size_frames);
3445
3446exit:
3447 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003448 if (out->pcm == NULL) {
3449 ALOGE("%s: %s - %d", __func__, step, ret);
3450 } else {
3451 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003452 pcm_close(out->pcm);
3453 out->pcm = NULL;
3454 }
3455 }
3456 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003457 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003458 return ret;
3459}
3460
3461static int out_get_mmap_position(const struct audio_stream_out *stream,
3462 struct audio_mmap_position *position)
3463{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003464 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003465 struct stream_out *out = (struct stream_out *)stream;
3466 ALOGVV("%s", __func__);
3467 if (position == NULL) {
3468 return -EINVAL;
3469 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003470 lock_output_stream(out);
3471 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3472 out->pcm == NULL) {
3473 ret = -ENOSYS;
3474 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003475 }
3476
3477 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003478 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003479 if (ret < 0) {
3480 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003481 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003482 }
Andy Hungfc044e12017-03-20 09:24:22 -07003483 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003484exit:
3485 pthread_mutex_unlock(&out->lock);
3486 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003487}
3488
3489
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003490/** audio_stream_in implementation **/
3491static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3492{
3493 struct stream_in *in = (struct stream_in *)stream;
3494
3495 return in->config.rate;
3496}
3497
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003498static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003499{
3500 return -ENOSYS;
3501}
3502
3503static size_t in_get_buffer_size(const struct audio_stream *stream)
3504{
3505 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003506 return in->config.period_size * in->af_period_multiplier *
3507 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003508}
3509
3510static uint32_t in_get_channels(const struct audio_stream *stream)
3511{
3512 struct stream_in *in = (struct stream_in *)stream;
3513
3514 return in->channel_mask;
3515}
3516
vivek mehta4ed66e62016-04-15 23:33:34 -07003517static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003518{
vivek mehta4ed66e62016-04-15 23:33:34 -07003519 struct stream_in *in = (struct stream_in *)stream;
3520 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003521}
3522
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003523static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003524{
3525 return -ENOSYS;
3526}
3527
3528static int in_standby(struct audio_stream *stream)
3529{
3530 struct stream_in *in = (struct stream_in *)stream;
3531 struct audio_device *adev = in->dev;
3532 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003533 bool do_stop = true;
3534
Eric Laurent994a6932013-07-17 11:51:42 -07003535 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003536
3537 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003538
3539 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003540 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003541 audio_extn_sound_trigger_stop_lab(in);
3542 in->standby = true;
3543 }
3544
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003545 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003546 if (adev->adm_deregister_stream)
3547 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3548
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003549 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003550 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003551 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003552 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003553 in->capture_started = false;
3554 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003555 if (in->pcm) {
3556 pcm_close(in->pcm);
3557 in->pcm = NULL;
3558 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003559 adev->enable_voicerx = false;
3560 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003561 if (do_stop) {
3562 status = stop_input_stream(in);
3563 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003564 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003565 }
3566 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003567 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003568 return status;
3569}
3570
Andy Hungd13f0d32017-06-12 13:58:37 -07003571static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003572{
Andy Hungd13f0d32017-06-12 13:58:37 -07003573 struct stream_in *in = (struct stream_in *)stream;
3574
3575 // We try to get the lock for consistency,
3576 // but it isn't necessary for these variables.
3577 // If we're not in standby, we may be blocked on a read.
3578 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3579 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3580 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3581 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3582
3583 if (locked) {
3584 pthread_mutex_unlock(&in->lock);
3585 }
3586
3587 // dump error info
3588 (void)error_log_dump(
3589 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003590 return 0;
3591}
3592
3593static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3594{
3595 struct stream_in *in = (struct stream_in *)stream;
3596 struct audio_device *adev = in->dev;
3597 struct str_parms *parms;
3598 char *str;
3599 char value[32];
3600 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003601 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003602
Eric Laurent994a6932013-07-17 11:51:42 -07003603 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003604 parms = str_parms_create_str(kvpairs);
3605
3606 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3607
Eric Laurenta1478072015-09-21 17:21:52 -07003608 lock_input_stream(in);
3609
Eric Laurent150dbfe2013-02-27 14:31:02 -08003610 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003611 if (ret >= 0) {
3612 val = atoi(value);
3613 /* no audio source uses val == 0 */
3614 if ((in->source != val) && (val != 0)) {
3615 in->source = val;
3616 }
3617 }
3618
3619 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003620
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003621 if (ret >= 0) {
3622 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003623 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003624
3625 // Workaround: If routing to an non existing usb device, fail gracefully
3626 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003627 int card;
3628 if (audio_is_usb_in_device(val) &&
3629 (card = get_alive_usb_card(parms)) >= 0) {
3630
3631 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003632 status = -ENOSYS;
3633 } else {
3634
3635 in->device = val;
3636 /* If recording is in progress, change the tx device to new device */
3637 if (!in->standby) {
3638 ALOGV("update input routing change");
3639 // inform adm before actual routing to prevent glitches.
3640 if (adev->adm_on_routing_change) {
3641 adev->adm_on_routing_change(adev->adm_data,
3642 in->capture_handle);
3643 }
3644 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003645 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003646 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003647 }
3648 }
3649
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003650 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003651 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003652
3653 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003654 ALOGV("%s: exit: status(%d)", __func__, status);
3655 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003656}
3657
Haynes Mathew George569b7482017-05-08 14:44:27 -07003658static char* in_get_parameters(const struct audio_stream *stream,
3659 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003660{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003661 struct stream_in *in = (struct stream_in *)stream;
3662 struct str_parms *query = str_parms_create_str(keys);
3663 char *str;
3664 struct str_parms *reply = str_parms_create();
3665 bool replied = false;
3666
3667 ALOGV("%s: enter: keys - %s", __func__, keys);
3668 replied |= stream_get_parameter_channels(query, reply,
3669 &in->supported_channel_masks[0]);
3670 replied |= stream_get_parameter_formats(query, reply,
3671 &in->supported_formats[0]);
3672 replied |= stream_get_parameter_rates(query, reply,
3673 &in->supported_sample_rates[0]);
3674 if (replied) {
3675 str = str_parms_to_str(reply);
3676 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003677 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003678 }
3679 str_parms_destroy(query);
3680 str_parms_destroy(reply);
3681 ALOGV("%s: exit: returns - %s", __func__, str);
3682 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003683}
3684
Eric Laurent51f3c662018-04-10 18:21:34 -07003685static int in_set_gain(struct audio_stream_in *stream, float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003686{
Eric Laurent51f3c662018-04-10 18:21:34 -07003687 struct stream_in *in = (struct stream_in *)stream;
3688 char mixer_ctl_name[128];
3689 struct mixer_ctl *ctl;
3690 int ctl_value;
3691
3692 ALOGV("%s: gain %f", __func__, gain);
3693
3694 if (stream == NULL)
3695 return -EINVAL;
3696
3697 /* in_set_gain() only used to silence MMAP capture for now */
3698 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
3699 return -ENOSYS;
3700
3701 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
3702
3703 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
3704 if (!ctl) {
3705 ALOGW("%s: Could not get ctl for mixer cmd - %s",
3706 __func__, mixer_ctl_name);
3707 return -ENOSYS;
3708 }
3709
3710 if (gain < RECORD_GAIN_MIN)
3711 gain = RECORD_GAIN_MIN;
3712 else if (gain > RECORD_GAIN_MAX)
3713 gain = RECORD_GAIN_MAX;
3714 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
3715
3716 mixer_ctl_set_value(ctl, 0, ctl_value);
3717 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003718}
3719
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003720static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3721{
3722 if (!stream || !parms)
3723 return;
3724
3725 struct stream_in *in = (struct stream_in *)stream;
3726 struct audio_device *adev = in->dev;
3727
3728 card_status_t status;
3729 int card;
3730 if (parse_snd_card_status(parms, &card, &status) < 0)
3731 return;
3732
3733 pthread_mutex_lock(&adev->lock);
3734 bool valid_cb = (card == adev->snd_card);
3735 pthread_mutex_unlock(&adev->lock);
3736
3737 if (!valid_cb)
3738 return;
3739
3740 lock_input_stream(in);
3741 if (in->card_status != status)
3742 in->card_status = status;
3743 pthread_mutex_unlock(&in->lock);
3744
3745 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3746 use_case_table[in->usecase],
3747 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3748
3749 // a better solution would be to report error back to AF and let
3750 // it put the stream to standby
3751 if (status == CARD_STATUS_OFFLINE)
3752 in_standby(&in->stream.common);
3753
3754 return;
3755}
3756
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003757static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3758 size_t bytes)
3759{
3760 struct stream_in *in = (struct stream_in *)stream;
3761 struct audio_device *adev = in->dev;
3762 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003763 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003764 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003765
Eric Laurenta1478072015-09-21 17:21:52 -07003766 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003767 const size_t frame_size = audio_stream_in_frame_size(stream);
3768 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003769
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003770 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003771 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003772 /* Read from sound trigger HAL */
3773 audio_extn_sound_trigger_read(in, buffer, bytes);
3774 pthread_mutex_unlock(&in->lock);
3775 return bytes;
3776 }
3777
Eric Laurent0e46adf2016-12-16 12:49:24 -08003778 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3779 ret = -ENOSYS;
3780 goto exit;
3781 }
3782
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003783 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003784 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003785 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003786 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003787 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003788 goto exit;
3789 }
3790 in->standby = 0;
3791 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003792
Andy Hungd13f0d32017-06-12 13:58:37 -07003793 // errors that occur here are read errors.
3794 error_code = ERROR_CODE_READ;
3795
Haynes Mathew George03c40102016-01-29 17:57:48 -08003796 //what's the duration requested by the client?
3797 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3798 in->config.rate;
3799 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003800
Haynes Mathew George03c40102016-01-29 17:57:48 -08003801 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003802 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003803 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003804 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003805 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003806 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003807 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003808 if (ret < 0) {
3809 ALOGE("Failed to read w/err %s", strerror(errno));
3810 ret = -errno;
3811 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003812 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3813 if (bytes % 4 == 0) {
3814 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3815 int_buf_stream = buffer;
3816 for (size_t itt=0; itt < bytes/4 ; itt++) {
3817 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003818 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003819 } else {
3820 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3821 ret = -EINVAL;
3822 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003823 }
3824 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003825 }
3826
Haynes Mathew George03c40102016-01-29 17:57:48 -08003827 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003828
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003829 /*
3830 * Instead of writing zeroes here, we could trust the hardware
3831 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003832 * 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 -08003833 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08003834 if (ret == 0 && adev->mic_muted &&
3835 !voice_is_in_call_rec_stream(in) &&
3836 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003837 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07003838 in->frames_muted += frames;
3839 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003840
3841exit:
3842 pthread_mutex_unlock(&in->lock);
3843
3844 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07003845 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003846 in_standby(&in->stream.common);
3847 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003848 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003849 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07003850 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08003851 }
3852 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003853 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003854 }
3855 return bytes;
3856}
3857
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003858static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003859{
3860 return 0;
3861}
3862
Andy Hung6ebe5962016-01-15 17:46:57 -08003863static int in_get_capture_position(const struct audio_stream_in *stream,
3864 int64_t *frames, int64_t *time)
3865{
3866 if (stream == NULL || frames == NULL || time == NULL) {
3867 return -EINVAL;
3868 }
3869 struct stream_in *in = (struct stream_in *)stream;
3870 int ret = -ENOSYS;
3871
3872 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003873 // note: ST sessions do not close the alsa pcm driver synchronously
3874 // on standby. Therefore, we may return an error even though the
3875 // pcm stream is still opened.
3876 if (in->standby) {
3877 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
3878 "%s stream in standby but pcm not NULL for non ST session", __func__);
3879 goto exit;
3880 }
Andy Hung6ebe5962016-01-15 17:46:57 -08003881 if (in->pcm) {
3882 struct timespec timestamp;
3883 unsigned int avail;
3884 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3885 *frames = in->frames_read + avail;
3886 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3887 ret = 0;
3888 }
3889 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003890exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08003891 pthread_mutex_unlock(&in->lock);
3892 return ret;
3893}
3894
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003895static int add_remove_audio_effect(const struct audio_stream *stream,
3896 effect_handle_t effect,
3897 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003898{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003899 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003900 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003901 int status = 0;
3902 effect_descriptor_t desc;
3903
3904 status = (*effect)->get_descriptor(effect, &desc);
3905 if (status != 0)
3906 return status;
3907
Eric Laurenta1478072015-09-21 17:21:52 -07003908 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003909 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003910 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003911 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003912 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003913 in->enable_aec != enable &&
3914 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3915 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003916 if (!enable)
3917 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003918 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3919 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3920 adev->enable_voicerx = enable;
3921 struct audio_usecase *usecase;
3922 struct listnode *node;
3923 list_for_each(node, &adev->usecase_list) {
3924 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07003925 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07003926 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05003927 }
3928 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003929 if (!in->standby)
3930 select_devices(in->dev, in->usecase);
3931 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003932 if (in->enable_ns != enable &&
3933 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3934 in->enable_ns = enable;
3935 if (!in->standby)
3936 select_devices(in->dev, in->usecase);
3937 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003938 pthread_mutex_unlock(&in->dev->lock);
3939 pthread_mutex_unlock(&in->lock);
3940
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003941 return 0;
3942}
3943
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003944static int in_add_audio_effect(const struct audio_stream *stream,
3945 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003946{
Eric Laurent994a6932013-07-17 11:51:42 -07003947 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003948 return add_remove_audio_effect(stream, effect, true);
3949}
3950
3951static int in_remove_audio_effect(const struct audio_stream *stream,
3952 effect_handle_t effect)
3953{
Eric Laurent994a6932013-07-17 11:51:42 -07003954 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003955 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003956}
3957
Eric Laurent0e46adf2016-12-16 12:49:24 -08003958static int in_stop(const struct audio_stream_in* stream)
3959{
3960 struct stream_in *in = (struct stream_in *)stream;
3961 struct audio_device *adev = in->dev;
3962
3963 int ret = -ENOSYS;
3964 ALOGV("%s", __func__);
3965 pthread_mutex_lock(&adev->lock);
3966 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3967 in->capture_started && in->pcm != NULL) {
3968 pcm_stop(in->pcm);
3969 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003970 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003971 }
3972 pthread_mutex_unlock(&adev->lock);
3973 return ret;
3974}
3975
3976static int in_start(const struct audio_stream_in* stream)
3977{
3978 struct stream_in *in = (struct stream_in *)stream;
3979 struct audio_device *adev = in->dev;
3980 int ret = -ENOSYS;
3981
3982 ALOGV("%s in %p", __func__, in);
3983 pthread_mutex_lock(&adev->lock);
3984 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3985 !in->capture_started && in->pcm != NULL) {
3986 if (!in->capture_started) {
3987 ret = start_input_stream(in);
3988 if (ret == 0) {
3989 in->capture_started = true;
3990 }
3991 }
3992 }
3993 pthread_mutex_unlock(&adev->lock);
3994 return ret;
3995}
3996
3997static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3998 int32_t min_size_frames,
3999 struct audio_mmap_buffer_info *info)
4000{
4001 struct stream_in *in = (struct stream_in *)stream;
4002 struct audio_device *adev = in->dev;
4003 int ret = 0;
4004 unsigned int offset1;
4005 unsigned int frames1;
4006 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07004007 uint32_t mmap_size;
4008 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004009
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004010 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004011 pthread_mutex_lock(&adev->lock);
4012 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08004013
Eric Laurent0e46adf2016-12-16 12:49:24 -08004014 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004015 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004016 ret = -EINVAL;
4017 goto exit;
4018 }
4019 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08004020 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004021 ALOGV("%s in %p", __func__, in);
4022 ret = -ENOSYS;
4023 goto exit;
4024 }
4025 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
4026 if (in->pcm_device_id < 0) {
4027 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4028 __func__, in->pcm_device_id, in->usecase);
4029 ret = -EINVAL;
4030 goto exit;
4031 }
Phil Burkbc991042017-02-24 08:06:44 -08004032
4033 adjust_mmap_period_count(&in->config, min_size_frames);
4034
Eric Laurent0e46adf2016-12-16 12:49:24 -08004035 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4036 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
4037 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
4038 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
4039 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
4040 step = "open";
4041 ret = -ENODEV;
4042 goto exit;
4043 }
4044
4045 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
4046 if (ret < 0) {
4047 step = "begin";
4048 goto exit;
4049 }
4050 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07004051 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004052 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07004053 ret = platform_get_mmap_data_fd(adev->platform,
4054 in->pcm_device_id, 1 /*capture*/,
4055 &info->shared_memory_fd,
4056 &mmap_size);
4057 if (ret < 0) {
4058 // Fall back to non exclusive mode
4059 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
4060 } else {
4061 if (mmap_size < buffer_size) {
4062 step = "mmap";
4063 goto exit;
4064 }
4065 // FIXME: indicate exclusive mode support by returning a negative buffer size
4066 info->buffer_size_frames *= -1;
4067 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08004068
Haynes Mathew George96483a22017-03-28 14:52:47 -07004069 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004070
4071 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4072 if (ret < 0) {
4073 step = "commit";
4074 goto exit;
4075 }
4076
Phil Burkbc991042017-02-24 08:06:44 -08004077 in->standby = false;
4078 ret = 0;
4079
Eric Laurent0e46adf2016-12-16 12:49:24 -08004080 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4081 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004082
4083exit:
4084 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004085 if (in->pcm == NULL) {
4086 ALOGE("%s: %s - %d", __func__, step, ret);
4087 } else {
4088 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08004089 pcm_close(in->pcm);
4090 in->pcm = NULL;
4091 }
4092 }
4093 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004094 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004095 return ret;
4096}
4097
4098static int in_get_mmap_position(const struct audio_stream_in *stream,
4099 struct audio_mmap_position *position)
4100{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004101 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004102 struct stream_in *in = (struct stream_in *)stream;
4103 ALOGVV("%s", __func__);
4104 if (position == NULL) {
4105 return -EINVAL;
4106 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004107 lock_input_stream(in);
4108 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
4109 in->pcm == NULL) {
4110 ret = -ENOSYS;
4111 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004112 }
4113 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004114 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004115 if (ret < 0) {
4116 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004117 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004118 }
Andy Hungfc044e12017-03-20 09:24:22 -07004119 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004120exit:
4121 pthread_mutex_unlock(&in->lock);
4122 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004123}
4124
jiabin8962a4d2018-03-19 18:21:24 -07004125static int in_get_active_microphones(const struct audio_stream_in *stream,
4126 struct audio_microphone_characteristic_t *mic_array,
4127 size_t *mic_count) {
4128 struct stream_in *in = (struct stream_in *)stream;
4129 struct audio_device *adev = in->dev;
4130 ALOGVV("%s", __func__);
4131
4132 lock_input_stream(in);
4133 pthread_mutex_lock(&adev->lock);
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004134 int ret = platform_get_active_microphones(adev->platform,
jiabin8962a4d2018-03-19 18:21:24 -07004135 audio_channel_count_from_in_mask(in->channel_mask),
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004136 in->usecase, mic_array, mic_count);
jiabin8962a4d2018-03-19 18:21:24 -07004137 pthread_mutex_unlock(&adev->lock);
4138 pthread_mutex_unlock(&in->lock);
4139
4140 return ret;
4141}
4142
4143static int adev_get_microphones(const struct audio_hw_device *dev,
4144 struct audio_microphone_characteristic_t *mic_array,
4145 size_t *mic_count) {
4146 struct audio_device *adev = (struct audio_device *)dev;
4147 ALOGVV("%s", __func__);
4148
4149 pthread_mutex_lock(&adev->lock);
4150 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
4151 pthread_mutex_unlock(&adev->lock);
4152
4153 return ret;
4154}
Eric Laurent0e46adf2016-12-16 12:49:24 -08004155
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004156static int adev_open_output_stream(struct audio_hw_device *dev,
4157 audio_io_handle_t handle,
4158 audio_devices_t devices,
4159 audio_output_flags_t flags,
4160 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07004161 struct audio_stream_out **stream_out,
4162 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004163{
4164 struct audio_device *adev = (struct audio_device *)dev;
4165 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004166 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004167 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
4168 bool is_usb_dev = audio_is_usb_out_device(devices) &&
4169 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004170
Andy Hungd9653bd2017-08-01 19:31:39 -07004171 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
4172 return -ENOSYS;
4173 }
4174
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004175 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
4176 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004177 *stream_out = NULL;
4178 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4179
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004180 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
4181
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004182 if (devices == AUDIO_DEVICE_NONE)
4183 devices = AUDIO_DEVICE_OUT_SPEAKER;
4184
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004185 out->flags = flags;
4186 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004187 out->dev = adev;
Eric Laurentc4aef752013-09-12 17:45:53 -07004188 out->handle = handle;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004189 out->a2dp_compress_mute = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004190
4191 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004192 if ((is_hdmi || is_usb_dev) &&
4193 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
4194 (flags == AUDIO_OUTPUT_FLAG_NONE ||
4195 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Eric Laurentab805ee2018-03-30 12:20:38 -07004196 audio_format_t req_format = config->format;
4197 audio_channel_mask_t req_channel_mask = config->channel_mask;
4198 uint32_t req_sample_rate = config->sample_rate;
4199
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004200 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004201 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004202 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004203 if (config->sample_rate == 0)
4204 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Eric Laurentab805ee2018-03-30 12:20:38 -07004205 if (config->channel_mask == AUDIO_CHANNEL_NONE)
Haynes Mathew George569b7482017-05-08 14:44:27 -07004206 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
4207 if (config->format == AUDIO_FORMAT_DEFAULT)
4208 config->format = AUDIO_FORMAT_PCM_16_BIT;
4209 } else if (is_usb_dev) {
4210 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
4211 &config->format,
4212 &out->supported_formats[0],
4213 MAX_SUPPORTED_FORMATS,
4214 &config->channel_mask,
4215 &out->supported_channel_masks[0],
4216 MAX_SUPPORTED_CHANNEL_MASKS,
4217 &config->sample_rate,
4218 &out->supported_sample_rates[0],
4219 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004220 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004221 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004222 pthread_mutex_unlock(&adev->lock);
Eric Laurentab805ee2018-03-30 12:20:38 -07004223 if (ret != 0) {
4224 // For MMAP NO IRQ, allow conversions in ADSP
4225 if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
4226 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004227
Eric Laurentab805ee2018-03-30 12:20:38 -07004228 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
4229 config->sample_rate = req_sample_rate;
4230 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
4231 config->channel_mask = req_channel_mask;
4232 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
4233 config->format = req_format;
4234 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004235
Haynes Mathew George569b7482017-05-08 14:44:27 -07004236 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004237 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004238 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004239 if (is_hdmi) {
4240 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4241 out->config = pcm_config_hdmi_multi;
4242 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
4243 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4244 out->config = pcm_config_mmap_playback;
4245 out->stream.start = out_start;
4246 out->stream.stop = out_stop;
4247 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4248 out->stream.get_mmap_position = out_get_mmap_position;
4249 } else {
4250 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4251 out->config = pcm_config_hifi;
4252 }
4253
4254 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004255 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004256 if (is_hdmi) {
4257 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
4258 audio_bytes_per_sample(out->format));
4259 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004260 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004261 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07004262 pthread_mutex_lock(&adev->lock);
4263 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4264 pthread_mutex_unlock(&adev->lock);
4265
4266 // reject offload during card offline to allow
4267 // fallback to s/w paths
4268 if (offline) {
4269 ret = -ENODEV;
4270 goto error_open;
4271 }
4272
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004273 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4274 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4275 ALOGE("%s: Unsupported Offload information", __func__);
4276 ret = -EINVAL;
4277 goto error_open;
4278 }
4279 if (!is_supported_format(config->offload_info.format)) {
4280 ALOGE("%s: Unsupported audio format", __func__);
4281 ret = -EINVAL;
4282 goto error_open;
4283 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004284 out->sample_rate = config->offload_info.sample_rate;
4285 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
4286 out->channel_mask = config->offload_info.channel_mask;
4287 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
4288 out->channel_mask = config->channel_mask;
4289 else
4290 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4291
4292 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004293
4294 out->compr_config.codec = (struct snd_codec *)
4295 calloc(1, sizeof(struct snd_codec));
4296
4297 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004298
4299 out->stream.set_callback = out_set_callback;
4300 out->stream.pause = out_pause;
4301 out->stream.resume = out_resume;
4302 out->stream.drain = out_drain;
4303 out->stream.flush = out_flush;
4304
4305 out->compr_config.codec->id =
4306 get_snd_codec_id(config->offload_info.format);
4307 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
4308 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004309 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004310 out->compr_config.codec->bit_rate =
4311 config->offload_info.bit_rate;
4312 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004313 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004314 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
4315
4316 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4317 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004318
4319 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004320 create_offload_callback_thread(out);
4321 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4322 __func__, config->offload_info.version,
4323 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02004324 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4325 switch (config->sample_rate) {
4326 case 0:
4327 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4328 break;
4329 case 8000:
4330 case 16000:
4331 case 48000:
4332 out->sample_rate = config->sample_rate;
4333 break;
4334 default:
4335 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
4336 config->sample_rate);
4337 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4338 ret = -EINVAL;
4339 goto error_open;
4340 }
4341 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4342 switch (config->channel_mask) {
4343 case AUDIO_CHANNEL_NONE:
4344 case AUDIO_CHANNEL_OUT_STEREO:
4345 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4346 break;
4347 default:
4348 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
4349 config->channel_mask);
4350 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4351 ret = -EINVAL;
4352 goto error_open;
4353 }
4354 switch (config->format) {
4355 case AUDIO_FORMAT_DEFAULT:
4356 case AUDIO_FORMAT_PCM_16_BIT:
4357 out->format = AUDIO_FORMAT_PCM_16_BIT;
4358 break;
4359 default:
4360 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
4361 config->format);
4362 config->format = AUDIO_FORMAT_PCM_16_BIT;
4363 ret = -EINVAL;
4364 goto error_open;
4365 }
4366
4367 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004368 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004369 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004370 case 0:
4371 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
4372 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07004373 case 8000:
4374 case 16000:
4375 case 48000:
4376 out->sample_rate = config->sample_rate;
4377 break;
4378 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004379 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
4380 config->sample_rate);
4381 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4382 ret = -EINVAL;
4383 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004384 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004385 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4386 switch (config->channel_mask) {
4387 case AUDIO_CHANNEL_NONE:
4388 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4389 break;
4390 case AUDIO_CHANNEL_OUT_STEREO:
4391 out->channel_mask = config->channel_mask;
4392 break;
4393 default:
4394 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
4395 config->channel_mask);
4396 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4397 ret = -EINVAL;
4398 break;
4399 }
4400 switch (config->format) {
4401 case AUDIO_FORMAT_DEFAULT:
4402 out->format = AUDIO_FORMAT_PCM_16_BIT;
4403 break;
4404 case AUDIO_FORMAT_PCM_16_BIT:
4405 out->format = config->format;
4406 break;
4407 default:
4408 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
4409 config->format);
4410 config->format = AUDIO_FORMAT_PCM_16_BIT;
4411 ret = -EINVAL;
4412 break;
4413 }
4414 if (ret != 0)
4415 goto error_open;
4416
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004417 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4418 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004419 out->config.rate = out->sample_rate;
4420 out->config.channels =
4421 audio_channel_count_from_out_mask(out->channel_mask);
4422 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004423 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004424 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
4425 switch (config->sample_rate) {
4426 case 0:
4427 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4428 break;
4429 case 8000:
4430 case 16000:
4431 case 32000:
4432 case 48000:
4433 out->sample_rate = config->sample_rate;
4434 break;
4435 default:
4436 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
4437 config->sample_rate);
4438 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4439 ret = -EINVAL;
4440 break;
4441 }
Eric Laurentad2dde92017-09-20 18:27:31 -07004442 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004443 switch (config->channel_mask) {
4444 case AUDIO_CHANNEL_NONE:
4445 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4446 break;
4447 case AUDIO_CHANNEL_OUT_STEREO:
4448 out->channel_mask = config->channel_mask;
4449 break;
4450 default:
4451 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
4452 config->channel_mask);
4453 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4454 ret = -EINVAL;
4455 break;
4456 }
4457 switch (config->format) {
4458 case AUDIO_FORMAT_DEFAULT:
4459 out->format = AUDIO_FORMAT_PCM_16_BIT;
4460 break;
4461 case AUDIO_FORMAT_PCM_16_BIT:
4462 out->format = config->format;
4463 break;
4464 default:
4465 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
4466 config->format);
4467 config->format = AUDIO_FORMAT_PCM_16_BIT;
4468 ret = -EINVAL;
4469 break;
4470 }
4471 if (ret != 0)
4472 goto error_open;
4473
vivek mehtaa68fea62017-06-08 19:04:02 -07004474 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07004475 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4476 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004477 out->config.rate = out->sample_rate;
4478 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07004479 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004480 out->sample_rate,
4481 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07004482 out->config.channels,
4483 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004484 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07004485 out->config.period_size = buffer_size / frame_size;
4486 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
4487 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004488 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004489 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07004490 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4491 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004492 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07004493 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
4494 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004495 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07004496 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004497 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004498 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004499 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004500 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4501 out->config = pcm_config_mmap_playback;
4502 out->stream.start = out_start;
4503 out->stream.stop = out_stop;
4504 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4505 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004506 } else {
4507 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4508 out->config = pcm_config_low_latency;
4509 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004510
4511 if (config->sample_rate == 0) {
4512 out->sample_rate = out->config.rate;
4513 } else {
4514 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004515 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004516 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
4517 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
4518 } else {
4519 out->channel_mask = config->channel_mask;
4520 }
4521 if (config->format == AUDIO_FORMAT_DEFAULT)
4522 out->format = audio_format_from_pcm_format(out->config.format);
4523 else if (!audio_is_linear_pcm(config->format)) {
4524 config->format = AUDIO_FORMAT_PCM_16_BIT;
4525 ret = -EINVAL;
4526 goto error_open;
4527 } else {
4528 out->format = config->format;
4529 }
4530
4531 out->config.rate = out->sample_rate;
4532 out->config.channels =
4533 audio_channel_count_from_out_mask(out->channel_mask);
4534 if (out->format != audio_format_from_pcm_format(out->config.format)) {
4535 out->config.format = pcm_format_from_audio_format(out->format);
4536 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004537 }
Kevin Rocard50eff892017-05-02 16:52:05 -07004538
4539 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
4540 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004541 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004542 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
4543 __func__, config->sample_rate, config->format, config->channel_mask);
4544 config->sample_rate = out->sample_rate;
4545 config->format = out->format;
4546 config->channel_mask = out->channel_mask;
4547 ret = -EINVAL;
4548 goto error_open;
4549 }
4550
Andy Hung6fcba9c2014-03-18 11:53:32 -07004551 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
4552 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004553
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004554 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004555 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004556 adev->primary_output = out;
4557 else {
4558 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004559 ret = -EEXIST;
4560 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004561 }
4562 }
4563
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004564 /* Check if this usecase is already existing */
4565 pthread_mutex_lock(&adev->lock);
4566 if (get_usecase_from_list(adev, out->usecase) != NULL) {
4567 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004568 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004569 ret = -EEXIST;
4570 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004571 }
4572 pthread_mutex_unlock(&adev->lock);
4573
4574 out->stream.common.get_sample_rate = out_get_sample_rate;
4575 out->stream.common.set_sample_rate = out_set_sample_rate;
4576 out->stream.common.get_buffer_size = out_get_buffer_size;
4577 out->stream.common.get_channels = out_get_channels;
4578 out->stream.common.get_format = out_get_format;
4579 out->stream.common.set_format = out_set_format;
4580 out->stream.common.standby = out_standby;
4581 out->stream.common.dump = out_dump;
4582 out->stream.common.set_parameters = out_set_parameters;
4583 out->stream.common.get_parameters = out_get_parameters;
4584 out->stream.common.add_audio_effect = out_add_audio_effect;
4585 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4586 out->stream.get_latency = out_get_latency;
4587 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004588#ifdef NO_AUDIO_OUT
4589 out->stream.write = out_write_for_no_output;
4590#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004591 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004592#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004593 out->stream.get_render_position = out_get_render_position;
4594 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004595 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004596
Eric Laurent0e46adf2016-12-16 12:49:24 -08004597 if (out->realtime)
4598 out->af_period_multiplier = af_period_multiplier;
4599 else
4600 out->af_period_multiplier = 1;
4601
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004602 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004603 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004604 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004605
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004606 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004607 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004608 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4609
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004610 config->format = out->stream.common.get_format(&out->stream.common);
4611 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4612 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4613
Kevin Rocarda325aa22018-04-03 09:15:52 -07004614 register_format(out->format, out->supported_formats);
4615 register_channel_mask(out->channel_mask, out->supported_channel_masks);
4616 register_sample_rate(out->sample_rate, out->supported_sample_rates);
4617
Andy Hunga452b0a2017-03-15 14:51:15 -07004618 out->error_log = error_log_create(
4619 ERROR_LOG_ENTRIES,
4620 1000000000 /* aggregate consecutive identical errors within one second in ns */);
4621
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004622 /*
4623 By locking output stream before registering, we allow the callback
4624 to update stream's state only after stream's initial state is set to
4625 adev state.
4626 */
4627 lock_output_stream(out);
4628 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4629 pthread_mutex_lock(&adev->lock);
4630 out->card_status = adev->card_status;
4631 pthread_mutex_unlock(&adev->lock);
4632 pthread_mutex_unlock(&out->lock);
4633
vivek mehta4a824772017-06-08 19:05:49 -07004634 stream_app_type_cfg_init(&out->app_type_cfg);
4635
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004636 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004637
Eric Laurent994a6932013-07-17 11:51:42 -07004638 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004639 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004640
4641error_open:
4642 free(out);
4643 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07004644 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004645 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004646}
4647
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004648static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004649 struct audio_stream_out *stream)
4650{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004651 struct stream_out *out = (struct stream_out *)stream;
4652 struct audio_device *adev = out->dev;
4653
Eric Laurent994a6932013-07-17 11:51:42 -07004654 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004655
4656 // must deregister from sndmonitor first to prevent races
4657 // between the callback and close_stream
4658 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004659 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004660 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
4661 destroy_offload_callback_thread(out);
4662
4663 if (out->compr_config.codec != NULL)
4664 free(out->compr_config.codec);
4665 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004666
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004667 out->a2dp_compress_mute = false;
4668
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004669 if (adev->voice_tx_output == out)
4670 adev->voice_tx_output = NULL;
4671
Andy Hunga452b0a2017-03-15 14:51:15 -07004672 error_log_destroy(out->error_log);
4673 out->error_log = NULL;
4674
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004675 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004676 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004677 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004678 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004679 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004680}
4681
4682static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4683{
4684 struct audio_device *adev = (struct audio_device *)dev;
4685 struct str_parms *parms;
4686 char *str;
4687 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004688 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004689 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07004690 int status = 0;
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004691 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004692
Joe Onorato188b6222016-03-01 11:02:27 -08004693 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004694
4695 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004696
4697 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004698 status = voice_set_parameters(adev, parms);
4699 if (status != 0) {
4700 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004701 }
4702
4703 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4704 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07004705 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004706 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4707 adev->bluetooth_nrec = true;
4708 else
4709 adev->bluetooth_nrec = false;
4710 }
4711
4712 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4713 if (ret >= 0) {
4714 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4715 adev->screen_off = false;
4716 else
4717 adev->screen_off = true;
4718 }
4719
jasmine cha270b7762018-03-30 15:41:33 +08004720#ifndef MAXXAUDIO_QDSP_ENABLED
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004721 ret = str_parms_get_int(parms, "rotation", &val);
4722 if (ret >= 0) {
4723 bool reverse_speakers = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004724 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004725 // FIXME: note that the code below assumes that the speakers are in the correct placement
4726 // relative to the user when the device is rotated 90deg from its default rotation. This
4727 // assumption is device-specific, not platform-specific like this code.
4728 case 270:
4729 reverse_speakers = true;
4730 break;
4731 case 0:
4732 case 90:
4733 case 180:
4734 break;
4735 default:
4736 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07004737 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004738 }
Eric Laurent03f09432014-03-25 18:09:11 -07004739 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004740 // check and set swap
4741 // - check if orientation changed and speaker active
4742 // - set rotation and cache the rotation value
4743 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004744 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004745 }
jasmine cha270b7762018-03-30 15:41:33 +08004746#endif
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004747
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004748 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4749 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004750 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004751 }
4752
David Linee3fe402017-03-13 10:00:42 -07004753 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4754 if (ret >= 0) {
4755 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004756 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004757 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4758 if (ret >= 0) {
4759 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004760 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004761 }
Eric Laurent99dab492017-06-17 15:19:08 -07004762 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004763 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4764 if (ret >= 0) {
4765 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004766 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004767 }
4768 }
4769 }
4770
4771 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4772 if (ret >= 0) {
4773 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004774 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004775 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4776 if (ret >= 0) {
4777 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004778 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004779 }
Eric Laurent99dab492017-06-17 15:19:08 -07004780 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004781 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4782 if (ret >= 0) {
4783 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004784 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004785 }
4786 }
4787 }
4788
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004789 audio_extn_hfp_set_parameters(adev, parms);
jasmine cha270b7762018-03-30 15:41:33 +08004790 audio_extn_ma_set_parameters(adev, parms);
4791
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004792 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
4793 if (status >= 0 && a2dp_reconfig) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004794 struct audio_usecase *usecase;
4795 struct listnode *node;
4796 list_for_each(node, &adev->usecase_list) {
4797 usecase = node_to_item(node, struct audio_usecase, list);
4798 if ((usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004799 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004800 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
4801
4802 pthread_mutex_unlock(&adev->lock);
4803 lock_output_stream(usecase->stream.out);
4804 pthread_mutex_lock(&adev->lock);
4805 audio_extn_a2dp_set_handoff_mode(true);
4806 // force device switch to reconfigure encoder
4807 select_devices(adev, usecase->id);
4808 audio_extn_a2dp_set_handoff_mode(false);
4809 pthread_mutex_unlock(&usecase->stream.out->lock);
4810 break;
4811 }
4812 }
4813 }
4814
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004815done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004816 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004817 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004818 ALOGV("%s: exit with code(%d)", __func__, status);
4819 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004820}
4821
4822static char* adev_get_parameters(const struct audio_hw_device *dev,
4823 const char *keys)
4824{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004825 struct audio_device *adev = (struct audio_device *)dev;
4826 struct str_parms *reply = str_parms_create();
4827 struct str_parms *query = str_parms_create_str(keys);
4828 char *str;
4829
4830 pthread_mutex_lock(&adev->lock);
4831
4832 voice_get_parameters(adev, query, reply);
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004833 audio_extn_a2dp_get_parameters(query, reply);
4834
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004835 str = str_parms_to_str(reply);
4836 str_parms_destroy(query);
4837 str_parms_destroy(reply);
4838
4839 pthread_mutex_unlock(&adev->lock);
4840 ALOGV("%s: exit: returns - %s", __func__, str);
4841 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004842}
4843
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004844static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004845{
4846 return 0;
4847}
4848
Haynes Mathew George5191a852013-09-11 14:19:36 -07004849static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4850{
4851 int ret;
4852 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004853
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004854 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4855
Haynes Mathew George5191a852013-09-11 14:19:36 -07004856 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004857 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004858 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004859
Haynes Mathew George5191a852013-09-11 14:19:36 -07004860 return ret;
4861}
4862
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004863static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004864{
4865 return -ENOSYS;
4866}
4867
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004868static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4869 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004870{
4871 return -ENOSYS;
4872}
4873
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004874static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004875{
4876 return -ENOSYS;
4877}
4878
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004879static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004880{
4881 return -ENOSYS;
4882}
4883
4884static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4885{
4886 struct audio_device *adev = (struct audio_device *)dev;
4887
4888 pthread_mutex_lock(&adev->lock);
4889 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004890 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004891 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004892 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4893 voice_is_in_call(adev)) {
4894 voice_stop_call(adev);
4895 adev->current_call_output = NULL;
4896 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004897 }
4898 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004899
4900 audio_extn_extspk_set_mode(adev->extspk, mode);
4901
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004902 return 0;
4903}
4904
4905static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4906{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004907 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004908 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004909
Eric Laurent2bafff12016-03-17 12:17:23 -07004910 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004911 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004912 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4913 ret = audio_extn_hfp_set_mic_mute(adev, state);
4914 } else {
4915 ret = voice_set_mic_mute(adev, state);
4916 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004917 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004918 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004919
4920 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004921}
4922
4923static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4924{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004925 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004926 return 0;
4927}
4928
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004929static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004930 const struct audio_config *config)
4931{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004932 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004933
Eric Laurent74b55762017-07-09 17:04:53 -07004934 /* Don't know if USB HIFI in this context so use true to be conservative */
4935 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4936 true /*is_usb_hifi */) != 0)
4937 return 0;
4938
vivek mehtaa68fea62017-06-08 19:04:02 -07004939 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4940 config->sample_rate, config->format,
4941 channel_count,
4942 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004943}
4944
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004945static bool adev_input_allow_hifi_record(struct audio_device *adev,
4946 audio_devices_t devices,
4947 audio_input_flags_t flags,
4948 audio_source_t source) {
4949 const bool allowed = true;
4950
4951 if (!audio_is_usb_in_device(devices))
4952 return !allowed;
4953
4954 switch (flags) {
4955 case AUDIO_INPUT_FLAG_NONE:
4956 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4957 break;
4958 default:
4959 return !allowed;
4960 }
4961
4962 switch (source) {
4963 case AUDIO_SOURCE_DEFAULT:
4964 case AUDIO_SOURCE_MIC:
4965 case AUDIO_SOURCE_UNPROCESSED:
4966 break;
4967 default:
4968 return !allowed;
4969 }
4970
4971 switch (adev->mode) {
4972 case 0:
4973 break;
4974 default:
4975 return !allowed;
4976 }
4977
4978 return allowed;
4979}
4980
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004981static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004982 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004983 audio_devices_t devices,
4984 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004985 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004986 audio_input_flags_t flags,
4987 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004988 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004989{
4990 struct audio_device *adev = (struct audio_device *)dev;
4991 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004992 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004993 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004994 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004995 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004996 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4997 devices,
4998 flags,
4999 source);
Eric Laurent74b55762017-07-09 17:04:53 -07005000 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005001 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005002
Andy Hungd9653bd2017-08-01 19:31:39 -07005003 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
5004 return -ENOSYS;
5005 }
5006
Eric Laurent74b55762017-07-09 17:04:53 -07005007 if (!(is_usb_dev && may_use_hifi_record)) {
5008 if (config->sample_rate == 0)
5009 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
5010 if (config->channel_mask == AUDIO_CHANNEL_NONE)
5011 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5012 if (config->format == AUDIO_FORMAT_DEFAULT)
5013 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005014
Eric Laurent74b55762017-07-09 17:04:53 -07005015 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
5016
5017 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
5018 return -EINVAL;
5019 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005020
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005021 if (audio_extn_tfa_98xx_is_supported() &&
5022 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005023 return -EINVAL;
5024
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005025 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
5026
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005027 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005028 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005029
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005030 in->stream.common.get_sample_rate = in_get_sample_rate;
5031 in->stream.common.set_sample_rate = in_set_sample_rate;
5032 in->stream.common.get_buffer_size = in_get_buffer_size;
5033 in->stream.common.get_channels = in_get_channels;
5034 in->stream.common.get_format = in_get_format;
5035 in->stream.common.set_format = in_set_format;
5036 in->stream.common.standby = in_standby;
5037 in->stream.common.dump = in_dump;
5038 in->stream.common.set_parameters = in_set_parameters;
5039 in->stream.common.get_parameters = in_get_parameters;
5040 in->stream.common.add_audio_effect = in_add_audio_effect;
5041 in->stream.common.remove_audio_effect = in_remove_audio_effect;
5042 in->stream.set_gain = in_set_gain;
5043 in->stream.read = in_read;
5044 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08005045 in->stream.get_capture_position = in_get_capture_position;
jiabin8962a4d2018-03-19 18:21:24 -07005046 in->stream.get_active_microphones = in_get_active_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005047
5048 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005049 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005050 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005051 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005052 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005053 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005054
Arun Mirpuriba2749a2018-04-17 14:32:24 -07005055 ALOGV("%s: source = %d, config->channel_mask = %d", __func__, source, config->channel_mask);
5056 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
5057 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
5058 /* Force channel config requested to mono if incall
5059 record is being requested for only uplink/downlink */
5060 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
5061 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5062 ret = -EINVAL;
5063 goto err_open;
5064 }
5065 }
5066
Haynes Mathew George569b7482017-05-08 14:44:27 -07005067 if (is_usb_dev && may_use_hifi_record) {
5068 /* HiFi record selects an appropriate format, channel, rate combo
5069 depending on sink capabilities*/
5070 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
5071 &config->format,
5072 &in->supported_formats[0],
5073 MAX_SUPPORTED_FORMATS,
5074 &config->channel_mask,
5075 &in->supported_channel_masks[0],
5076 MAX_SUPPORTED_CHANNEL_MASKS,
5077 &config->sample_rate,
5078 &in->supported_sample_rates[0],
5079 MAX_SUPPORTED_SAMPLE_RATES);
5080 if (ret != 0) {
5081 ret = -EINVAL;
5082 goto err_open;
5083 }
Eric Laurent74b55762017-07-09 17:04:53 -07005084 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005085 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07005086 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07005087 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
5088 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
5089 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5090 bool ret_error = false;
5091 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5092 from HAL is 8_24
5093 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5094 8_24 return error indicating supported format is 8_24
5095 *> In case of any other source requesting 24 bit or float return error
5096 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07005097
vivek mehta57ff9b52016-04-28 14:13:08 -07005098 on error flinger will retry with supported format passed
5099 */
juyuchenbe5c67e2018-08-29 17:19:20 +08005100 if (!is_supported_24bits_audiosource(source)) {
vivek mehta57ff9b52016-04-28 14:13:08 -07005101 config->format = AUDIO_FORMAT_PCM_16_BIT;
5102 ret_error = true;
5103 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
5104 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
5105 ret_error = true;
5106 }
5107
5108 if (ret_error) {
5109 ret = -EINVAL;
5110 goto err_open;
5111 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005112 }
5113
vivek mehta57ff9b52016-04-28 14:13:08 -07005114 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07005115 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07005116
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005117 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005118 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
5119 if (config->sample_rate == 0)
5120 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5121 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5122 config->sample_rate != 8000) {
5123 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5124 ret = -EINVAL;
5125 goto err_open;
5126 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005127
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005128 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5129 config->format = AUDIO_FORMAT_PCM_16_BIT;
5130 ret = -EINVAL;
5131 goto err_open;
5132 }
5133
5134 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5135 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07005136 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005137 } else if (is_usb_dev && may_use_hifi_record) {
5138 in->usecase = USECASE_AUDIO_RECORD_HIFI;
5139 in->config = pcm_config_audio_capture;
5140 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005141 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5142 config->sample_rate,
5143 config->format,
5144 channel_count,
5145 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005146 in->config.period_size = buffer_size / frame_size;
5147 in->config.rate = config->sample_rate;
5148 in->af_period_multiplier = 1;
5149 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005150 } else {
5151 in->usecase = USECASE_AUDIO_RECORD;
5152 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08005153 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005154 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07005155#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005156 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07005157#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08005158 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005159 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08005160 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005161 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005162 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5163 config->sample_rate,
5164 config->format,
5165 channel_count,
5166 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005167 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005168 in->config.rate = config->sample_rate;
5169 in->af_period_multiplier = 1;
5170 } else {
5171 // period size is left untouched for rt mode playback
5172 in->config = pcm_config_audio_capture_rt;
5173 in->af_period_multiplier = af_period_multiplier;
5174 }
5175 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
5176 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005177 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08005178 in->usecase = USECASE_AUDIO_RECORD_MMAP;
5179 in->config = pcm_config_mmap_capture;
5180 in->stream.start = in_start;
5181 in->stream.stop = in_stop;
5182 in->stream.create_mmap_buffer = in_create_mmap_buffer;
5183 in->stream.get_mmap_position = in_get_mmap_position;
5184 in->af_period_multiplier = 1;
5185 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07005186 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07005187 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07005188 (config->sample_rate == 8000 ||
5189 config->sample_rate == 16000 ||
5190 config->sample_rate == 32000 ||
5191 config->sample_rate == 48000) &&
5192 channel_count == 1) {
5193 in->usecase = USECASE_AUDIO_RECORD_VOIP;
5194 in->config = pcm_config_audio_capture;
5195 frame_size = audio_stream_in_frame_size(&in->stream);
5196 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
5197 config->sample_rate,
5198 config->format,
5199 channel_count, false /*is_low_latency*/);
5200 in->config.period_size = buffer_size / frame_size;
5201 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
5202 in->config.rate = config->sample_rate;
5203 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005204 } else {
5205 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005206 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005207 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5208 config->sample_rate,
5209 config->format,
5210 channel_count,
5211 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005212 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005213 in->config.rate = config->sample_rate;
5214 in->af_period_multiplier = 1;
5215 }
5216 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
5217 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005218 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08005219
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005220 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07005221 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005222
Kevin Rocarda325aa22018-04-03 09:15:52 -07005223
5224 register_format(in->format, in->supported_formats);
5225 register_channel_mask(in->channel_mask, in->supported_channel_masks);
5226 register_sample_rate(in->sample_rate, in->supported_sample_rates);
5227
Andy Hungd13f0d32017-06-12 13:58:37 -07005228 in->error_log = error_log_create(
5229 ERROR_LOG_ENTRIES,
5230 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
5231
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005232 /* This stream could be for sound trigger lab,
5233 get sound trigger pcm if present */
5234 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005235
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005236 lock_input_stream(in);
5237 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5238 pthread_mutex_lock(&adev->lock);
5239 in->card_status = adev->card_status;
5240 pthread_mutex_unlock(&adev->lock);
5241 pthread_mutex_unlock(&in->lock);
5242
vivek mehta4a824772017-06-08 19:05:49 -07005243 stream_app_type_cfg_init(&in->app_type_cfg);
5244
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005245 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005246 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005247 return 0;
5248
5249err_open:
5250 free(in);
5251 *stream_in = NULL;
5252 return ret;
5253}
5254
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005255static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005256 struct audio_stream_in *stream)
5257{
Andy Hungd13f0d32017-06-12 13:58:37 -07005258 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005259 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005260
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005261 // must deregister from sndmonitor first to prevent races
5262 // between the callback and close_stream
5263 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005264 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07005265
5266 error_log_destroy(in->error_log);
5267 in->error_log = NULL;
5268
Andy Hung0dbb52b2017-08-09 13:51:38 -07005269 pthread_mutex_destroy(&in->pre_lock);
5270 pthread_mutex_destroy(&in->lock);
5271
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005272 free(stream);
5273
5274 return;
5275}
5276
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005277static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005278{
5279 return 0;
5280}
5281
Andy Hung31aca912014-03-20 17:14:59 -07005282/* verifies input and output devices and their capabilities.
5283 *
5284 * This verification is required when enabling extended bit-depth or
5285 * sampling rates, as not all qcom products support it.
5286 *
5287 * Suitable for calling only on initialization such as adev_open().
5288 * It fills the audio_device use_case_table[] array.
5289 *
5290 * Has a side-effect that it needs to configure audio routing / devices
5291 * in order to power up the devices and read the device parameters.
5292 * It does not acquire any hw device lock. Should restore the devices
5293 * back to "normal state" upon completion.
5294 */
5295static int adev_verify_devices(struct audio_device *adev)
5296{
5297 /* enumeration is a bit difficult because one really wants to pull
5298 * the use_case, device id, etc from the hidden pcm_device_table[].
5299 * In this case there are the following use cases and device ids.
5300 *
5301 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
5302 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005303 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07005304 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
5305 * [USECASE_AUDIO_RECORD] = {0, 0},
5306 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
5307 * [USECASE_VOICE_CALL] = {2, 2},
5308 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005309 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07005310 * USECASE_VOICE_CALL omitted, but possible for either input or output.
5311 */
5312
5313 /* should be the usecases enabled in adev_open_input_stream() */
5314 static const int test_in_usecases[] = {
5315 USECASE_AUDIO_RECORD,
5316 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
5317 };
5318 /* should be the usecases enabled in adev_open_output_stream()*/
5319 static const int test_out_usecases[] = {
5320 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
5321 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
5322 };
5323 static const usecase_type_t usecase_type_by_dir[] = {
5324 PCM_PLAYBACK,
5325 PCM_CAPTURE,
5326 };
5327 static const unsigned flags_by_dir[] = {
5328 PCM_OUT,
5329 PCM_IN,
5330 };
5331
5332 size_t i;
5333 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005334 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07005335 char info[512]; /* for possible debug info */
5336
5337 for (dir = 0; dir < 2; ++dir) {
5338 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
5339 const unsigned flags_dir = flags_by_dir[dir];
5340 const size_t testsize =
5341 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
5342 const int *testcases =
5343 dir ? test_in_usecases : test_out_usecases;
5344 const audio_devices_t audio_device =
5345 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
5346
5347 for (i = 0; i < testsize; ++i) {
5348 const audio_usecase_t audio_usecase = testcases[i];
5349 int device_id;
5350 snd_device_t snd_device;
5351 struct pcm_params **pparams;
5352 struct stream_out out;
5353 struct stream_in in;
5354 struct audio_usecase uc_info;
5355 int retval;
5356
5357 pparams = &adev->use_case_table[audio_usecase];
5358 pcm_params_free(*pparams); /* can accept null input */
5359 *pparams = NULL;
5360
5361 /* find the device ID for the use case (signed, for error) */
5362 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
5363 if (device_id < 0)
5364 continue;
5365
5366 /* prepare structures for device probing */
5367 memset(&uc_info, 0, sizeof(uc_info));
5368 uc_info.id = audio_usecase;
5369 uc_info.type = usecase_type;
5370 if (dir) {
5371 adev->active_input = &in;
5372 memset(&in, 0, sizeof(in));
5373 in.device = audio_device;
5374 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
5375 uc_info.stream.in = &in;
5376 } else {
5377 adev->active_input = NULL;
5378 }
5379 memset(&out, 0, sizeof(out));
5380 out.devices = audio_device; /* only field needed in select_devices */
5381 uc_info.stream.out = &out;
5382 uc_info.devices = audio_device;
5383 uc_info.in_snd_device = SND_DEVICE_NONE;
5384 uc_info.out_snd_device = SND_DEVICE_NONE;
5385 list_add_tail(&adev->usecase_list, &uc_info.list);
5386
5387 /* select device - similar to start_(in/out)put_stream() */
5388 retval = select_devices(adev, audio_usecase);
5389 if (retval >= 0) {
5390 *pparams = pcm_params_get(card_id, device_id, flags_dir);
5391#if LOG_NDEBUG == 0
5392 if (*pparams) {
5393 ALOGV("%s: (%s) card %d device %d", __func__,
5394 dir ? "input" : "output", card_id, device_id);
5395 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07005396 } else {
5397 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
5398 }
5399#endif
5400 }
5401
5402 /* deselect device - similar to stop_(in/out)put_stream() */
5403 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07005404 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07005405 /* 2. Disable the rx device */
5406 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07005407 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07005408 list_remove(&uc_info.list);
5409 }
5410 }
5411 adev->active_input = NULL; /* restore adev state */
5412 return 0;
5413}
5414
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005415static int adev_close(hw_device_t *device)
5416{
Andy Hung31aca912014-03-20 17:14:59 -07005417 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005418 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005419
5420 if (!adev)
5421 return 0;
5422
5423 pthread_mutex_lock(&adev_init_lock);
5424
5425 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005426 audio_extn_snd_mon_unregister_listener(adev);
5427 audio_extn_tfa_98xx_deinit();
jasmine cha270b7762018-03-30 15:41:33 +08005428 audio_extn_ma_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005429 audio_route_free(adev->audio_route);
5430 free(adev->snd_dev_ref_cnt);
5431 platform_deinit(adev->platform);
5432 audio_extn_extspk_deinit(adev->extspk);
5433 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005434 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005435 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
5436 pcm_params_free(adev->use_case_table[i]);
5437 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005438 if (adev->adm_deinit)
5439 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005440 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005441 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07005442 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07005443
5444 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005445
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005446 return 0;
5447}
5448
Glenn Kasten4f993392014-05-14 07:30:48 -07005449/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5450 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5451 * just that it _might_ work.
5452 */
5453static int period_size_is_plausible_for_low_latency(int period_size)
5454{
5455 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005456 case 48:
5457 case 96:
5458 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07005459 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005460 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07005461 case 240:
5462 case 320:
5463 case 480:
5464 return 1;
5465 default:
5466 return 0;
5467 }
5468}
5469
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005470static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
5471{
5472 int card;
5473 card_status_t status;
5474
5475 if (!parms)
5476 return;
5477
5478 if (parse_snd_card_status(parms, &card, &status) < 0)
5479 return;
5480
5481 pthread_mutex_lock(&adev->lock);
5482 bool valid_cb = (card == adev->snd_card);
5483 if (valid_cb) {
5484 if (adev->card_status != status) {
5485 adev->card_status = status;
5486 platform_snd_card_update(adev->platform, status);
5487 }
5488 }
5489 pthread_mutex_unlock(&adev->lock);
5490 return;
5491}
5492
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005493/* out and adev lock held */
5494static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
5495{
5496 struct audio_usecase *uc_info;
5497 float left_p;
5498 float right_p;
5499 audio_devices_t devices;
5500
5501 uc_info = get_usecase_from_list(adev, out->usecase);
5502 if (uc_info == NULL) {
5503 ALOGE("%s: Could not find the usecase (%d) in the list",
5504 __func__, out->usecase);
5505 return -EINVAL;
5506 }
5507
5508 ALOGD("%s: enter: usecase(%d: %s)", __func__,
5509 out->usecase, use_case_table[out->usecase]);
5510
5511 if (restore) {
5512 // restore A2DP device for active usecases and unmute if required
5513 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
5514 !is_a2dp_device(uc_info->out_snd_device)) {
5515 ALOGD("%s: restoring A2DP and unmuting stream", __func__);
5516 select_devices(adev, uc_info->id);
5517 pthread_mutex_lock(&out->compr_mute_lock);
5518 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5519 (out->a2dp_compress_mute)) {
5520 out->a2dp_compress_mute = false;
5521 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5522 }
5523 pthread_mutex_unlock(&out->compr_mute_lock);
5524 }
5525 } else {
5526 // mute compress stream if suspended
5527 pthread_mutex_lock(&out->compr_mute_lock);
5528 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5529 (!out->a2dp_compress_mute)) {
5530 if (!out->standby) {
5531 ALOGD("%s: selecting speaker and muting stream", __func__);
5532 devices = out->devices;
5533 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
5534 left_p = out->volume_l;
5535 right_p = out->volume_r;
5536 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5537 compress_pause(out->compr);
5538 set_compr_volume(&out->stream, 0.0f, 0.0f);
5539 out->a2dp_compress_mute = true;
5540 select_devices(adev, out->usecase);
5541 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5542 compress_resume(out->compr);
5543 out->devices = devices;
5544 out->volume_l = left_p;
5545 out->volume_r = right_p;
5546 }
5547 }
5548 pthread_mutex_unlock(&out->compr_mute_lock);
5549 }
5550 ALOGV("%s: exit", __func__);
5551 return 0;
5552}
5553
5554int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
5555{
5556 int ret = 0;
5557
5558 lock_output_stream(out);
5559 pthread_mutex_lock(&adev->lock);
5560
5561 ret = check_a2dp_restore_l(adev, out, restore);
5562
5563 pthread_mutex_unlock(&adev->lock);
5564 pthread_mutex_unlock(&out->lock);
5565 return ret;
5566}
5567
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005568static int adev_open(const hw_module_t *module, const char *name,
5569 hw_device_t **device)
5570{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005571 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005572
Eric Laurent2bafff12016-03-17 12:17:23 -07005573 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005574 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005575 pthread_mutex_lock(&adev_init_lock);
5576 if (audio_device_ref_count != 0) {
5577 *device = &adev->device.common;
5578 audio_device_ref_count++;
5579 ALOGV("%s: returning existing instance of adev", __func__);
5580 ALOGV("%s: exit", __func__);
5581 pthread_mutex_unlock(&adev_init_lock);
5582 return 0;
5583 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005584 adev = calloc(1, sizeof(struct audio_device));
5585
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005586 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5587
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005588 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5589 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5590 adev->device.common.module = (struct hw_module_t *)module;
5591 adev->device.common.close = adev_close;
5592
5593 adev->device.init_check = adev_init_check;
5594 adev->device.set_voice_volume = adev_set_voice_volume;
5595 adev->device.set_master_volume = adev_set_master_volume;
5596 adev->device.get_master_volume = adev_get_master_volume;
5597 adev->device.set_master_mute = adev_set_master_mute;
5598 adev->device.get_master_mute = adev_get_master_mute;
5599 adev->device.set_mode = adev_set_mode;
5600 adev->device.set_mic_mute = adev_set_mic_mute;
5601 adev->device.get_mic_mute = adev_get_mic_mute;
5602 adev->device.set_parameters = adev_set_parameters;
5603 adev->device.get_parameters = adev_get_parameters;
5604 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5605 adev->device.open_output_stream = adev_open_output_stream;
5606 adev->device.close_output_stream = adev_close_output_stream;
5607 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005608
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005609 adev->device.close_input_stream = adev_close_input_stream;
5610 adev->device.dump = adev_dump;
jiabin8962a4d2018-03-19 18:21:24 -07005611 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005612
5613 /* Set the default route before the PCM stream is opened */
5614 pthread_mutex_lock(&adev->lock);
5615 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005616 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005617 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005618 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005619 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005620 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005621 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005622 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005623 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005624 pthread_mutex_unlock(&adev->lock);
5625
5626 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005627 adev->platform = platform_init(adev);
5628 if (!adev->platform) {
5629 free(adev->snd_dev_ref_cnt);
5630 free(adev);
5631 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5632 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005633 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005634 return -EINVAL;
5635 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05005636 adev->extspk = audio_extn_extspk_init(adev);
5637
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005638 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5639 if (adev->visualizer_lib == NULL) {
5640 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5641 } else {
5642 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5643 adev->visualizer_start_output =
Aniket Kumar Lata72a3cea2018-04-06 13:56:37 -07005644 (int (*)(audio_io_handle_t, int, int, int))dlsym(adev->visualizer_lib,
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005645 "visualizer_hal_start_output");
5646 adev->visualizer_stop_output =
5647 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5648 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07005649 }
5650
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005651 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5652 if (adev->offload_effects_lib == NULL) {
5653 ALOGW("%s: DLOPEN failed for %s", __func__,
5654 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5655 } else {
5656 ALOGV("%s: DLOPEN successful for %s", __func__,
5657 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5658 adev->offload_effects_start_output =
5659 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5660 "offload_effects_bundle_hal_start_output");
5661 adev->offload_effects_stop_output =
5662 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5663 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07005664 }
5665
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005666 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5667 if (adev->adm_lib == NULL) {
5668 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5669 } else {
5670 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5671 adev->adm_init = (adm_init_t)
5672 dlsym(adev->adm_lib, "adm_init");
5673 adev->adm_deinit = (adm_deinit_t)
5674 dlsym(adev->adm_lib, "adm_deinit");
5675 adev->adm_register_input_stream = (adm_register_input_stream_t)
5676 dlsym(adev->adm_lib, "adm_register_input_stream");
5677 adev->adm_register_output_stream = (adm_register_output_stream_t)
5678 dlsym(adev->adm_lib, "adm_register_output_stream");
5679 adev->adm_deregister_stream = (adm_deregister_stream_t)
5680 dlsym(adev->adm_lib, "adm_deregister_stream");
5681 adev->adm_request_focus = (adm_request_focus_t)
5682 dlsym(adev->adm_lib, "adm_request_focus");
5683 adev->adm_abandon_focus = (adm_abandon_focus_t)
5684 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08005685 adev->adm_set_config = (adm_set_config_t)
5686 dlsym(adev->adm_lib, "adm_set_config");
5687 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5688 dlsym(adev->adm_lib, "adm_request_focus_v2");
5689 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5690 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5691 adev->adm_on_routing_change = (adm_on_routing_change_t)
5692 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005693 }
5694
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005695 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005696 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005697
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005698 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005699
Andy Hung31aca912014-03-20 17:14:59 -07005700 if (k_enable_extended_precision)
5701 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005702
Glenn Kasten4f993392014-05-14 07:30:48 -07005703 char value[PROPERTY_VALUE_MAX];
5704 int trial;
5705 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5706 trial = atoi(value);
5707 if (period_size_is_plausible_for_low_latency(trial)) {
5708 pcm_config_low_latency.period_size = trial;
5709 pcm_config_low_latency.start_threshold = trial / 4;
5710 pcm_config_low_latency.avail_min = trial / 4;
5711 configured_low_latency_capture_period_size = trial;
5712 }
5713 }
5714 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5715 trial = atoi(value);
5716 if (period_size_is_plausible_for_low_latency(trial)) {
5717 configured_low_latency_capture_period_size = trial;
5718 }
5719 }
5720
Vignesh Kulothunganb6f0a9c2018-03-22 13:50:22 -07005721 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
5722
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005723 // commented as full set of app type cfg is sent from platform
5724 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005725 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005726
5727 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5728 af_period_multiplier = atoi(value);
5729 if (af_period_multiplier < 0) {
5730 af_period_multiplier = 2;
5731 } else if (af_period_multiplier > 4) {
5732 af_period_multiplier = 4;
5733 }
5734 ALOGV("new period_multiplier = %d", af_period_multiplier);
5735 }
5736
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005737 audio_extn_tfa_98xx_init(adev);
jasmine cha270b7762018-03-30 15:41:33 +08005738 audio_extn_ma_init(adev->platform);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005739
vivek mehta1a9b7c02015-06-25 11:49:38 -07005740 pthread_mutex_unlock(&adev_init_lock);
5741
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005742 if (adev->adm_init)
5743 adev->adm_data = adev->adm_init();
5744
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005745 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005746 audio_extn_snd_mon_init();
5747 pthread_mutex_lock(&adev->lock);
5748 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
5749 adev->card_status = CARD_STATUS_ONLINE;
5750 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005751 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005752
Eric Laurent2bafff12016-03-17 12:17:23 -07005753 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005754 return 0;
5755}
5756
5757static struct hw_module_methods_t hal_module_methods = {
5758 .open = adev_open,
5759};
5760
5761struct audio_module HAL_MODULE_INFO_SYM = {
5762 .common = {
5763 .tag = HARDWARE_MODULE_TAG,
5764 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5765 .hal_api_version = HARDWARE_HAL_API_VERSION,
5766 .id = AUDIO_HARDWARE_MODULE_ID,
5767 .name = "QCOM Audio HAL",
5768 .author = "Code Aurora Forum",
5769 .methods = &hal_module_methods,
5770 },
5771};