blob: e1d53094bc61871c4b2881cdd5f39f2220d109a0 [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
jiabinad481a72018-07-23 12:03:17 -0700228#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 256
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700229#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
jiabinad481a72018-07-23 12:03:17 -0700242#define AFE_PROXY_RECORD_PERIOD_SIZE 256
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700243#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;
Andy Hung11f10e22018-10-19 17:47:12 -0700618 char mixer_path[MIXER_PATH_MAX_LENGTH];
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);
Andy Hung11f10e22018-10-19 17:47:12 -0700631
632 // we shouldn't truncate mixer_path
633 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
634 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
635 // this also appends to mixer_path
yixuanjiang509f0a72018-09-06 18:37:23 +0800636 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Andy Hung11f10e22018-10-19 17:47:12 -0700637
yixuanjiang509f0a72018-09-06 18:37:23 +0800638 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700639 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700640 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800641
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800642 ALOGV("%s: exit", __func__);
643 return 0;
644}
645
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800646int disable_audio_route(struct audio_device *adev,
647 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800648{
yixuanjiang509f0a72018-09-06 18:37:23 +0800649 snd_device_t snd_device;
Andy Hung11f10e22018-10-19 17:47:12 -0700650 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800651
652 if (usecase == NULL)
653 return -EINVAL;
654
655 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
yixuanjiang509f0a72018-09-06 18:37:23 +0800656 if (usecase->type == PCM_CAPTURE)
657 snd_device = usecase->in_snd_device;
658 else
659 snd_device = usecase->out_snd_device;
Andy Hung11f10e22018-10-19 17:47:12 -0700660
661 // we shouldn't truncate mixer_path
662 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
663 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
664 // this also appends to mixer_path
yixuanjiang509f0a72018-09-06 18:37:23 +0800665 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700666 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Andy Hung11f10e22018-10-19 17:47:12 -0700667
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700668 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000669 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800670
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800671 ALOGV("%s: exit", __func__);
672 return 0;
673}
674
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800675int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700676 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800677{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700678 int i, num_devices = 0;
679 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800680 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800681 if (snd_device < SND_DEVICE_MIN ||
682 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800683 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800684 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800685 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700686
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700687 platform_send_audio_calibration(adev->platform, snd_device);
688
vivek mehtade4849c2016-03-03 17:23:38 -0800689 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700690 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700691 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800692 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700693 }
694
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700695 /* due to the possibility of calibration overwrite between listen
696 and audio, notify sound trigger hal before audio calibration is sent */
697 audio_extn_sound_trigger_update_device_status(snd_device,
698 ST_EVENT_SND_DEVICE_BUSY);
699
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700700 if (audio_extn_spkr_prot_is_enabled())
701 audio_extn_spkr_prot_calib_cancel(adev);
702
zhaoyang yin4211fad2015-06-04 21:13:25 +0800703 audio_extn_dsm_feedback_enable(adev, snd_device, true);
704
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700705 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800706 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
juyuchen1d05ba32018-03-31 16:03:51 +0800707 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700708 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
709 audio_extn_spkr_prot_is_enabled()) {
Aniket Kumar Lata9d6679a2018-04-11 18:13:23 -0700710 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800711 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700712 }
713 if (audio_extn_spkr_prot_start_processing(snd_device)) {
714 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800715 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700716 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700717 } else if (platform_can_split_snd_device(snd_device,
718 &num_devices,
719 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700720 for (i = 0; i < num_devices; i++) {
721 enable_snd_device(adev, new_snd_devices[i]);
722 }
vivek mehtab6506412015-08-07 16:55:17 -0700723 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700724 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800725 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
726 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
727 ALOGE(" %s: Invalid sound device returned", __func__);
728 goto on_error;
729 }
Ed Tam70b5c142016-03-21 19:14:29 -0700730
Eric Laurent2e140aa2016-06-30 17:14:46 -0700731 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Aniket Kumar Lataa158e862018-05-11 17:28:40 -0700732
733 if (is_a2dp_device(snd_device) &&
734 (audio_extn_a2dp_start_playback() < 0)) {
735 ALOGE("%s: failed to configure A2DP control path", __func__);
736 goto on_error;
737 }
738
vivek mehtade4849c2016-03-03 17:23:38 -0800739 audio_route_apply_and_update_path(adev->audio_route, device_name);
740 }
741on_success:
742 adev->snd_dev_ref_cnt[snd_device]++;
743 ret_val = 0;
744on_error:
745 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800746}
747
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800748int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700749 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800750{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700751 int i, num_devices = 0;
752 snd_device_t new_snd_devices[2];
753
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800754 if (snd_device < SND_DEVICE_MIN ||
755 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800756 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800757 return -EINVAL;
758 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700759 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
760 ALOGE("%s: device ref cnt is already 0", __func__);
761 return -EINVAL;
762 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800763 audio_extn_tfa_98xx_disable_speaker(snd_device);
764
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700765 adev->snd_dev_ref_cnt[snd_device]--;
766 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800767 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800768
769 if (is_a2dp_device(snd_device))
770 audio_extn_a2dp_stop_playback();
771
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700772 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800773 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700774 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700775 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
776 audio_extn_spkr_prot_is_enabled()) {
777 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700778
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700779 // FIXME b/65363602: bullhead is the only Nexus with audio_extn_spkr_prot_is_enabled()
780 // and does not use speaker swap. As this code causes a problem with device enable ref
781 // counting we remove it for now.
vivek mehtae59cfb22017-06-16 15:57:11 -0700782 // when speaker device is disabled, reset swap.
783 // will be renabled on usecase start
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700784 // platform_set_swap_channels(adev, false);
vivek mehtae59cfb22017-06-16 15:57:11 -0700785
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700786 } else if (platform_can_split_snd_device(snd_device,
787 &num_devices,
788 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700789 for (i = 0; i < num_devices; i++) {
790 disable_snd_device(adev, new_snd_devices[i]);
791 }
vivek mehtab6506412015-08-07 16:55:17 -0700792 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700793 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800794 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
795 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
796 ALOGE(" %s: Invalid sound device returned", __func__);
797 return -EINVAL;
798 }
799
Eric Laurent2e140aa2016-06-30 17:14:46 -0700800 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800801 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700802 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700803 audio_extn_sound_trigger_update_device_status(snd_device,
804 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700805 }
vivek mehtab6506412015-08-07 16:55:17 -0700806
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800807 return 0;
808}
809
Vignesh Kulothungan64698822018-01-23 11:25:18 -0800810#ifdef DYNAMIC_ECNS_ENABLED
811static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
812 struct stream_in *in,
813 struct audio_effect_config effect_config,
814 unsigned int param_value)
815{
816 char mixer_ctl_name[] = "Audio Effect";
817 long set_values[6];
818
819 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
820 if (!ctl) {
821 ALOGE("%s: Could not get mixer ctl - %s",
822 __func__, mixer_ctl_name);
823 return -EINVAL;
824 }
825
826 set_values[0] = 1; //0:Rx 1:Tx
827 set_values[1] = in->app_type_cfg.app_type;
828 set_values[2] = (long)effect_config.module_id;
829 set_values[3] = (long)effect_config.instance_id;
830 set_values[4] = (long)effect_config.param_id;
831 set_values[5] = param_value;
832
833 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
834
835 return 0;
836
837}
838
839static int update_effect_param_ecns(struct audio_usecase *usecase,
840 unsigned int module_id, int effect_type,
841 unsigned int *param_value)
842{
843 int ret = 0;
844 struct audio_effect_config other_effect_config;
845 struct stream_in *in = NULL;
846
847 if (!usecase)
848 return -EINVAL;
849
850 in = usecase->stream.in;
851
852 /* Get the effect config data of the other effect */
853 ret = platform_get_effect_config_data(usecase->in_snd_device,
854 &other_effect_config,
855 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
856 if (ret < 0) {
857 ALOGE("%s Failed to get effect params %d", __func__, ret);
858 return ret;
859 }
860
861 if (module_id == other_effect_config.module_id) {
862 //Same module id for AEC/NS. Values need to be combined
863 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
864 ((effect_type == EFFECT_NS) && (in->enable_aec)))
865 *param_value |= other_effect_config.param_value;
866 }
867
868 return ret;
869}
870
871static int enable_disable_effect(struct audio_device *adev, struct stream_in *in,
872 int effect_type, bool enable)
873{
874 struct audio_effect_config effect_config;
875 struct audio_usecase *usecase = NULL;
876 int ret = 0;
877 unsigned int param_value = 0;
878
879 if (!in) {
880 ALOGE("%s: Invalid input stream", __func__);
881 return -EINVAL;
882 }
883
884 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
885
886 usecase = get_usecase_from_list(adev, in->usecase);
887
888 ret = platform_get_effect_config_data(usecase->in_snd_device,
889 &effect_config, effect_type);
890 if (ret < 0) {
891 ALOGE("%s Failed to get module id %d", __func__, ret);
892 return ret;
893 }
894 ALOGV("%s: module %d app_type %d usecase->id:%d usecase->in_snd_device:%d",
895 __func__, effect_config.module_id, in->app_type_cfg.app_type,
896 usecase->id, usecase->in_snd_device);
897
898 if (enable)
899 param_value = effect_config.param_value;
900
901 /*Special handling for AEC & NS effects Param values need to be
902 updated if module ids are same*/
903
904 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
905 ret = update_effect_param_ecns(usecase, effect_config.module_id,
906 effect_type, &param_value);
907 if (ret < 0)
908 return ret;
909 }
910
911 ret = send_effect_enable_disable_mixer_ctl(adev, in,
912 effect_config, param_value);
913
914 return ret;
915}
916
917static int check_and_enable_effect(struct audio_device *adev)
918{
919 int ret = 0;
920
921 struct listnode *node;
922 struct stream_in *in = NULL;
923
924 list_for_each(node, &adev->usecase_list)
925 {
926 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
927 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL) {
928 in = usecase->stream.in;
929
930 if (in->standby)
931 continue;
932
933 if (in->enable_aec) {
934 ret = enable_disable_effect(adev, in, EFFECT_AEC, true);
935 }
936
937 if (in->enable_ns &&
938 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
939 ret = enable_disable_effect(adev, in, EFFECT_NS, true);
940 }
941 }
942 }
943
944 return ret;
945}
946#else
947#define enable_disable_effect(w, x, y, z) -ENOSYS
948#define check_and_enable_effect(x) -ENOSYS
949#endif
950
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700951/*
952 legend:
953 uc - existing usecase
954 new_uc - new usecase
955 d1, d11, d2 - SND_DEVICE enums
956 a1, a2 - corresponding ANDROID device enums
957 B, B1, B2 - backend strings
958
959case 1
960 uc->dev d1 (a1) B1
961 new_uc->dev d1 (a1), d2 (a2) B1, B2
962
963 resolution: disable and enable uc->dev on d1
964
965case 2
966 uc->dev d1 (a1) B1
967 new_uc->dev d11 (a1) B1
968
969 resolution: need to switch uc since d1 and d11 are related
970 (e.g. speaker and voice-speaker)
971 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
972
973case 3
974 uc->dev d1 (a1) B1
975 new_uc->dev d2 (a2) B2
976
977 resolution: no need to switch uc
978
979case 4
980 uc->dev d1 (a1) B
981 new_uc->dev d2 (a2) B
982
983 resolution: disable enable uc-dev on d2 since backends match
984 we cannot enable two streams on two different devices if they
985 share the same backend. e.g. if offload is on speaker device using
986 QUAD_MI2S backend and a low-latency stream is started on voice-handset
987 using the same backend, offload must also be switched to voice-handset.
988
989case 5
990 uc->dev d1 (a1) B
991 new_uc->dev d1 (a1), d2 (a2) B
992
993 resolution: disable enable uc-dev on d2 since backends match
994 we cannot enable two streams on two different devices if they
995 share the same backend.
996
997case 6
998 uc->dev d1 a1 B1
999 new_uc->dev d2 a1 B2
1000
1001 resolution: no need to switch
1002
1003case 7
1004
1005 uc->dev d1 (a1), d2 (a2) B1, B2
1006 new_uc->dev d1 B1
1007
1008 resolution: no need to switch
1009
1010*/
1011static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
1012 struct audio_usecase *new_uc,
1013 snd_device_t new_snd_device)
1014{
1015 audio_devices_t a1 = uc->stream.out->devices;
1016 audio_devices_t a2 = new_uc->stream.out->devices;
1017
1018 snd_device_t d1 = uc->out_snd_device;
1019 snd_device_t d2 = new_snd_device;
1020
1021 // Treat as a special case when a1 and a2 are not disjoint
1022 if ((a1 != a2) && (a1 & a2)) {
1023 snd_device_t d3[2];
1024 int num_devices = 0;
1025 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
1026 &num_devices,
1027 d3);
1028 if (ret < 0) {
1029 if (ret != -ENOSYS) {
1030 ALOGW("%s failed to split snd_device %d",
1031 __func__,
1032 popcount(a1) > 1 ? d1 : d2);
1033 }
1034 goto end;
1035 }
1036
1037 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1038 // But if it does happen, we need to give priority to d2 if
1039 // the combo devices active on the existing usecase share a backend.
1040 // This is because we cannot have a usecase active on a combo device
1041 // and a new usecase requests one device in this combo pair.
1042 if (platform_check_backends_match(d3[0], d3[1])) {
1043 return d2; // case 5
1044 } else {
1045 return d1; // case 1
1046 }
1047 } else {
1048 if (platform_check_backends_match(d1, d2)) {
1049 return d2; // case 2, 4
1050 } else {
1051 return d1; // case 6, 3
1052 }
1053 }
1054
1055end:
1056 return d2; // return whatever was calculated before.
1057}
1058
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001059static void check_and_route_playback_usecases(struct audio_device *adev,
1060 struct audio_usecase *uc_info,
1061 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001062{
1063 struct listnode *node;
1064 struct audio_usecase *usecase;
1065 bool switch_device[AUDIO_USECASE_MAX];
1066 int i, num_uc_to_switch = 0;
1067
Haynes Mathew George137a2ee2017-05-23 17:03:35 -07001068 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
1069 uc_info,
1070 snd_device);
David Linee3fe402017-03-13 10:00:42 -07001071
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001072 /* For a2dp device reconfigure all active sessions
1073 * with new AFE encoder format based on a2dp state
1074 */
1075 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Aniket Kumar Lata9723a962018-05-16 17:41:55 -07001076 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1077 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001078 audio_extn_a2dp_is_force_device_switch()) {
1079 force_routing = true;
1080 }
1081
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001082 /*
1083 * This function is to make sure that all the usecases that are active on
1084 * the hardware codec backend are always routed to any one device that is
1085 * handled by the hardware codec.
1086 * For example, if low-latency and deep-buffer usecases are currently active
1087 * on speaker and out_set_parameters(headset) is received on low-latency
1088 * output, then we have to make sure deep-buffer is also switched to headset,
1089 * because of the limitation that both the devices cannot be enabled
1090 * at the same time as they share the same backend.
1091 */
1092 /* Disable all the usecases on the shared backend other than the
1093 specified usecase */
1094 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1095 switch_device[i] = false;
1096
1097 list_for_each(node, &adev->usecase_list) {
1098 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -07001099 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
1100 continue;
1101
1102 if (force_routing ||
1103 (usecase->out_snd_device != snd_device &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -07001104 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
1105 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -07001106 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001107 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1108 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -07001109 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001110 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001111 switch_device[usecase->id] = true;
1112 num_uc_to_switch++;
1113 }
1114 }
1115
1116 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001117 list_for_each(node, &adev->usecase_list) {
1118 usecase = node_to_item(node, struct audio_usecase, list);
1119 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001120 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +09001121 }
1122 }
1123
Haynes Mathew George2d809e02016-09-22 17:38:16 -07001124 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +09001125 list_for_each(node, &adev->usecase_list) {
1126 usecase = node_to_item(node, struct audio_usecase, list);
1127 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -07001128 d_device = derive_playback_snd_device(usecase, uc_info,
1129 snd_device);
1130 enable_snd_device(adev, d_device);
1131 /* Update the out_snd_device before enabling the audio route */
1132 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001133 }
1134 }
1135
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001136 /* Re-route all the usecases on the shared backend other than the
1137 specified usecase to new snd devices */
1138 list_for_each(node, &adev->usecase_list) {
1139 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001140 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001141 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001142 }
1143 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001144 }
1145}
1146
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001147static void check_and_route_capture_usecases(struct audio_device *adev,
1148 struct audio_usecase *uc_info,
1149 snd_device_t snd_device)
1150{
1151 struct listnode *node;
1152 struct audio_usecase *usecase;
1153 bool switch_device[AUDIO_USECASE_MAX];
1154 int i, num_uc_to_switch = 0;
1155
vivek mehta4ed66e62016-04-15 23:33:34 -07001156 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
1157
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001158 /*
1159 * This function is to make sure that all the active capture usecases
1160 * are always routed to the same input sound device.
1161 * For example, if audio-record and voice-call usecases are currently
1162 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1163 * is received for voice call then we have to make sure that audio-record
1164 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1165 * because of the limitation that two devices cannot be enabled
1166 * at the same time if they share the same backend.
1167 */
1168 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1169 switch_device[i] = false;
1170
1171 list_for_each(node, &adev->usecase_list) {
1172 usecase = node_to_item(node, struct audio_usecase, list);
1173 if (usecase->type != PCM_PLAYBACK &&
1174 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -07001175 usecase->in_snd_device != snd_device &&
1176 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001177 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1178 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001179 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001180 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001181 switch_device[usecase->id] = true;
1182 num_uc_to_switch++;
1183 }
1184 }
1185
1186 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001187 list_for_each(node, &adev->usecase_list) {
1188 usecase = node_to_item(node, struct audio_usecase, list);
1189 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001190 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001191 }
1192 }
1193
1194 list_for_each(node, &adev->usecase_list) {
1195 usecase = node_to_item(node, struct audio_usecase, list);
1196 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001197 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001198 }
1199 }
1200
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001201 /* Re-route all the usecases on the shared backend other than the
1202 specified usecase to new snd devices */
1203 list_for_each(node, &adev->usecase_list) {
1204 usecase = node_to_item(node, struct audio_usecase, list);
1205 /* Update the in_snd_device only before enabling the audio route */
1206 if (switch_device[usecase->id] ) {
1207 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001208 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001209 }
1210 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001211 }
1212}
1213
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001214/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001215static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001216{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001217 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001218 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001219
1220 switch (channels) {
1221 /*
1222 * Do not handle stereo output in Multi-channel cases
1223 * Stereo case is handled in normal playback path
1224 */
1225 case 6:
1226 ALOGV("%s: HDMI supports 5.1", __func__);
1227 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1228 break;
1229 case 8:
1230 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
1231 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1232 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
1233 break;
1234 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001235 ALOGE("HDMI does not support multi channel playback");
1236 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001237 break;
1238 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001239 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001240}
1241
Andy Hung18859412017-08-09 11:47:21 -07001242static ssize_t read_usb_sup_sample_rates(bool is_playback,
1243 uint32_t *supported_sample_rates,
1244 uint32_t max_rates)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001245{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001246 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1247 supported_sample_rates,
1248 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001249#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001250 for (ssize_t i=0; i<count; i++) {
1251 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1252 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001253 }
1254#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001255 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001256}
1257
Haynes Mathew George569b7482017-05-08 14:44:27 -07001258static int read_usb_sup_channel_masks(bool is_playback,
1259 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001260 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001261{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001262 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001263 int channel_count;
1264 uint32_t num_masks = 0;
1265 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1266 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001267 }
Eric Laurent74b55762017-07-09 17:04:53 -07001268 if (is_playback) {
Andy Hung6c1afb12017-12-22 11:34:41 -08001269 // start from 2 channels as framework currently doesn't support mono.
1270 // TODO: consider only supporting channel index masks beyond stereo here.
1271 for (channel_count = FCC_2;
1272 channel_count <= channels && num_masks < max_masks;
1273 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001274 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1275 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001276 for (channel_count = FCC_2;
1277 channel_count <= channels && num_masks < max_masks;
1278 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001279 supported_channel_masks[num_masks++] =
1280 audio_channel_mask_for_index_assignment_from_count(channel_count);
1281 }
1282 } else {
1283 // For capture we report all supported channel masks from 1 channel up.
1284 channel_count = MIN_CHANNEL_COUNT;
1285 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1286 // indexed mask
1287 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
Andy Hung88ce1d92018-10-29 18:31:12 -07001288 const audio_channel_mask_t mask =
Eric Laurent74b55762017-07-09 17:04:53 -07001289 audio_channel_in_mask_from_count(channel_count);
Andy Hung88ce1d92018-10-29 18:31:12 -07001290 supported_channel_masks[num_masks++] = mask;
1291 const audio_channel_mask_t index_mask =
1292 audio_channel_mask_for_index_assignment_from_count(channel_count);
1293 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
1294 supported_channel_masks[num_masks++] = index_mask;
1295 }
Eric Laurent74b55762017-07-09 17:04:53 -07001296 }
1297 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001298#ifdef NDEBUG
1299 for (size_t i = 0; i < num_masks; ++i) {
1300 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1301 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
1302 }
1303#endif
Eric Laurent74b55762017-07-09 17:04:53 -07001304 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001305}
1306
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001307static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001308 audio_format_t *supported_formats,
1309 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001310{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001311 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001312 switch (bitwidth) {
1313 case 24:
1314 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001315 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001316 break;
1317 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001318 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001319 break;
1320 case 16:
1321 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001322 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001323 break;
1324 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001325 ALOGV("%s: %s supported format %d", __func__,
1326 is_playback ? "P" : "C", bitwidth);
1327 return 1;
1328}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001329
Haynes Mathew George569b7482017-05-08 14:44:27 -07001330static int read_usb_sup_params_and_compare(bool is_playback,
1331 audio_format_t *format,
1332 audio_format_t *supported_formats,
1333 uint32_t max_formats,
1334 audio_channel_mask_t *mask,
1335 audio_channel_mask_t *supported_channel_masks,
1336 uint32_t max_masks,
1337 uint32_t *rate,
1338 uint32_t *supported_sample_rates,
1339 uint32_t max_rates) {
1340 int ret = 0;
1341 int num_formats;
1342 int num_masks;
1343 int num_rates;
1344 int i;
1345
1346 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1347 max_formats);
1348 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1349 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001350
Haynes Mathew George569b7482017-05-08 14:44:27 -07001351 num_rates = read_usb_sup_sample_rates(is_playback,
1352 supported_sample_rates, max_rates);
1353
1354#define LUT(table, len, what, dflt) \
1355 for (i=0; i<len && (table[i] != what); i++); \
1356 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1357
1358 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1359 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1360 LUT(supported_sample_rates, num_rates, *rate, 0);
1361
1362#undef LUT
1363 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001364}
1365
Andy Hungd9653bd2017-08-01 19:31:39 -07001366static bool is_usb_ready(struct audio_device *adev, bool is_playback)
1367{
1368 // Check if usb is ready.
1369 // The usb device may have been removed quickly after insertion and hence
1370 // no longer available. This will show up as empty channel masks, or rates.
1371
1372 pthread_mutex_lock(&adev->lock);
1373 uint32_t supported_sample_rate;
1374
1375 // we consider usb ready if we can fetch at least one sample rate.
1376 const bool ready = read_usb_sup_sample_rates(
1377 is_playback, &supported_sample_rate, 1 /* max_rates */) > 0;
1378 pthread_mutex_unlock(&adev->lock);
1379 return ready;
1380}
1381
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001382static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1383{
1384 struct audio_usecase *usecase;
1385 struct listnode *node;
1386
1387 list_for_each(node, &adev->usecase_list) {
1388 usecase = node_to_item(node, struct audio_usecase, list);
1389 if (usecase->type == VOICE_CALL) {
1390 ALOGV("%s: usecase id %d", __func__, usecase->id);
1391 return usecase->id;
1392 }
1393 }
1394 return USECASE_INVALID;
1395}
1396
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001397struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1398 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001399{
1400 struct audio_usecase *usecase;
1401 struct listnode *node;
1402
1403 list_for_each(node, &adev->usecase_list) {
1404 usecase = node_to_item(node, struct audio_usecase, list);
1405 if (usecase->id == uc_id)
1406 return usecase;
1407 }
1408 return NULL;
1409}
1410
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001411static bool force_device_switch(struct audio_usecase *usecase)
1412{
1413 if (usecase->stream.out == NULL) {
1414 ALOGE("%s: stream.out is NULL", __func__);
1415 return false;
1416 }
1417
1418 // Force all A2DP output devices to reconfigure for proper AFE encode format
1419 // Also handle a case where in earlier A2DP start failed as A2DP stream was
1420 // in suspended state, hence try to trigger a retry when we again get a routing request.
1421 if ((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
1422 audio_extn_a2dp_is_force_device_switch()) {
1423 ALOGD("%s: Force A2DP device switch to update new encoder config", __func__);
1424 return true;
1425 }
1426
1427 return false;
1428}
1429
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001430struct stream_in *adev_get_active_input(const struct audio_device *adev)
1431{
1432 struct listnode *node;
1433 struct stream_in *last_active_in = NULL;
1434
1435 /* Get last added active input.
1436 * TODO: We may use a priority mechanism to pick highest priority active source */
1437 list_for_each(node, &adev->usecase_list)
1438 {
1439 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
1440 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL) {
1441 last_active_in = usecase->stream.in;
1442 }
1443 }
1444
1445 return last_active_in;
1446}
1447
1448struct stream_in *get_voice_communication_input(const struct audio_device *adev)
1449{
1450 struct listnode *node;
1451
1452 /* First check active inputs with voice communication source and then
1453 * any input if audio mode is in communication */
1454 list_for_each(node, &adev->usecase_list)
1455 {
1456 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
1457 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
1458 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1459 return usecase->stream.in;
1460 }
1461 }
1462 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
1463 return adev_get_active_input(adev);
1464 }
1465 return NULL;
1466}
1467
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001468int select_devices(struct audio_device *adev,
1469 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001470{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001471 snd_device_t out_snd_device = SND_DEVICE_NONE;
1472 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001473 struct audio_usecase *usecase = NULL;
1474 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001475 struct audio_usecase *hfp_usecase = NULL;
1476 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001477 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001478 int status = 0;
Eric Laurentf4520b02017-09-20 18:31:58 -07001479 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1480 USECASE_AUDIO_PLAYBACK_VOIP);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001481
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001482 usecase = get_usecase_from_list(adev, uc_id);
1483 if (usecase == NULL) {
1484 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1485 return -EINVAL;
1486 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001487
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001488 if ((usecase->type == VOICE_CALL) ||
1489 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001490 out_snd_device = platform_get_output_snd_device(adev->platform,
1491 usecase->stream.out->devices);
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001492 in_snd_device = platform_get_input_snd_device(adev->platform,
1493 NULL,
1494 usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001495 usecase->devices = usecase->stream.out->devices;
1496 } else {
1497 /*
1498 * If the voice call is active, use the sound devices of voice call usecase
1499 * so that it would not result any device switch. All the usecases will
1500 * be switched to new device when select_devices() is called for voice call
1501 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001502 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001503 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001504 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001505 vc_usecase = get_usecase_from_list(adev,
1506 get_voice_usecase_id_from_list(adev));
1507 if ((vc_usecase != NULL) &&
1508 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1509 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001510 in_snd_device = vc_usecase->in_snd_device;
1511 out_snd_device = vc_usecase->out_snd_device;
1512 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001513 } else if (audio_extn_hfp_is_active(adev)) {
1514 hfp_ucid = audio_extn_hfp_get_usecase();
1515 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1516 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1517 in_snd_device = hfp_usecase->in_snd_device;
1518 out_snd_device = hfp_usecase->out_snd_device;
1519 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001520 }
1521 if (usecase->type == PCM_PLAYBACK) {
1522 usecase->devices = usecase->stream.out->devices;
1523 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001524 if (out_snd_device == SND_DEVICE_NONE) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001525 struct stream_out *voip_out = adev->primary_output;
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001526 struct stream_in *voip_in = get_voice_communication_input(adev);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001527
Eric Laurentb23d5282013-05-14 15:27:20 -07001528 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001529 usecase->stream.out->devices);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001530
1531 if (voip_usecase)
1532 voip_out = voip_usecase->stream.out;
1533
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001534 if (usecase->stream.out == voip_out && voip_in != NULL) {
1535 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001536 }
1537 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001538 } else if (usecase->type == PCM_CAPTURE) {
1539 usecase->devices = usecase->stream.in->device;
1540 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001541 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001542 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001543 struct stream_in *voip_in = get_voice_communication_input(adev);
1544
1545 if (voip_in != NULL) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001546
1547 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1548 USECASE_AUDIO_PLAYBACK_VOIP);
1549
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001550 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001551 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1552 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001553 } else if (voip_usecase) {
1554 out_device = voip_usecase->stream.out->devices;
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001555 } else if (adev->primary_output) {
1556 out_device = adev->primary_output->devices;
1557 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001558 }
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001559 in_snd_device = platform_get_input_snd_device(adev->platform,
1560 usecase->stream.in,
1561 out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001562 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001563 }
1564 }
1565
1566 if (out_snd_device == usecase->out_snd_device &&
1567 in_snd_device == usecase->in_snd_device) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001568 if (!force_device_switch(usecase))
1569 return 0;
1570 }
1571
1572 if (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready()) {
1573 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1574 return 0;
1575 }
1576
Aniket Kumar Lata9723a962018-05-16 17:41:55 -07001577 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
1578 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001579 (!audio_extn_a2dp_is_ready())) {
1580 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
juyuchen9baad392018-06-05 19:02:10 +08001581 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
1582 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
1583 else
1584 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001585 }
1586
juyuchen66c4ecf2018-08-06 15:39:34 +08001587 if (usecase->id == USECASE_INCALL_MUSIC_UPLINK) {
1588 out_snd_device = SND_DEVICE_OUT_VOICE_MUSIC_TX;
1589 }
1590
Eric Laurent2bafff12016-03-17 12:17:23 -07001591 if (out_snd_device != SND_DEVICE_NONE &&
1592 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1593 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1594 __func__,
1595 use_case_table[uc_id],
1596 adev->last_logged_snd_device[uc_id][0],
1597 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1598 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1599 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1600 -1,
1601 out_snd_device,
1602 platform_get_snd_device_name(out_snd_device),
1603 platform_get_snd_device_acdb_id(out_snd_device));
1604 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1605 }
1606 if (in_snd_device != SND_DEVICE_NONE &&
1607 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1608 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1609 __func__,
1610 use_case_table[uc_id],
1611 adev->last_logged_snd_device[uc_id][1],
1612 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1613 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1614 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1615 -1,
1616 in_snd_device,
1617 platform_get_snd_device_name(in_snd_device),
1618 platform_get_snd_device_acdb_id(in_snd_device));
1619 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1620 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001621
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001622 /*
1623 * Limitation: While in call, to do a device switch we need to disable
1624 * and enable both RX and TX devices though one of them is same as current
1625 * device.
1626 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001627 if ((usecase->type == VOICE_CALL) &&
1628 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1629 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001630 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001631 /* Disable sidetone only if voice call already exists */
1632 if (voice_is_call_state_active(adev))
1633 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001634 }
1635
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001636 /* Disable current sound devices */
1637 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001638 disable_audio_route(adev, usecase);
1639 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001640 }
1641
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001642 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001643 disable_audio_route(adev, usecase);
1644 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001645 }
1646
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001647 /* Applicable only on the targets that has external modem.
1648 * New device information should be sent to modem before enabling
1649 * the devices to reduce in-call device switch time.
1650 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001651 if ((usecase->type == VOICE_CALL) &&
1652 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1653 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001654 status = platform_switch_voice_call_enable_device_config(adev->platform,
1655 out_snd_device,
1656 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001657 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001658
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001659 /* Enable new sound devices */
1660 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001661 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001662 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) ||
1663 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001664 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001665 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001666 }
1667
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001668 if (in_snd_device != SND_DEVICE_NONE) {
1669 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001670 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001671 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001672
Eric Laurentb23d5282013-05-14 15:27:20 -07001673 if (usecase->type == VOICE_CALL)
1674 status = platform_switch_voice_call_device_post(adev->platform,
1675 out_snd_device,
1676 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001677
sangwoo170731f2013-06-08 15:36:36 +09001678 usecase->in_snd_device = in_snd_device;
1679 usecase->out_snd_device = out_snd_device;
1680
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001681 audio_extn_tfa_98xx_set_mode();
1682
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001683 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001684
Jasmine Cha70771b62018-05-15 15:02:43 +08001685 audio_extn_ma_set_device(usecase);
jasmine cha270b7762018-03-30 15:41:33 +08001686
Vignesh Kulothungan64698822018-01-23 11:25:18 -08001687 /* If input stream is already running the effect needs to be
1688 applied on the new input device that's being enabled here. */
1689 if (in_snd_device != SND_DEVICE_NONE)
1690 check_and_enable_effect(adev);
1691
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001692 /* Applicable only on the targets that has external modem.
1693 * Enable device command should be sent to modem only after
1694 * enabling voice call mixer controls
1695 */
vivek mehta765eb642015-08-07 19:46:06 -07001696 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001697 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1698 out_snd_device,
1699 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001700 /* Enable sidetone only if voice call already exists */
1701 if (voice_is_call_state_active(adev))
1702 voice_set_sidetone(adev, out_snd_device, true);
1703 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001704
Yung Ti Sue9d64f92018-06-22 17:38:47 +08001705 if (usecase->type != PCM_CAPTURE && voip_usecase) {
Eric Laurentf4520b02017-09-20 18:31:58 -07001706 struct stream_out *voip_out = voip_usecase->stream.out;
1707 audio_extn_utils_send_app_type_gain(adev,
1708 voip_out->app_type_cfg.app_type,
1709 &voip_out->app_type_cfg.gain[0]);
1710 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001711 return status;
1712}
1713
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001714static int stop_input_stream(struct stream_in *in)
1715{
1716 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001717 struct audio_usecase *uc_info;
1718 struct audio_device *adev = in->dev;
1719
Eric Laurent994a6932013-07-17 11:51:42 -07001720 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001721 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001722
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001723 uc_info = get_usecase_from_list(adev, in->usecase);
1724 if (uc_info == NULL) {
1725 ALOGE("%s: Could not find the usecase (%d) in the list",
1726 __func__, in->usecase);
1727 return -EINVAL;
1728 }
1729
vivek mehta781065c2017-04-04 12:55:01 -07001730 /* Close in-call recording streams */
1731 voice_check_and_stop_incall_rec_usecase(adev, in);
1732
Eric Laurent150dbfe2013-02-27 14:31:02 -08001733 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001734 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001735
1736 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001737 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001738
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001739 list_remove(&uc_info->list);
1740 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001741
Eric Laurent994a6932013-07-17 11:51:42 -07001742 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001743 return ret;
1744}
1745
1746int start_input_stream(struct stream_in *in)
1747{
1748 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001749 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001750 struct audio_usecase *uc_info;
1751 struct audio_device *adev = in->dev;
1752
Eric Laurent994a6932013-07-17 11:51:42 -07001753 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001754
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001755 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1756 return -EIO;
1757
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001758 if (in->card_status == CARD_STATUS_OFFLINE ||
1759 adev->card_status == CARD_STATUS_OFFLINE) {
1760 ALOGW("in->card_status or adev->card_status offline, try again");
1761 ret = -EAGAIN;
1762 goto error_config;
1763 }
1764
vivek mehta781065c2017-04-04 12:55:01 -07001765 /* Check if source matches incall recording usecase criteria */
1766 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1767 if (ret)
1768 goto error_config;
1769 else
1770 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1771
Eric Laurentb23d5282013-05-14 15:27:20 -07001772 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001773 if (in->pcm_device_id < 0) {
1774 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1775 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001776 ret = -EINVAL;
1777 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001778 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001779
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001780 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1781 uc_info->id = in->usecase;
1782 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001783 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001784 uc_info->devices = in->device;
1785 uc_info->in_snd_device = SND_DEVICE_NONE;
1786 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001787
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001788 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001789
Wei Wangf4837d52017-11-21 14:51:20 -08001790 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001791 audio_extn_perf_lock_acquire();
1792
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001793 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001794
Eric Laurent0e46adf2016-12-16 12:49:24 -08001795 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001796 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001797 ALOGE("%s: pcm stream not ready", __func__);
1798 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001799 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001800 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001801 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001802 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1803 goto error_open;
1804 }
1805 } else {
1806 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1807 unsigned int pcm_open_retry_count = 0;
1808
1809 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1810 flags |= PCM_MMAP | PCM_NOIRQ;
1811 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1812 } else if (in->realtime) {
1813 flags |= PCM_MMAP | PCM_NOIRQ;
1814 }
1815
1816 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1817 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1818
1819 while (1) {
1820 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1821 flags, &in->config);
1822 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1823 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1824 if (in->pcm != NULL) {
1825 pcm_close(in->pcm);
1826 in->pcm = NULL;
1827 }
1828 if (pcm_open_retry_count-- == 0) {
1829 ret = -EIO;
1830 goto error_open;
1831 }
1832 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1833 continue;
1834 }
1835 break;
1836 }
1837
1838 ALOGV("%s: pcm_prepare", __func__);
1839 ret = pcm_prepare(in->pcm);
1840 if (ret < 0) {
1841 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001842 pcm_close(in->pcm);
1843 in->pcm = NULL;
1844 goto error_open;
1845 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001846 if (in->realtime) {
1847 ret = pcm_start(in->pcm);
1848 if (ret < 0) {
1849 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1850 pcm_close(in->pcm);
1851 in->pcm = NULL;
1852 goto error_open;
1853 }
1854 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001855 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001856 register_in_stream(in);
Vignesh Kulothungan64698822018-01-23 11:25:18 -08001857 check_and_enable_effect(adev);
Wei Wangf4837d52017-11-21 14:51:20 -08001858 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001859 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001860 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001861
Eric Laurent0e46adf2016-12-16 12:49:24 -08001862 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001863
1864error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001865 stop_input_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001866 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001867 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001868
1869error_config:
Eric Laurent2bafff12016-03-17 12:17:23 -07001870 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001871 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001872}
1873
Eric Laurenta1478072015-09-21 17:21:52 -07001874void lock_input_stream(struct stream_in *in)
1875{
1876 pthread_mutex_lock(&in->pre_lock);
1877 pthread_mutex_lock(&in->lock);
1878 pthread_mutex_unlock(&in->pre_lock);
1879}
1880
1881void lock_output_stream(struct stream_out *out)
1882{
1883 pthread_mutex_lock(&out->pre_lock);
1884 pthread_mutex_lock(&out->lock);
1885 pthread_mutex_unlock(&out->pre_lock);
1886}
1887
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001888/* must be called with out->lock locked */
1889static int send_offload_cmd_l(struct stream_out* out, int command)
1890{
1891 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1892
1893 ALOGVV("%s %d", __func__, command);
1894
1895 cmd->cmd = command;
1896 list_add_tail(&out->offload_cmd_list, &cmd->node);
1897 pthread_cond_signal(&out->offload_cond);
1898 return 0;
1899}
1900
1901/* must be called iwth out->lock locked */
1902static void stop_compressed_output_l(struct stream_out *out)
1903{
1904 out->offload_state = OFFLOAD_STATE_IDLE;
1905 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001906 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001907 if (out->compr != NULL) {
1908 compress_stop(out->compr);
1909 while (out->offload_thread_blocked) {
1910 pthread_cond_wait(&out->cond, &out->lock);
1911 }
1912 }
1913}
1914
1915static void *offload_thread_loop(void *context)
1916{
1917 struct stream_out *out = (struct stream_out *) context;
1918 struct listnode *item;
1919
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001920 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1921 set_sched_policy(0, SP_FOREGROUND);
1922 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1923
1924 ALOGV("%s", __func__);
juyuchenb0f5bfd2018-12-12 17:58:09 +08001925
Eric Laurenta1478072015-09-21 17:21:52 -07001926 lock_output_stream(out);
juyuchenb0f5bfd2018-12-12 17:58:09 +08001927 out->offload_state = OFFLOAD_STATE_IDLE;
1928 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001929 for (;;) {
1930 struct offload_cmd *cmd = NULL;
1931 stream_callback_event_t event;
1932 bool send_callback = false;
1933
1934 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1935 __func__, list_empty(&out->offload_cmd_list),
1936 out->offload_state);
1937 if (list_empty(&out->offload_cmd_list)) {
1938 ALOGV("%s SLEEPING", __func__);
1939 pthread_cond_wait(&out->offload_cond, &out->lock);
1940 ALOGV("%s RUNNING", __func__);
1941 continue;
1942 }
1943
1944 item = list_head(&out->offload_cmd_list);
1945 cmd = node_to_item(item, struct offload_cmd, node);
1946 list_remove(item);
1947
1948 ALOGVV("%s STATE %d CMD %d out->compr %p",
1949 __func__, out->offload_state, cmd->cmd, out->compr);
1950
1951 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1952 free(cmd);
1953 break;
1954 }
1955
1956 if (out->compr == NULL) {
1957 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001958 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001959 pthread_cond_signal(&out->cond);
1960 continue;
1961 }
1962 out->offload_thread_blocked = true;
1963 pthread_mutex_unlock(&out->lock);
1964 send_callback = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001965 switch (cmd->cmd) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001966 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1967 compress_wait(out->compr, -1);
1968 send_callback = true;
1969 event = STREAM_CBK_EVENT_WRITE_READY;
1970 break;
1971 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001972 compress_next_track(out->compr);
1973 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001974 send_callback = true;
1975 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001976 /* Resend the metadata for next iteration */
1977 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001978 break;
1979 case OFFLOAD_CMD_DRAIN:
1980 compress_drain(out->compr);
1981 send_callback = true;
1982 event = STREAM_CBK_EVENT_DRAIN_READY;
1983 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001984 case OFFLOAD_CMD_ERROR:
1985 send_callback = true;
1986 event = STREAM_CBK_EVENT_ERROR;
1987 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001988 default:
1989 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1990 break;
1991 }
Eric Laurenta1478072015-09-21 17:21:52 -07001992 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001993 out->offload_thread_blocked = false;
1994 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001995 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001996 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001997 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001998 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001999 free(cmd);
2000 }
2001
2002 pthread_cond_signal(&out->cond);
2003 while (!list_empty(&out->offload_cmd_list)) {
2004 item = list_head(&out->offload_cmd_list);
2005 list_remove(item);
2006 free(node_to_item(item, struct offload_cmd, node));
2007 }
2008 pthread_mutex_unlock(&out->lock);
2009
2010 return NULL;
2011}
2012
2013static int create_offload_callback_thread(struct stream_out *out)
2014{
2015 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2016 list_init(&out->offload_cmd_list);
2017 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2018 offload_thread_loop, out);
2019 return 0;
2020}
2021
2022static int destroy_offload_callback_thread(struct stream_out *out)
2023{
Eric Laurenta1478072015-09-21 17:21:52 -07002024 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002025 stop_compressed_output_l(out);
2026 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2027
2028 pthread_mutex_unlock(&out->lock);
2029 pthread_join(out->offload_thread, (void **) NULL);
2030 pthread_cond_destroy(&out->offload_cond);
2031
2032 return 0;
2033}
2034
Eric Laurent07eeafd2013-10-06 12:52:49 -07002035static bool allow_hdmi_channel_config(struct audio_device *adev)
2036{
2037 struct listnode *node;
2038 struct audio_usecase *usecase;
2039 bool ret = true;
2040
2041 list_for_each(node, &adev->usecase_list) {
2042 usecase = node_to_item(node, struct audio_usecase, list);
2043 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2044 /*
2045 * If voice call is already existing, do not proceed further to avoid
2046 * disabling/enabling both RX and TX devices, CSD calls, etc.
2047 * Once the voice call done, the HDMI channels can be configured to
2048 * max channels of remaining use cases.
2049 */
2050 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08002051 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07002052 __func__);
2053 ret = false;
2054 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002055 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
2056 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07002057 "no change in HDMI channels", __func__);
2058 ret = false;
2059 break;
2060 }
2061 }
2062 }
2063 return ret;
2064}
2065
2066static int check_and_set_hdmi_channels(struct audio_device *adev,
2067 unsigned int channels)
2068{
2069 struct listnode *node;
2070 struct audio_usecase *usecase;
2071
2072 /* Check if change in HDMI channel config is allowed */
2073 if (!allow_hdmi_channel_config(adev))
2074 return 0;
2075
2076 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08002077 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002078 return 0;
2079 }
2080
2081 platform_set_hdmi_channels(adev->platform, channels);
2082 adev->cur_hdmi_channels = channels;
2083
2084 /*
2085 * Deroute all the playback streams routed to HDMI so that
2086 * the back end is deactivated. Note that backend will not
2087 * be deactivated if any one stream is connected to it.
2088 */
2089 list_for_each(node, &adev->usecase_list) {
2090 usecase = node_to_item(node, struct audio_usecase, list);
2091 if (usecase->type == PCM_PLAYBACK &&
2092 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002093 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002094 }
2095 }
2096
2097 /*
2098 * Enable all the streams disabled above. Now the HDMI backend
2099 * will be activated with new channel configuration
2100 */
2101 list_for_each(node, &adev->usecase_list) {
2102 usecase = node_to_item(node, struct audio_usecase, list);
2103 if (usecase->type == PCM_PLAYBACK &&
2104 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002105 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002106 }
2107 }
2108
2109 return 0;
2110}
2111
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002112static int check_and_set_usb_service_interval(struct audio_device *adev,
2113 struct audio_usecase *uc_info,
2114 bool min)
2115{
2116 struct listnode *node;
2117 struct audio_usecase *usecase;
2118 bool switch_usecases = false;
2119 bool reconfig = false;
2120
2121 if ((uc_info->id != USECASE_AUDIO_PLAYBACK_MMAP) &&
2122 (uc_info->id != USECASE_AUDIO_PLAYBACK_ULL))
2123 return -1;
2124
2125 /* set if the valid usecase do not already exist */
2126 list_for_each(node, &adev->usecase_list) {
2127 usecase = node_to_item(node, struct audio_usecase, list);
2128 if (usecase->type == PCM_PLAYBACK &&
2129 (audio_is_usb_out_device(usecase->devices & AUDIO_DEVICE_OUT_ALL_USB))) {
2130 switch (usecase->id) {
2131 case USECASE_AUDIO_PLAYBACK_MMAP:
2132 case USECASE_AUDIO_PLAYBACK_ULL:
2133 // cannot reconfig while mmap/ull is present.
2134 return -1;
2135 default:
2136 switch_usecases = true;
2137 break;
2138 }
2139 }
2140 if (switch_usecases)
2141 break;
2142 }
2143 /*
2144 * client can try to set service interval in start_output_stream
2145 * to min or to 0 (i.e reset) in stop_output_stream .
2146 */
2147 unsigned long service_interval =
2148 audio_extn_usb_find_service_interval(min, true /*playback*/);
2149 int ret = platform_set_usb_service_interval(adev->platform,
2150 true /*playback*/,
2151 service_interval,
2152 &reconfig);
2153 /* no change or not supported or no active usecases */
2154 if (ret || !reconfig || !switch_usecases)
2155 return -1;
2156 return 0;
2157#undef VALID_USECASE
2158}
2159
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002160static int stop_output_stream(struct stream_out *out)
2161{
2162 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002163 struct audio_usecase *uc_info;
2164 struct audio_device *adev = out->dev;
HW Lee88512e92018-06-12 15:26:09 +08002165 bool has_voip_usecase =
2166 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002167
Eric Laurent994a6932013-07-17 11:51:42 -07002168 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002169 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002170 uc_info = get_usecase_from_list(adev, out->usecase);
2171 if (uc_info == NULL) {
2172 ALOGE("%s: Could not find the usecase (%d) in the list",
2173 __func__, out->usecase);
2174 return -EINVAL;
2175 }
2176
Haynes Mathew George41f86652014-06-17 14:22:15 -07002177 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2178 if (adev->visualizer_stop_output != NULL)
2179 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
2180 if (adev->offload_effects_stop_output != NULL)
2181 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002182 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2183 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2184 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07002185 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002186
Arun Mirpuri0cc2f312018-05-29 17:26:07 -07002187 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
2188 voice_set_device_mute_flag(adev, false);
2189
Eric Laurent150dbfe2013-02-27 14:31:02 -08002190 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002191 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002192
2193 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002194 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002195
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002196 list_remove(&uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002197
Eric Laurent0499d4f2014-08-25 22:39:29 -05002198 audio_extn_extspk_update(adev->extspk);
2199
Eric Laurent07eeafd2013-10-06 12:52:49 -07002200 /* Must be called after removing the usecase from list */
2201 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2202 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
HW Lee88512e92018-06-12 15:26:09 +08002203 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002204 ret = check_and_set_usb_service_interval(adev, uc_info, false /*min*/);
2205 if (ret == 0) {
2206 /* default service interval was successfully updated,
2207 reopen USB backend with new service interval */
2208 check_and_route_playback_usecases(adev, uc_info, uc_info->out_snd_device);
2209 }
2210 ret = 0;
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07002211 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002212
HW Lee88512e92018-06-12 15:26:09 +08002213 if (has_voip_usecase ||
2214 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
2215 struct listnode *node;
2216 struct audio_usecase *usecase;
2217 list_for_each(node, &adev->usecase_list) {
2218 usecase = node_to_item(node, struct audio_usecase, list);
2219 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
2220 continue;
2221
2222 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
2223 __func__, usecase->id, use_case_table[usecase->id],
2224 out->usecase, use_case_table[out->usecase]);
2225 select_devices(adev, usecase->id);
2226 }
2227 }
2228
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002229 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07002230 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002231 return ret;
2232}
2233
2234int start_output_stream(struct stream_out *out)
2235{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002236 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002237 struct audio_usecase *uc_info;
2238 struct audio_device *adev = out->dev;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002239 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002240
Eric Laurent994a6932013-07-17 11:51:42 -07002241 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002242 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002243
2244 if (out->card_status == CARD_STATUS_OFFLINE ||
2245 adev->card_status == CARD_STATUS_OFFLINE) {
2246 ALOGW("out->card_status or adev->card_status offline, try again");
2247 ret = -EAGAIN;
2248 goto error_config;
2249 }
2250
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002251 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2252 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002253 if (out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002254 a2dp_combo = true;
2255 } else {
2256 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2257 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2258 ret = -EAGAIN;
2259 goto error_config;
2260 }
2261 }
2262 }
2263 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002264 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002265 if (out->pcm_device_id < 0) {
2266 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2267 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002268 ret = -EINVAL;
2269 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002270 }
2271
2272 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
2273 uc_info->id = out->usecase;
2274 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002275 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002276 uc_info->devices = out->devices;
2277 uc_info->in_snd_device = SND_DEVICE_NONE;
2278 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002279
Eric Laurent07eeafd2013-10-06 12:52:49 -07002280 /* This must be called before adding this usecase to the list */
2281 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2282 check_and_set_hdmi_channels(adev, out->config.channels);
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002283 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
2284 check_and_set_usb_service_interval(adev, uc_info, true /*min*/);
2285 /* USB backend is not reopened immediately.
2286 This is eventually done as part of select_devices */
2287 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002288
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002289 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002290
Wei Wangf4837d52017-11-21 14:51:20 -08002291 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002292 audio_extn_perf_lock_acquire();
2293
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002294 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2295 (!audio_extn_a2dp_is_ready())) {
2296 if (!a2dp_combo) {
2297 check_a2dp_restore_l(adev, out, false);
2298 } else {
2299 audio_devices_t dev = out->devices;
juyuchen9baad392018-06-05 19:02:10 +08002300 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2301 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2302 else
2303 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002304 select_devices(adev, out->usecase);
2305 out->devices = dev;
2306 }
2307 } else {
2308 select_devices(adev, out->usecase);
2309 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002310
Eric Laurent0499d4f2014-08-25 22:39:29 -05002311 audio_extn_extspk_update(adev->extspk);
2312
Arun Mirpuri0cc2f312018-05-29 17:26:07 -07002313 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
2314 voice_set_device_mute_flag(adev, true);
2315
Andy Hung31aca912014-03-20 17:14:59 -07002316 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002317 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002318 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2319 out->pcm = NULL;
2320 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
2321 COMPRESS_IN, &out->compr_config);
2322 if (out->compr && !is_compress_ready(out->compr)) {
2323 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2324 compress_close(out->compr);
2325 out->compr = NULL;
2326 ret = -EIO;
2327 goto error_open;
2328 }
2329 if (out->offload_callback)
2330 compress_nonblock(out->compr, out->non_blocking);
2331
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07002332 if (adev->visualizer_start_output != NULL) {
2333 int capture_device_id =
2334 platform_get_pcm_device_id(USECASE_AUDIO_RECORD_AFE_PROXY,
2335 PCM_CAPTURE);
2336 adev->visualizer_start_output(out->handle, out->pcm_device_id,
2337 adev->snd_card, capture_device_id);
2338 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002339 if (adev->offload_effects_start_output != NULL)
2340 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
2341 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002342 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002343 ALOGE("%s: pcm stream not ready", __func__);
2344 goto error_open;
2345 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002346 ret = pcm_start(out->pcm);
2347 if (ret < 0) {
2348 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2349 goto error_open;
2350 }
2351 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07002352 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002353 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002354
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002355 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2356 flags |= PCM_MMAP | PCM_NOIRQ;
2357 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002358 } else if (out->realtime) {
2359 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07002360 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002361
2362 while (1) {
2363 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2364 flags, &out->config);
2365 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2366 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2367 if (out->pcm != NULL) {
2368 pcm_close(out->pcm);
2369 out->pcm = NULL;
2370 }
2371 if (pcm_open_retry_count-- == 0) {
2372 ret = -EIO;
2373 goto error_open;
2374 }
2375 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2376 continue;
2377 }
2378 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002379 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002380 ALOGV("%s: pcm_prepare", __func__);
2381 if (pcm_is_ready(out->pcm)) {
2382 ret = pcm_prepare(out->pcm);
2383 if (ret < 0) {
2384 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2385 pcm_close(out->pcm);
2386 out->pcm = NULL;
2387 goto error_open;
2388 }
2389 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002390 if (out->realtime) {
2391 ret = pcm_start(out->pcm);
2392 if (ret < 0) {
2393 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
2394 pcm_close(out->pcm);
2395 out->pcm = NULL;
2396 goto error_open;
2397 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002398 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002399 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002400 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08002401 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002402 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002403 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07002404
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002405 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2406 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2407 audio_low_latency_hint_start();
2408 }
2409
vivek mehtae59cfb22017-06-16 15:57:11 -07002410 // consider a scenario where on pause lower layers are tear down.
2411 // so on resume, swap mixer control need to be sent only when
2412 // backend is active, hence rather than sending from enable device
2413 // sending it from start of streamtream
2414
2415 platform_set_swap_channels(adev, true);
2416
Eric Laurent994a6932013-07-17 11:51:42 -07002417 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002418 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002419error_open:
Wei Wangf4837d52017-11-21 14:51:20 -08002420 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002421 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002422 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002423error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002424 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002425}
2426
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002427static int check_input_parameters(uint32_t sample_rate,
2428 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07002429 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002430{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002431 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2432 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002433 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2434 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002435 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2436 return -EINVAL;
2437 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002438
Eric Laurent74b55762017-07-09 17:04:53 -07002439 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2440 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002441 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002442 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002443 return -EINVAL;
2444 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002445
2446 switch (sample_rate) {
2447 case 8000:
2448 case 11025:
2449 case 12000:
2450 case 16000:
2451 case 22050:
2452 case 24000:
2453 case 32000:
2454 case 44100:
2455 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002456 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002457 break;
2458 default:
vivek mehtadae44712015-07-27 14:13:18 -07002459 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002460 return -EINVAL;
2461 }
2462
2463 return 0;
2464}
2465
Kevin Rocarda325aa22018-04-03 09:15:52 -07002466/** Add a value in a list if not already present.
2467 * @return true if value was successfully inserted or already present,
2468 * false if the list is full and does not contain the value.
2469 */
2470static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
2471 for (size_t i = 0; i < list_length; i++) {
2472 if (list[i] == value) return true; // value is already present
2473 if (list[i] == 0) { // no values in this slot
2474 list[i] = value;
2475 return true; // value inserted
2476 }
2477 }
2478 return false; // could not insert value
2479}
2480
2481/** Add channel_mask in supported_channel_masks if not already present.
2482 * @return true if channel_mask was successfully inserted or already present,
2483 * false if supported_channel_masks is full and does not contain channel_mask.
2484 */
2485static void register_channel_mask(audio_channel_mask_t channel_mask,
2486 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
2487 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
2488 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
2489}
2490
2491/** Add format in supported_formats if not already present.
2492 * @return true if format was successfully inserted or already present,
2493 * false if supported_formats is full and does not contain format.
2494 */
2495static void register_format(audio_format_t format,
2496 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
2497 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
2498 "%s: stream can not declare supporting its format %x", __func__, format);
2499}
2500/** Add sample_rate in supported_sample_rates if not already present.
2501 * @return true if sample_rate was successfully inserted or already present,
2502 * false if supported_sample_rates is full and does not contain sample_rate.
2503 */
2504static void register_sample_rate(uint32_t sample_rate,
2505 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
2506 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
2507 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
2508}
2509
vivek mehtaa68fea62017-06-08 19:04:02 -07002510static size_t get_stream_buffer_size(size_t duration_ms,
2511 uint32_t sample_rate,
2512 audio_format_t format,
2513 int channel_count,
2514 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002515{
2516 size_t size = 0;
2517
vivek mehtaa68fea62017-06-08 19:04:02 -07002518 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002519 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002520 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002521
2522 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002523
Glenn Kasten4f993392014-05-14 07:30:48 -07002524 /* make sure the size is multiple of 32 bytes
2525 * At 48 kHz mono 16-bit PCM:
2526 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2527 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2528 */
2529 size += 0x1f;
2530 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002531
2532 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002533}
2534
2535static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2536{
2537 struct stream_out *out = (struct stream_out *)stream;
2538
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002539 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002540}
2541
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002542static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002543{
2544 return -ENOSYS;
2545}
2546
2547static size_t out_get_buffer_size(const struct audio_stream *stream)
2548{
2549 struct stream_out *out = (struct stream_out *)stream;
2550
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002551 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2552 return out->compr_config.fragment_size;
2553 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002554 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002555 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002556}
2557
2558static uint32_t out_get_channels(const struct audio_stream *stream)
2559{
2560 struct stream_out *out = (struct stream_out *)stream;
2561
2562 return out->channel_mask;
2563}
2564
2565static audio_format_t out_get_format(const struct audio_stream *stream)
2566{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002567 struct stream_out *out = (struct stream_out *)stream;
2568
2569 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002570}
2571
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002572static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002573{
2574 return -ENOSYS;
2575}
2576
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002577/* must be called with out->lock locked */
2578static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002579{
2580 struct stream_out *out = (struct stream_out *)stream;
2581 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002582 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002583
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002584 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002585 if (adev->adm_deregister_stream)
2586 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002587 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002588 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002589 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2590 if (out->pcm) {
2591 pcm_close(out->pcm);
2592 out->pcm = NULL;
2593 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002594 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002595 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002596 out->playback_started = false;
2597 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002598 } else {
2599 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002600 out->gapless_mdata.encoder_delay = 0;
2601 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002602 if (out->compr != NULL) {
2603 compress_close(out->compr);
2604 out->compr = NULL;
2605 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002606 }
Phil Burkbc991042017-02-24 08:06:44 -08002607 if (do_stop) {
2608 stop_output_stream(out);
2609 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002610 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002611 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002612 return 0;
2613}
2614
2615static int out_standby(struct audio_stream *stream)
2616{
2617 struct stream_out *out = (struct stream_out *)stream;
2618
2619 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2620 out->usecase, use_case_table[out->usecase]);
2621
2622 lock_output_stream(out);
2623 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002624 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002625 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002626 return 0;
2627}
2628
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002629static int out_on_error(struct audio_stream *stream)
2630{
2631 struct stream_out *out = (struct stream_out *)stream;
2632 struct audio_device *adev = out->dev;
2633 bool do_standby = false;
2634
2635 lock_output_stream(out);
2636 if (!out->standby) {
2637 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2638 stop_compressed_output_l(out);
2639 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2640 } else
2641 do_standby = true;
2642 }
2643 pthread_mutex_unlock(&out->lock);
2644
2645 if (do_standby)
2646 return out_standby(&out->stream.common);
2647
2648 return 0;
2649}
2650
Andy Hung7401c7c2016-09-21 12:41:21 -07002651static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002652{
Andy Hung7401c7c2016-09-21 12:41:21 -07002653 struct stream_out *out = (struct stream_out *)stream;
2654
2655 // We try to get the lock for consistency,
2656 // but it isn't necessary for these variables.
2657 // If we're not in standby, we may be blocked on a write.
2658 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2659 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2660 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2661
2662 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002663 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002664 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002665
2666 // dump error info
2667 (void)error_log_dump(
2668 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002669
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002670 return 0;
2671}
2672
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002673static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2674{
2675 int ret = 0;
2676 char value[32];
2677 struct compr_gapless_mdata tmp_mdata;
2678
2679 if (!out || !parms) {
2680 return -EINVAL;
2681 }
2682
2683 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2684 if (ret >= 0) {
2685 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2686 } else {
2687 return -EINVAL;
2688 }
2689
2690 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2691 if (ret >= 0) {
2692 tmp_mdata.encoder_padding = atoi(value);
2693 } else {
2694 return -EINVAL;
2695 }
2696
2697 out->gapless_mdata = tmp_mdata;
2698 out->send_new_metadata = 1;
2699 ALOGV("%s new encoder delay %u and padding %u", __func__,
2700 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2701
2702 return 0;
2703}
2704
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002705static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2706{
2707 return out == adev->primary_output || out == adev->voice_tx_output;
2708}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002709
Kevin Rocard1e02c882017-08-09 15:26:07 -07002710static int get_alive_usb_card(struct str_parms* parms) {
2711 int card;
2712 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2713 !audio_extn_usb_alive(card)) {
2714 return card;
2715 }
2716 return -ENODEV;
2717}
2718
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002719static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2720{
2721 struct stream_out *out = (struct stream_out *)stream;
2722 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002723 struct audio_usecase *usecase;
2724 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002725 struct str_parms *parms;
2726 char value[32];
2727 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002728 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002729 int status = 0;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002730 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002731
Eric Laurent2e140aa2016-06-30 17:14:46 -07002732 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002733 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002734 parms = str_parms_create_str(kvpairs);
2735 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2736 if (ret >= 0) {
2737 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002738
Eric Laurenta1478072015-09-21 17:21:52 -07002739 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002740
2741 // The usb driver needs to be closed after usb device disconnection
2742 // otherwise audio is no longer played on the new usb devices.
2743 // By forcing the stream in standby, the usb stack refcount drops to 0
2744 // and the driver is closed.
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002745 if (val == AUDIO_DEVICE_NONE &&
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002746 audio_is_usb_out_device(out->devices)) {
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002747 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2748 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2749 out_standby_l(&out->stream.common);
2750 }
2751 val = AUDIO_DEVICE_OUT_SPEAKER;
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002752 }
2753
Eric Laurent150dbfe2013-02-27 14:31:02 -08002754 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002755
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002756 /*
2757 * When HDMI cable is unplugged the music playback is paused and
2758 * the policy manager sends routing=0. But the audioflinger
2759 * continues to write data until standby time (3sec).
2760 * As the HDMI core is turned off, the write gets blocked.
2761 * Avoid this by routing audio to speaker until standby.
2762 */
2763 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2764 val == AUDIO_DEVICE_NONE) {
2765 val = AUDIO_DEVICE_OUT_SPEAKER;
2766 }
2767
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002768 /*
2769 * When A2DP is disconnected the
2770 * music playback is paused and the policy manager sends routing=0
2771 * But the audioflingercontinues to write data until standby time
2772 * (3sec). As BT is turned off, the write gets blocked.
2773 * Avoid this by routing audio to speaker until standby.
2774 */
2775 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2776 (val == AUDIO_DEVICE_NONE) &&
2777 !audio_extn_a2dp_is_ready()) {
2778 val = AUDIO_DEVICE_OUT_SPEAKER;
2779 }
2780
2781 /* To avoid a2dp to sco overlapping / BT device improper state
2782 * check with BT lib about a2dp streaming support before routing
2783 */
2784 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2785 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002786 if (val & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002787 //combo usecase just by pass a2dp
2788 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2789 bypass_a2dp = true;
2790 } else {
2791 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2792 /* update device to a2dp and don't route as BT returned error
2793 * However it is still possible a2dp routing called because
2794 * of current active device disconnection (like wired headset)
2795 */
2796 out->devices = val;
2797 pthread_mutex_unlock(&out->lock);
2798 pthread_mutex_unlock(&adev->lock);
2799 status = -ENOSYS;
2800 goto routing_fail;
2801 }
2802 }
2803 }
2804
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002805 audio_devices_t new_dev = val;
2806
2807 // Workaround: If routing to an non existing usb device, fail gracefully
2808 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002809 int card;
2810 if (audio_is_usb_out_device(new_dev) &&
2811 (card = get_alive_usb_card(parms)) >= 0) {
2812
2813 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002814 pthread_mutex_unlock(&adev->lock);
2815 pthread_mutex_unlock(&out->lock);
2816 status = -ENOSYS;
2817 goto routing_fail;
2818 }
2819
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002820 /*
2821 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002822 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002823 * the select_devices(). But how do we undo this?
2824 *
2825 * For example, music playback is active on headset (deep-buffer usecase)
2826 * and if we go to ringtones and select a ringtone, low-latency usecase
2827 * will be started on headset+speaker. As we can't enable headset+speaker
2828 * and headset devices at the same time, select_devices() switches the music
2829 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2830 * So when the ringtone playback is completed, how do we undo the same?
2831 *
2832 * We are relying on the out_set_parameters() call on deep-buffer output,
2833 * once the ringtone playback is ended.
2834 * NOTE: We should not check if the current devices are same as new devices.
2835 * Because select_devices() must be called to switch back the music
2836 * playback to headset.
2837 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002838 if (new_dev != AUDIO_DEVICE_NONE) {
2839 bool same_dev = out->devices == new_dev;
2840 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002841
Eric Laurenta7657192014-10-09 21:09:33 -07002842 if (output_drives_call(adev, out)) {
Vignesh Kulothungana5c9da12017-11-10 11:41:24 -08002843 if (!voice_is_call_state_active(adev)) {
Eric Laurenta7657192014-10-09 21:09:33 -07002844 if (adev->mode == AUDIO_MODE_IN_CALL) {
2845 adev->current_call_output = out;
2846 ret = voice_start_call(adev);
2847 }
2848 } else {
2849 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002850 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002851 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002852 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002853
2854 if (!out->standby) {
2855 if (!same_dev) {
2856 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002857 // inform adm before actual routing to prevent glitches.
2858 if (adev->adm_on_routing_change) {
2859 adev->adm_on_routing_change(adev->adm_data,
2860 out->handle);
2861 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002862 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002863 if (!bypass_a2dp) {
2864 select_devices(adev, out->usecase);
2865 } else {
juyuchen9baad392018-06-05 19:02:10 +08002866 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2867 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2868 else
2869 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002870 select_devices(adev, out->usecase);
2871 out->devices = new_dev;
2872 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002873 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002874
2875 // on device switch force swap, lower functions will make sure
2876 // to check if swap is allowed or not.
2877
2878 if (!same_dev)
2879 platform_set_swap_channels(adev, true);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002880
2881 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2882 out->a2dp_compress_mute &&
2883 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
2884 pthread_mutex_lock(&out->compr_mute_lock);
2885 out->a2dp_compress_mute = false;
2886 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
2887 pthread_mutex_unlock(&out->compr_mute_lock);
2888 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002889 }
2890
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002891 }
2892
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002893 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002894 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002895
2896 /*handles device and call state changes*/
2897 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002898 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002899 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002900
2901 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2902 parse_compress_metadata(out, parms);
2903 }
2904
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002905 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002906 ALOGV("%s: exit: code(%d)", __func__, status);
2907 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002908}
2909
Haynes Mathew George569b7482017-05-08 14:44:27 -07002910static bool stream_get_parameter_channels(struct str_parms *query,
2911 struct str_parms *reply,
2912 audio_channel_mask_t *supported_channel_masks) {
2913 int ret = -1;
Andy Hung64fdb452018-09-07 11:25:33 -07002914 char value[ARRAY_SIZE(channels_name_to_enum_table) * 32 /* max channel name size */];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002915 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002916 size_t i, j;
2917
2918 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2919 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002920 value[0] = '\0';
2921 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002922 while (supported_channel_masks[i] != 0) {
2923 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2924 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002925 if (!first) {
2926 strcat(value, "|");
2927 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002928 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002929 first = false;
2930 break;
2931 }
2932 }
2933 i++;
2934 }
2935 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002936 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002937 return ret >= 0;
2938}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002939
Haynes Mathew George569b7482017-05-08 14:44:27 -07002940static bool stream_get_parameter_formats(struct str_parms *query,
2941 struct str_parms *reply,
2942 audio_format_t *supported_formats) {
2943 int ret = -1;
2944 char value[256];
2945 int i;
2946
2947 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2948 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002949 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002950 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002951 case AUDIO_FORMAT_PCM_16_BIT:
2952 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2953 break;
2954 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2955 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2956 break;
2957 case AUDIO_FORMAT_PCM_32_BIT:
2958 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2959 break;
2960 default:
2961 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002962 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002963 break;
2964 }
2965 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002966 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002967 return ret >= 0;
2968}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002969
Haynes Mathew George569b7482017-05-08 14:44:27 -07002970static bool stream_get_parameter_rates(struct str_parms *query,
2971 struct str_parms *reply,
2972 uint32_t *supported_sample_rates) {
2973
2974 int i;
2975 char value[256];
2976 int ret = -1;
2977 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2978 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002979 value[0] = '\0';
2980 i=0;
2981 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002982 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002983 int avail = sizeof(value) - cursor;
2984 ret = snprintf(value + cursor, avail, "%s%d",
2985 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002986 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002987 if (ret < 0 || ret >= avail) {
2988 // if cursor is at the last element of the array
2989 // overwrite with \0 is duplicate work as
2990 // snprintf already put a \0 in place.
2991 // else
2992 // we had space to write the '|' at value[cursor]
2993 // (which will be overwritten) or no space to fill
2994 // the first element (=> cursor == 0)
2995 value[cursor] = '\0';
2996 break;
2997 }
2998 cursor += ret;
2999 ++i;
3000 }
3001 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
3002 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003003 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003004 return ret >= 0;
3005}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003006
Haynes Mathew George569b7482017-05-08 14:44:27 -07003007static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
3008{
3009 struct stream_out *out = (struct stream_out *)stream;
3010 struct str_parms *query = str_parms_create_str(keys);
3011 char *str;
3012 struct str_parms *reply = str_parms_create();
3013 bool replied = false;
3014 ALOGV("%s: enter: keys - %s", __func__, keys);
3015
3016 replied |= stream_get_parameter_channels(query, reply,
3017 &out->supported_channel_masks[0]);
3018 replied |= stream_get_parameter_formats(query, reply,
3019 &out->supported_formats[0]);
3020 replied |= stream_get_parameter_rates(query, reply,
3021 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003022 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003023 str = str_parms_to_str(reply);
3024 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07003025 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003026 }
3027 str_parms_destroy(query);
3028 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07003029 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003030 return str;
3031}
3032
3033static uint32_t out_get_latency(const struct audio_stream_out *stream)
3034{
Haynes Mathew George03c40102016-01-29 17:57:48 -08003035 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003036 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003037 uint32_t latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003038
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003039 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3040 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003041 else if ((out->realtime) ||
3042 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003043 // since the buffer won't be filled up faster than realtime,
3044 // return a smaller number
3045 period_ms = (out->af_period_multiplier * out->config.period_size *
3046 1000) / (out->config.rate);
3047 hw_delay = platform_render_latency(out->usecase)/1000;
3048 return period_ms + hw_delay;
3049 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003050
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003051 latency = (out->config.period_count * out->config.period_size * 1000) /
3052 (out->config.rate);
3053
3054 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
3055 latency += audio_extn_a2dp_get_encoder_latency();
3056
3057 return latency;
3058}
3059
3060static int set_compr_volume(struct audio_stream_out *stream, float left,
3061 float right)
3062{
3063 struct stream_out *out = (struct stream_out *)stream;
3064 int volume[2];
3065 char mixer_ctl_name[128];
3066 struct audio_device *adev = out->dev;
3067 struct mixer_ctl *ctl;
3068 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
3069 PCM_PLAYBACK);
3070
3071 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3072 "Compress Playback %d Volume", pcm_device_id);
3073 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3074 if (!ctl) {
3075 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3076 __func__, mixer_ctl_name);
3077 return -EINVAL;
3078 }
3079 ALOGV("%s: ctl for mixer cmd - %s, left %f, right %f",
3080 __func__, mixer_ctl_name, left, right);
3081 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3082 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3083 mixer_ctl_set_array(ctl, volume, sizeof(volume) / sizeof(volume[0]));
3084
3085 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003086}
3087
3088static int out_set_volume(struct audio_stream_out *stream, float left,
3089 float right)
3090{
Eric Laurenta9024de2013-04-04 09:19:12 -07003091 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003092 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003093
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003094 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07003095 /* only take left channel into account: the API is for stereo anyway */
3096 out->muted = (left == 0.0f);
3097 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003098 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003099 pthread_mutex_lock(&out->compr_mute_lock);
3100 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
3101 if (!out->a2dp_compress_mute)
3102 ret = set_compr_volume(stream, left, right);
3103 out->volume_l = left;
3104 out->volume_r = right;
3105 pthread_mutex_unlock(&out->compr_mute_lock);
3106 return ret;
vivek mehtaa68fea62017-06-08 19:04:02 -07003107 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07003108 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
3109 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
3110 if (!out->standby) {
3111 // if in standby, cached volume will be sent after stream is opened
3112 audio_extn_utils_send_app_type_gain(out->dev,
3113 out->app_type_cfg.app_type,
3114 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07003115 }
vivek mehtaa68fea62017-06-08 19:04:02 -07003116 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07003117 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003118
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003119 return -ENOSYS;
3120}
3121
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003122// note: this call is safe only if the stream_cb is
3123// removed first in close_output_stream (as is done now).
3124static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3125{
3126 if (!stream || !parms)
3127 return;
3128
3129 struct stream_out *out = (struct stream_out *)stream;
3130 struct audio_device *adev = out->dev;
3131
3132 card_status_t status;
3133 int card;
3134 if (parse_snd_card_status(parms, &card, &status) < 0)
3135 return;
3136
3137 pthread_mutex_lock(&adev->lock);
3138 bool valid_cb = (card == adev->snd_card);
3139 pthread_mutex_unlock(&adev->lock);
3140
3141 if (!valid_cb)
3142 return;
3143
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003144 lock_output_stream(out);
3145 if (out->card_status != status)
3146 out->card_status = status;
3147 pthread_mutex_unlock(&out->lock);
3148
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07003149 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
3150 use_case_table[out->usecase],
3151 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3152
3153 if (status == CARD_STATUS_OFFLINE)
3154 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003155
3156 return;
3157}
3158
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003159#ifdef NO_AUDIO_OUT
3160static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05003161 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003162{
3163 struct stream_out *out = (struct stream_out *)stream;
3164
3165 /* No Output device supported other than BT for playback.
3166 * Sleep for the amount of buffer duration
3167 */
Eric Laurenta1478072015-09-21 17:21:52 -07003168 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05003169 usleep(bytes * 1000000 / audio_stream_out_frame_size(
3170 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003171 out_get_sample_rate(&out->stream.common));
3172 pthread_mutex_unlock(&out->lock);
3173 return bytes;
3174}
3175#endif
3176
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003177static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3178 size_t bytes)
3179{
3180 struct stream_out *out = (struct stream_out *)stream;
3181 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07003182 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07003183 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003184
Eric Laurenta1478072015-09-21 17:21:52 -07003185 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07003186 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07003187 const size_t frame_size = audio_stream_out_frame_size(stream);
3188 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07003189
Eric Laurent0e46adf2016-12-16 12:49:24 -08003190 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3191 error_code = ERROR_CODE_WRITE;
3192 goto exit;
3193 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003194
3195 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3196 (audio_extn_a2dp_is_suspended())) {
juyuchen9baad392018-06-05 19:02:10 +08003197 if (!(out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003198 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3199 ret = -EIO;
3200 goto exit;
3201 }
3202 }
3203 }
3204
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003205 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003206 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003207 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003208 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07003209
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003210 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003211 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003212 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07003213 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003214 goto exit;
3215 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07003216
vivek mehta40125092017-08-21 18:48:51 -07003217 // after standby always force set last known cal step
3218 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
3219 ALOGD("%s: retry previous failed cal level set", __func__);
3220 send_gain_dep_calibration_l();
3221 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003222 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003223
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003224 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003225 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003226 if (out->send_new_metadata) {
3227 ALOGVV("send new gapless metadata");
3228 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3229 out->send_new_metadata = 0;
3230 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003231 unsigned int avail;
3232 struct timespec tstamp;
3233 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
3234 /* Do not limit write size if the available frames count is unknown */
3235 if (ret != 0) {
3236 avail = bytes;
3237 }
3238 if (avail == 0) {
3239 ret = 0;
3240 } else {
3241 if (avail > bytes) {
3242 avail = bytes;
3243 }
3244 ret = compress_write(out->compr, buffer, avail);
3245 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
3246 __func__, avail, ret);
3247 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003248
Eric Laurent6e895242013-09-05 16:10:57 -07003249 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003250 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
3251 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003252 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003253 compress_start(out->compr);
3254 out->playback_started = 1;
3255 out->offload_state = OFFLOAD_STATE_PLAYING;
3256 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003257 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07003258 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07003259 } else {
3260 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07003261 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003262 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07003263 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003264 return ret;
3265 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07003266 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003267 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003268 size_t bytes_to_write = bytes;
3269
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003270 if (out->muted)
3271 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07003272 // FIXME: this can be removed once audio flinger mixer supports mono output
Nadav Bar3d72cfc2018-01-07 12:19:24 +02003273 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP || out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003274 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3275 int16_t *src = (int16_t *)buffer;
3276 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003277
Eric Laurentad2dde92017-09-20 18:27:31 -07003278 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
3279 out->format != AUDIO_FORMAT_PCM_16_BIT,
3280 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003281
Eric Laurentad2dde92017-09-20 18:27:31 -07003282 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
3283 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
3284 }
3285 bytes_to_write /= 2;
3286 }
3287 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes_to_write);
3288
Glenn Kasten5a59dff2018-02-22 08:05:35 -08003289 long ns = (frames * (int64_t) NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003290 request_out_focus(out, ns);
3291
3292 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3293 if (use_mmap)
Eric Laurentad2dde92017-09-20 18:27:31 -07003294 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003295 else
Eric Laurentad2dde92017-09-20 18:27:31 -07003296 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003297
Haynes Mathew George03c40102016-01-29 17:57:48 -08003298 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07003299 } else {
3300 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003301 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003302 }
3303
3304exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07003305 // For PCM we always consume the buffer and return #bytes regardless of ret.
3306 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003307 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07003308 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003309 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07003310
Andy Hung7401c7c2016-09-21 12:41:21 -07003311 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07003312 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07003313 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3314 ALOGE_IF(out->pcm != NULL,
3315 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07003316 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003317 // usleep not guaranteed for values over 1 second but we don't limit here.
3318 }
3319 }
Andy Hungda9b56b2016-09-16 20:06:35 -07003320
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003321 pthread_mutex_unlock(&out->lock);
3322
3323 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07003324 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003325 if (sleeptime_us != 0)
3326 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003327 }
3328 return bytes;
3329}
3330
3331static int out_get_render_position(const struct audio_stream_out *stream,
3332 uint32_t *dsp_frames)
3333{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003334 struct stream_out *out = (struct stream_out *)stream;
3335 *dsp_frames = 0;
3336 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07003337 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003338 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003339 unsigned long frames = 0;
3340 // TODO: check return value
3341 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
3342 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003343 ALOGVV("%s rendered frames %d sample_rate %d",
3344 __func__, *dsp_frames, out->sample_rate);
3345 }
3346 pthread_mutex_unlock(&out->lock);
3347 return 0;
3348 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003349 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003350}
3351
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003352static int out_add_audio_effect(const struct audio_stream *stream __unused,
3353 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003354{
3355 return 0;
3356}
3357
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003358static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3359 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003360{
3361 return 0;
3362}
3363
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003364static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3365 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003366{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003367 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003368}
3369
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003370static int out_get_presentation_position(const struct audio_stream_out *stream,
3371 uint64_t *frames, struct timespec *timestamp)
3372{
3373 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003374 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07003375 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003376
Eric Laurenta1478072015-09-21 17:21:52 -07003377 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003378
Eric Laurent949a0892013-09-20 09:20:13 -07003379 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3380 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003381 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07003382 compress_get_tstamp(out->compr, &dsp_frames,
3383 &out->sample_rate);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003384 // Adjustment accounts for A2DP encoder latency with offload usecases
3385 // Note: Encoder latency is returned in ms.
3386 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3387 unsigned long offset =
3388 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3389 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
3390 }
Eric Laurent949a0892013-09-20 09:20:13 -07003391 ALOGVV("%s rendered frames %ld sample_rate %d",
3392 __func__, dsp_frames, out->sample_rate);
3393 *frames = dsp_frames;
3394 ret = 0;
3395 /* this is the best we can do */
3396 clock_gettime(CLOCK_MONOTONIC, timestamp);
3397 }
3398 } else {
3399 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07003400 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003401 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3402 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003403 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003404 // This adjustment accounts for buffering after app processor.
3405 // It is based on estimated DSP latency per use case, rather than exact.
3406 signed_frames -=
3407 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3408
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003409 // Adjustment accounts for A2DP encoder latency with non-offload usecases
3410 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3411 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3412 signed_frames -=
3413 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3414 }
3415
Eric Laurent949a0892013-09-20 09:20:13 -07003416 // It would be unusual for this value to be negative, but check just in case ...
3417 if (signed_frames >= 0) {
3418 *frames = signed_frames;
3419 ret = 0;
3420 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003421 }
3422 }
3423 }
3424
3425 pthread_mutex_unlock(&out->lock);
3426
3427 return ret;
3428}
3429
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003430static int out_set_callback(struct audio_stream_out *stream,
3431 stream_callback_t callback, void *cookie)
3432{
3433 struct stream_out *out = (struct stream_out *)stream;
3434
3435 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003436 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003437 out->offload_callback = callback;
3438 out->offload_cookie = cookie;
3439 pthread_mutex_unlock(&out->lock);
3440 return 0;
3441}
3442
3443static int out_pause(struct audio_stream_out* stream)
3444{
3445 struct stream_out *out = (struct stream_out *)stream;
3446 int status = -ENOSYS;
3447 ALOGV("%s", __func__);
3448 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003449 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003450 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
3451 status = compress_pause(out->compr);
3452 out->offload_state = OFFLOAD_STATE_PAUSED;
3453 }
3454 pthread_mutex_unlock(&out->lock);
3455 }
3456 return status;
3457}
3458
3459static int out_resume(struct audio_stream_out* stream)
3460{
3461 struct stream_out *out = (struct stream_out *)stream;
3462 int status = -ENOSYS;
3463 ALOGV("%s", __func__);
3464 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3465 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07003466 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003467 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
3468 status = compress_resume(out->compr);
3469 out->offload_state = OFFLOAD_STATE_PLAYING;
3470 }
3471 pthread_mutex_unlock(&out->lock);
3472 }
3473 return status;
3474}
3475
3476static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3477{
3478 struct stream_out *out = (struct stream_out *)stream;
3479 int status = -ENOSYS;
3480 ALOGV("%s", __func__);
3481 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003482 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003483 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3484 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3485 else
3486 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3487 pthread_mutex_unlock(&out->lock);
3488 }
3489 return status;
3490}
3491
3492static int out_flush(struct audio_stream_out* stream)
3493{
3494 struct stream_out *out = (struct stream_out *)stream;
3495 ALOGV("%s", __func__);
3496 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003497 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003498 stop_compressed_output_l(out);
3499 pthread_mutex_unlock(&out->lock);
3500 return 0;
3501 }
3502 return -ENOSYS;
3503}
3504
Eric Laurent0e46adf2016-12-16 12:49:24 -08003505static int out_stop(const struct audio_stream_out* stream)
3506{
3507 struct stream_out *out = (struct stream_out *)stream;
3508 struct audio_device *adev = out->dev;
3509 int ret = -ENOSYS;
3510
3511 ALOGV("%s", __func__);
3512 pthread_mutex_lock(&adev->lock);
3513 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3514 out->playback_started && out->pcm != NULL) {
3515 pcm_stop(out->pcm);
3516 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08003517 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003518 }
3519 pthread_mutex_unlock(&adev->lock);
3520 return ret;
3521}
3522
3523static int out_start(const struct audio_stream_out* stream)
3524{
3525 struct stream_out *out = (struct stream_out *)stream;
3526 struct audio_device *adev = out->dev;
3527 int ret = -ENOSYS;
3528
3529 ALOGV("%s", __func__);
3530 pthread_mutex_lock(&adev->lock);
3531 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3532 !out->playback_started && out->pcm != NULL) {
3533 ret = start_output_stream(out);
3534 if (ret == 0) {
3535 out->playback_started = true;
3536 }
3537 }
3538 pthread_mutex_unlock(&adev->lock);
3539 return ret;
3540}
3541
Phil Burkbc991042017-02-24 08:06:44 -08003542/*
3543 * Modify config->period_count based on min_size_frames
3544 */
3545static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
3546{
3547 int periodCountRequested = (min_size_frames + config->period_size - 1)
3548 / config->period_size;
3549 int periodCount = MMAP_PERIOD_COUNT_MIN;
3550
3551 ALOGV("%s original config.period_size = %d config.period_count = %d",
3552 __func__, config->period_size, config->period_count);
3553
3554 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
3555 periodCount *= 2;
3556 }
3557 config->period_count = periodCount;
3558
3559 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
3560}
3561
Eric Laurent0e46adf2016-12-16 12:49:24 -08003562static int out_create_mmap_buffer(const struct audio_stream_out *stream,
3563 int32_t min_size_frames,
3564 struct audio_mmap_buffer_info *info)
3565{
3566 struct stream_out *out = (struct stream_out *)stream;
3567 struct audio_device *adev = out->dev;
3568 int ret = 0;
3569 unsigned int offset1;
3570 unsigned int frames1;
3571 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003572 uint32_t mmap_size;
3573 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003574
3575 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003576 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003577 pthread_mutex_lock(&adev->lock);
3578
3579 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003580 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003581 ret = -EINVAL;
3582 goto exit;
3583 }
3584 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003585 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003586 ret = -ENOSYS;
3587 goto exit;
3588 }
3589 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3590 if (out->pcm_device_id < 0) {
3591 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3592 __func__, out->pcm_device_id, out->usecase);
3593 ret = -EINVAL;
3594 goto exit;
3595 }
Phil Burkbc991042017-02-24 08:06:44 -08003596
3597 adjust_mmap_period_count(&out->config, min_size_frames);
3598
Eric Laurent0e46adf2016-12-16 12:49:24 -08003599 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3600 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3601 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3602 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3603 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3604 step = "open";
3605 ret = -ENODEV;
3606 goto exit;
3607 }
3608 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3609 if (ret < 0) {
3610 step = "begin";
3611 goto exit;
3612 }
3613 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003614 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003615 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003616 ret = platform_get_mmap_data_fd(adev->platform,
3617 out->pcm_device_id, 0 /*playback*/,
3618 &info->shared_memory_fd,
3619 &mmap_size);
3620 if (ret < 0) {
3621 // Fall back to non exclusive mode
3622 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3623 } else {
3624 if (mmap_size < buffer_size) {
3625 step = "mmap";
3626 goto exit;
3627 }
3628 // FIXME: indicate exclusive mode support by returning a negative buffer size
3629 info->buffer_size_frames *= -1;
3630 }
3631 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003632
3633 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3634 if (ret < 0) {
3635 step = "commit";
3636 goto exit;
3637 }
Phil Burkbc991042017-02-24 08:06:44 -08003638
3639 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003640 ret = 0;
3641
3642 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3643 __func__, info->shared_memory_address, info->buffer_size_frames);
3644
3645exit:
3646 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003647 if (out->pcm == NULL) {
3648 ALOGE("%s: %s - %d", __func__, step, ret);
3649 } else {
3650 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003651 pcm_close(out->pcm);
3652 out->pcm = NULL;
3653 }
3654 }
3655 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003656 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003657 return ret;
3658}
3659
3660static int out_get_mmap_position(const struct audio_stream_out *stream,
3661 struct audio_mmap_position *position)
3662{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003663 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003664 struct stream_out *out = (struct stream_out *)stream;
3665 ALOGVV("%s", __func__);
3666 if (position == NULL) {
3667 return -EINVAL;
3668 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003669 lock_output_stream(out);
3670 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3671 out->pcm == NULL) {
3672 ret = -ENOSYS;
3673 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003674 }
3675
3676 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003677 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003678 if (ret < 0) {
3679 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003680 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003681 }
Andy Hungfc044e12017-03-20 09:24:22 -07003682 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003683exit:
3684 pthread_mutex_unlock(&out->lock);
3685 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003686}
3687
3688
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003689/** audio_stream_in implementation **/
3690static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3691{
3692 struct stream_in *in = (struct stream_in *)stream;
3693
3694 return in->config.rate;
3695}
3696
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003697static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003698{
3699 return -ENOSYS;
3700}
3701
3702static size_t in_get_buffer_size(const struct audio_stream *stream)
3703{
3704 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003705 return in->config.period_size * in->af_period_multiplier *
3706 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003707}
3708
3709static uint32_t in_get_channels(const struct audio_stream *stream)
3710{
3711 struct stream_in *in = (struct stream_in *)stream;
3712
3713 return in->channel_mask;
3714}
3715
vivek mehta4ed66e62016-04-15 23:33:34 -07003716static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003717{
vivek mehta4ed66e62016-04-15 23:33:34 -07003718 struct stream_in *in = (struct stream_in *)stream;
3719 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003720}
3721
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003722static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003723{
3724 return -ENOSYS;
3725}
3726
3727static int in_standby(struct audio_stream *stream)
3728{
3729 struct stream_in *in = (struct stream_in *)stream;
3730 struct audio_device *adev = in->dev;
3731 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003732 bool do_stop = true;
3733
Eric Laurent994a6932013-07-17 11:51:42 -07003734 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003735
3736 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003737
3738 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003739 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003740 audio_extn_sound_trigger_stop_lab(in);
3741 in->standby = true;
3742 }
3743
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003744 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003745 if (adev->adm_deregister_stream)
3746 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3747
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003748 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003749 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003750 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003751 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003752 in->capture_started = false;
3753 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003754 if (in->pcm) {
3755 pcm_close(in->pcm);
3756 in->pcm = NULL;
3757 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003758 adev->enable_voicerx = false;
3759 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003760 if (do_stop) {
3761 status = stop_input_stream(in);
3762 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003763 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003764 }
3765 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003766 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003767 return status;
3768}
3769
Andy Hungd13f0d32017-06-12 13:58:37 -07003770static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003771{
Andy Hungd13f0d32017-06-12 13:58:37 -07003772 struct stream_in *in = (struct stream_in *)stream;
3773
3774 // We try to get the lock for consistency,
3775 // but it isn't necessary for these variables.
3776 // If we're not in standby, we may be blocked on a read.
3777 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3778 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3779 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3780 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3781
3782 if (locked) {
3783 pthread_mutex_unlock(&in->lock);
3784 }
3785
3786 // dump error info
3787 (void)error_log_dump(
3788 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003789 return 0;
3790}
3791
3792static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3793{
3794 struct stream_in *in = (struct stream_in *)stream;
3795 struct audio_device *adev = in->dev;
3796 struct str_parms *parms;
3797 char *str;
3798 char value[32];
3799 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003800 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003801
Eric Laurent994a6932013-07-17 11:51:42 -07003802 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003803 parms = str_parms_create_str(kvpairs);
3804
3805 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3806
Eric Laurenta1478072015-09-21 17:21:52 -07003807 lock_input_stream(in);
3808
Eric Laurent150dbfe2013-02-27 14:31:02 -08003809 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003810 if (ret >= 0) {
3811 val = atoi(value);
3812 /* no audio source uses val == 0 */
3813 if ((in->source != val) && (val != 0)) {
3814 in->source = val;
3815 }
3816 }
3817
3818 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003819
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003820 if (ret >= 0) {
3821 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003822 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003823
3824 // Workaround: If routing to an non existing usb device, fail gracefully
3825 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003826 int card;
3827 if (audio_is_usb_in_device(val) &&
3828 (card = get_alive_usb_card(parms)) >= 0) {
3829
3830 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003831 status = -ENOSYS;
3832 } else {
3833
3834 in->device = val;
3835 /* If recording is in progress, change the tx device to new device */
3836 if (!in->standby) {
3837 ALOGV("update input routing change");
3838 // inform adm before actual routing to prevent glitches.
3839 if (adev->adm_on_routing_change) {
3840 adev->adm_on_routing_change(adev->adm_data,
3841 in->capture_handle);
3842 }
3843 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003844 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003845 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003846 }
3847 }
3848
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003849 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003850 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003851
3852 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003853 ALOGV("%s: exit: status(%d)", __func__, status);
3854 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003855}
3856
Haynes Mathew George569b7482017-05-08 14:44:27 -07003857static char* in_get_parameters(const struct audio_stream *stream,
3858 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003859{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003860 struct stream_in *in = (struct stream_in *)stream;
3861 struct str_parms *query = str_parms_create_str(keys);
3862 char *str;
3863 struct str_parms *reply = str_parms_create();
3864 bool replied = false;
3865
3866 ALOGV("%s: enter: keys - %s", __func__, keys);
3867 replied |= stream_get_parameter_channels(query, reply,
3868 &in->supported_channel_masks[0]);
3869 replied |= stream_get_parameter_formats(query, reply,
3870 &in->supported_formats[0]);
3871 replied |= stream_get_parameter_rates(query, reply,
3872 &in->supported_sample_rates[0]);
3873 if (replied) {
3874 str = str_parms_to_str(reply);
3875 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003876 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003877 }
3878 str_parms_destroy(query);
3879 str_parms_destroy(reply);
3880 ALOGV("%s: exit: returns - %s", __func__, str);
3881 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003882}
3883
Eric Laurent51f3c662018-04-10 18:21:34 -07003884static int in_set_gain(struct audio_stream_in *stream, float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003885{
Eric Laurent51f3c662018-04-10 18:21:34 -07003886 struct stream_in *in = (struct stream_in *)stream;
3887 char mixer_ctl_name[128];
3888 struct mixer_ctl *ctl;
3889 int ctl_value;
3890
3891 ALOGV("%s: gain %f", __func__, gain);
3892
3893 if (stream == NULL)
3894 return -EINVAL;
3895
3896 /* in_set_gain() only used to silence MMAP capture for now */
3897 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
3898 return -ENOSYS;
3899
3900 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
3901
3902 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
3903 if (!ctl) {
3904 ALOGW("%s: Could not get ctl for mixer cmd - %s",
3905 __func__, mixer_ctl_name);
3906 return -ENOSYS;
3907 }
3908
3909 if (gain < RECORD_GAIN_MIN)
3910 gain = RECORD_GAIN_MIN;
3911 else if (gain > RECORD_GAIN_MAX)
3912 gain = RECORD_GAIN_MAX;
3913 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
3914
3915 mixer_ctl_set_value(ctl, 0, ctl_value);
3916 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003917}
3918
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003919static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3920{
3921 if (!stream || !parms)
3922 return;
3923
3924 struct stream_in *in = (struct stream_in *)stream;
3925 struct audio_device *adev = in->dev;
3926
3927 card_status_t status;
3928 int card;
3929 if (parse_snd_card_status(parms, &card, &status) < 0)
3930 return;
3931
3932 pthread_mutex_lock(&adev->lock);
3933 bool valid_cb = (card == adev->snd_card);
3934 pthread_mutex_unlock(&adev->lock);
3935
3936 if (!valid_cb)
3937 return;
3938
3939 lock_input_stream(in);
3940 if (in->card_status != status)
3941 in->card_status = status;
3942 pthread_mutex_unlock(&in->lock);
3943
3944 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3945 use_case_table[in->usecase],
3946 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3947
3948 // a better solution would be to report error back to AF and let
3949 // it put the stream to standby
3950 if (status == CARD_STATUS_OFFLINE)
3951 in_standby(&in->stream.common);
3952
3953 return;
3954}
3955
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003956static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3957 size_t bytes)
3958{
3959 struct stream_in *in = (struct stream_in *)stream;
3960 struct audio_device *adev = in->dev;
3961 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003962 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003963 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003964
Eric Laurenta1478072015-09-21 17:21:52 -07003965 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003966 const size_t frame_size = audio_stream_in_frame_size(stream);
3967 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003968
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003969 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003970 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003971 /* Read from sound trigger HAL */
3972 audio_extn_sound_trigger_read(in, buffer, bytes);
3973 pthread_mutex_unlock(&in->lock);
3974 return bytes;
3975 }
3976
Eric Laurent0e46adf2016-12-16 12:49:24 -08003977 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3978 ret = -ENOSYS;
3979 goto exit;
3980 }
3981
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003982 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003983 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003984 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003985 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003986 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003987 goto exit;
3988 }
3989 in->standby = 0;
3990 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003991
Andy Hungd13f0d32017-06-12 13:58:37 -07003992 // errors that occur here are read errors.
3993 error_code = ERROR_CODE_READ;
3994
Haynes Mathew George03c40102016-01-29 17:57:48 -08003995 //what's the duration requested by the client?
3996 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3997 in->config.rate;
3998 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003999
Haynes Mathew George03c40102016-01-29 17:57:48 -08004000 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004001 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08004002 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004003 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07004004 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004005 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004006 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004007 if (ret < 0) {
4008 ALOGE("Failed to read w/err %s", strerror(errno));
4009 ret = -errno;
4010 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004011 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4012 if (bytes % 4 == 0) {
4013 /* data from DSP comes in 24_8 format, convert it to 8_24 */
4014 int_buf_stream = buffer;
4015 for (size_t itt=0; itt < bytes/4 ; itt++) {
4016 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07004017 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004018 } else {
4019 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
4020 ret = -EINVAL;
4021 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07004022 }
4023 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004024 }
4025
Haynes Mathew George03c40102016-01-29 17:57:48 -08004026 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004027
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004028 /*
4029 * Instead of writing zeroes here, we could trust the hardware
4030 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004031 * 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 -08004032 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08004033 if (ret == 0 && adev->mic_muted &&
4034 !voice_is_in_call_rec_stream(in) &&
4035 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004036 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07004037 in->frames_muted += frames;
4038 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004039
4040exit:
4041 pthread_mutex_unlock(&in->lock);
4042
4043 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07004044 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004045 in_standby(&in->stream.common);
4046 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07004047 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08004048 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07004049 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08004050 }
4051 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07004052 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004053 }
4054 return bytes;
4055}
4056
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004057static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004058{
4059 return 0;
4060}
4061
Andy Hung6ebe5962016-01-15 17:46:57 -08004062static int in_get_capture_position(const struct audio_stream_in *stream,
4063 int64_t *frames, int64_t *time)
4064{
4065 if (stream == NULL || frames == NULL || time == NULL) {
4066 return -EINVAL;
4067 }
4068 struct stream_in *in = (struct stream_in *)stream;
4069 int ret = -ENOSYS;
4070
4071 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08004072 // note: ST sessions do not close the alsa pcm driver synchronously
4073 // on standby. Therefore, we may return an error even though the
4074 // pcm stream is still opened.
4075 if (in->standby) {
4076 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
4077 "%s stream in standby but pcm not NULL for non ST session", __func__);
4078 goto exit;
4079 }
Andy Hung6ebe5962016-01-15 17:46:57 -08004080 if (in->pcm) {
4081 struct timespec timestamp;
4082 unsigned int avail;
4083 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
4084 *frames = in->frames_read + avail;
4085 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
4086 ret = 0;
4087 }
4088 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08004089exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08004090 pthread_mutex_unlock(&in->lock);
4091 return ret;
4092}
4093
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004094static int add_remove_audio_effect(const struct audio_stream *stream,
4095 effect_handle_t effect,
4096 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004097{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004098 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004099 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004100 int status = 0;
4101 effect_descriptor_t desc;
4102
4103 status = (*effect)->get_descriptor(effect, &desc);
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004104 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
4105
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004106 if (status != 0)
4107 return status;
4108
Eric Laurenta1478072015-09-21 17:21:52 -07004109 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004110 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07004111 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07004112 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07004113 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004114 in->enable_aec != enable &&
4115 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
4116 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004117 if (!enable)
4118 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07004119 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
4120 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
4121 adev->enable_voicerx = enable;
4122 struct audio_usecase *usecase;
4123 struct listnode *node;
4124 list_for_each(node, &adev->usecase_list) {
4125 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07004126 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07004127 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05004128 }
4129 }
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004130 if (!in->standby
4131 && enable_disable_effect(in->dev, in, EFFECT_AEC, enable) == -ENOSYS)
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004132 select_devices(in->dev, in->usecase);
4133 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07004134 if (in->enable_ns != enable &&
4135 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
4136 in->enable_ns = enable;
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004137 if (!in->standby) {
4138 if (in->source != AUDIO_SOURCE_VOICE_COMMUNICATION
4139 || enable_disable_effect(in->dev, in, EFFECT_NS, enable) == -ENOSYS)
4140 select_devices(in->dev, in->usecase);
4141 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07004142 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004143 pthread_mutex_unlock(&in->dev->lock);
4144 pthread_mutex_unlock(&in->lock);
4145
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004146 return 0;
4147}
4148
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004149static int in_add_audio_effect(const struct audio_stream *stream,
4150 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004151{
Eric Laurent994a6932013-07-17 11:51:42 -07004152 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004153 return add_remove_audio_effect(stream, effect, true);
4154}
4155
4156static int in_remove_audio_effect(const struct audio_stream *stream,
4157 effect_handle_t effect)
4158{
Eric Laurent994a6932013-07-17 11:51:42 -07004159 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004160 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004161}
4162
Eric Laurent0e46adf2016-12-16 12:49:24 -08004163static int in_stop(const struct audio_stream_in* stream)
4164{
4165 struct stream_in *in = (struct stream_in *)stream;
4166 struct audio_device *adev = in->dev;
4167
4168 int ret = -ENOSYS;
4169 ALOGV("%s", __func__);
4170 pthread_mutex_lock(&adev->lock);
4171 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4172 in->capture_started && in->pcm != NULL) {
4173 pcm_stop(in->pcm);
4174 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08004175 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004176 }
4177 pthread_mutex_unlock(&adev->lock);
4178 return ret;
4179}
4180
4181static int in_start(const struct audio_stream_in* stream)
4182{
4183 struct stream_in *in = (struct stream_in *)stream;
4184 struct audio_device *adev = in->dev;
4185 int ret = -ENOSYS;
4186
4187 ALOGV("%s in %p", __func__, in);
4188 pthread_mutex_lock(&adev->lock);
4189 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4190 !in->capture_started && in->pcm != NULL) {
4191 if (!in->capture_started) {
4192 ret = start_input_stream(in);
4193 if (ret == 0) {
4194 in->capture_started = true;
4195 }
4196 }
4197 }
4198 pthread_mutex_unlock(&adev->lock);
4199 return ret;
4200}
4201
4202static int in_create_mmap_buffer(const struct audio_stream_in *stream,
4203 int32_t min_size_frames,
4204 struct audio_mmap_buffer_info *info)
4205{
4206 struct stream_in *in = (struct stream_in *)stream;
4207 struct audio_device *adev = in->dev;
4208 int ret = 0;
4209 unsigned int offset1;
4210 unsigned int frames1;
4211 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07004212 uint32_t mmap_size;
4213 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004214
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004215 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004216 pthread_mutex_lock(&adev->lock);
4217 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08004218
Eric Laurent0e46adf2016-12-16 12:49:24 -08004219 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004220 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004221 ret = -EINVAL;
4222 goto exit;
4223 }
4224 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08004225 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004226 ALOGV("%s in %p", __func__, in);
4227 ret = -ENOSYS;
4228 goto exit;
4229 }
4230 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
4231 if (in->pcm_device_id < 0) {
4232 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4233 __func__, in->pcm_device_id, in->usecase);
4234 ret = -EINVAL;
4235 goto exit;
4236 }
Phil Burkbc991042017-02-24 08:06:44 -08004237
4238 adjust_mmap_period_count(&in->config, min_size_frames);
4239
Eric Laurent0e46adf2016-12-16 12:49:24 -08004240 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4241 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
4242 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
4243 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
4244 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
4245 step = "open";
4246 ret = -ENODEV;
4247 goto exit;
4248 }
4249
4250 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
4251 if (ret < 0) {
4252 step = "begin";
4253 goto exit;
4254 }
4255 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07004256 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004257 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07004258 ret = platform_get_mmap_data_fd(adev->platform,
4259 in->pcm_device_id, 1 /*capture*/,
4260 &info->shared_memory_fd,
4261 &mmap_size);
4262 if (ret < 0) {
4263 // Fall back to non exclusive mode
4264 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
4265 } else {
4266 if (mmap_size < buffer_size) {
4267 step = "mmap";
4268 goto exit;
4269 }
4270 // FIXME: indicate exclusive mode support by returning a negative buffer size
4271 info->buffer_size_frames *= -1;
4272 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08004273
Haynes Mathew George96483a22017-03-28 14:52:47 -07004274 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004275
4276 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4277 if (ret < 0) {
4278 step = "commit";
4279 goto exit;
4280 }
4281
Phil Burkbc991042017-02-24 08:06:44 -08004282 in->standby = false;
4283 ret = 0;
4284
Eric Laurent0e46adf2016-12-16 12:49:24 -08004285 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4286 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004287
4288exit:
4289 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004290 if (in->pcm == NULL) {
4291 ALOGE("%s: %s - %d", __func__, step, ret);
4292 } else {
4293 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08004294 pcm_close(in->pcm);
4295 in->pcm = NULL;
4296 }
4297 }
4298 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004299 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004300 return ret;
4301}
4302
4303static int in_get_mmap_position(const struct audio_stream_in *stream,
4304 struct audio_mmap_position *position)
4305{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004306 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004307 struct stream_in *in = (struct stream_in *)stream;
4308 ALOGVV("%s", __func__);
4309 if (position == NULL) {
4310 return -EINVAL;
4311 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004312 lock_input_stream(in);
4313 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
4314 in->pcm == NULL) {
4315 ret = -ENOSYS;
4316 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004317 }
4318 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004319 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004320 if (ret < 0) {
4321 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004322 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004323 }
Andy Hungfc044e12017-03-20 09:24:22 -07004324 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004325exit:
4326 pthread_mutex_unlock(&in->lock);
4327 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004328}
4329
jiabin8962a4d2018-03-19 18:21:24 -07004330static int in_get_active_microphones(const struct audio_stream_in *stream,
4331 struct audio_microphone_characteristic_t *mic_array,
4332 size_t *mic_count) {
4333 struct stream_in *in = (struct stream_in *)stream;
4334 struct audio_device *adev = in->dev;
4335 ALOGVV("%s", __func__);
4336
4337 lock_input_stream(in);
4338 pthread_mutex_lock(&adev->lock);
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004339 int ret = platform_get_active_microphones(adev->platform,
jiabin8962a4d2018-03-19 18:21:24 -07004340 audio_channel_count_from_in_mask(in->channel_mask),
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004341 in->usecase, mic_array, mic_count);
jiabin8962a4d2018-03-19 18:21:24 -07004342 pthread_mutex_unlock(&adev->lock);
4343 pthread_mutex_unlock(&in->lock);
4344
4345 return ret;
4346}
4347
4348static int adev_get_microphones(const struct audio_hw_device *dev,
4349 struct audio_microphone_characteristic_t *mic_array,
4350 size_t *mic_count) {
4351 struct audio_device *adev = (struct audio_device *)dev;
4352 ALOGVV("%s", __func__);
4353
4354 pthread_mutex_lock(&adev->lock);
4355 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
4356 pthread_mutex_unlock(&adev->lock);
4357
4358 return ret;
4359}
Eric Laurent0e46adf2016-12-16 12:49:24 -08004360
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004361static int adev_open_output_stream(struct audio_hw_device *dev,
4362 audio_io_handle_t handle,
4363 audio_devices_t devices,
4364 audio_output_flags_t flags,
4365 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07004366 struct audio_stream_out **stream_out,
4367 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004368{
4369 struct audio_device *adev = (struct audio_device *)dev;
4370 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004371 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004372 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
4373 bool is_usb_dev = audio_is_usb_out_device(devices) &&
4374 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004375
Andy Hungd9653bd2017-08-01 19:31:39 -07004376 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
4377 return -ENOSYS;
4378 }
4379
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004380 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
4381 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004382 *stream_out = NULL;
4383 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4384
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004385 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
4386
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004387 if (devices == AUDIO_DEVICE_NONE)
4388 devices = AUDIO_DEVICE_OUT_SPEAKER;
4389
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004390 out->flags = flags;
4391 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004392 out->dev = adev;
Eric Laurentc4aef752013-09-12 17:45:53 -07004393 out->handle = handle;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004394 out->a2dp_compress_mute = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004395
4396 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004397 if ((is_hdmi || is_usb_dev) &&
4398 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
4399 (flags == AUDIO_OUTPUT_FLAG_NONE ||
4400 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Eric Laurentab805ee2018-03-30 12:20:38 -07004401 audio_format_t req_format = config->format;
4402 audio_channel_mask_t req_channel_mask = config->channel_mask;
4403 uint32_t req_sample_rate = config->sample_rate;
4404
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004405 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004406 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004407 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004408 if (config->sample_rate == 0)
4409 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Eric Laurentab805ee2018-03-30 12:20:38 -07004410 if (config->channel_mask == AUDIO_CHANNEL_NONE)
Haynes Mathew George569b7482017-05-08 14:44:27 -07004411 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
4412 if (config->format == AUDIO_FORMAT_DEFAULT)
4413 config->format = AUDIO_FORMAT_PCM_16_BIT;
4414 } else if (is_usb_dev) {
4415 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
4416 &config->format,
4417 &out->supported_formats[0],
4418 MAX_SUPPORTED_FORMATS,
4419 &config->channel_mask,
4420 &out->supported_channel_masks[0],
4421 MAX_SUPPORTED_CHANNEL_MASKS,
4422 &config->sample_rate,
4423 &out->supported_sample_rates[0],
4424 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004425 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004426 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004427 pthread_mutex_unlock(&adev->lock);
Eric Laurentab805ee2018-03-30 12:20:38 -07004428 if (ret != 0) {
4429 // For MMAP NO IRQ, allow conversions in ADSP
4430 if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
4431 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004432
Eric Laurentab805ee2018-03-30 12:20:38 -07004433 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
4434 config->sample_rate = req_sample_rate;
4435 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
4436 config->channel_mask = req_channel_mask;
4437 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
4438 config->format = req_format;
4439 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004440
Haynes Mathew George569b7482017-05-08 14:44:27 -07004441 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004442 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004443 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004444 if (is_hdmi) {
4445 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4446 out->config = pcm_config_hdmi_multi;
4447 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
4448 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4449 out->config = pcm_config_mmap_playback;
4450 out->stream.start = out_start;
4451 out->stream.stop = out_stop;
4452 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4453 out->stream.get_mmap_position = out_get_mmap_position;
4454 } else {
4455 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4456 out->config = pcm_config_hifi;
4457 }
4458
4459 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004460 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004461 if (is_hdmi) {
4462 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
4463 audio_bytes_per_sample(out->format));
4464 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004465 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004466 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07004467 pthread_mutex_lock(&adev->lock);
4468 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4469 pthread_mutex_unlock(&adev->lock);
4470
4471 // reject offload during card offline to allow
4472 // fallback to s/w paths
4473 if (offline) {
4474 ret = -ENODEV;
4475 goto error_open;
4476 }
4477
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004478 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4479 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4480 ALOGE("%s: Unsupported Offload information", __func__);
4481 ret = -EINVAL;
4482 goto error_open;
4483 }
4484 if (!is_supported_format(config->offload_info.format)) {
4485 ALOGE("%s: Unsupported audio format", __func__);
4486 ret = -EINVAL;
4487 goto error_open;
4488 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004489 out->sample_rate = config->offload_info.sample_rate;
4490 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
4491 out->channel_mask = config->offload_info.channel_mask;
4492 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
4493 out->channel_mask = config->channel_mask;
4494 else
4495 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4496
4497 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004498
4499 out->compr_config.codec = (struct snd_codec *)
4500 calloc(1, sizeof(struct snd_codec));
4501
4502 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004503
4504 out->stream.set_callback = out_set_callback;
4505 out->stream.pause = out_pause;
4506 out->stream.resume = out_resume;
4507 out->stream.drain = out_drain;
4508 out->stream.flush = out_flush;
4509
4510 out->compr_config.codec->id =
4511 get_snd_codec_id(config->offload_info.format);
4512 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
4513 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004514 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004515 out->compr_config.codec->bit_rate =
4516 config->offload_info.bit_rate;
4517 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004518 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004519 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
4520
4521 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4522 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004523
4524 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004525 create_offload_callback_thread(out);
4526 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4527 __func__, config->offload_info.version,
4528 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02004529 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4530 switch (config->sample_rate) {
4531 case 0:
4532 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4533 break;
4534 case 8000:
4535 case 16000:
4536 case 48000:
4537 out->sample_rate = config->sample_rate;
4538 break;
4539 default:
4540 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
4541 config->sample_rate);
4542 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4543 ret = -EINVAL;
4544 goto error_open;
4545 }
4546 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4547 switch (config->channel_mask) {
4548 case AUDIO_CHANNEL_NONE:
4549 case AUDIO_CHANNEL_OUT_STEREO:
4550 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4551 break;
4552 default:
4553 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
4554 config->channel_mask);
4555 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4556 ret = -EINVAL;
4557 goto error_open;
4558 }
4559 switch (config->format) {
4560 case AUDIO_FORMAT_DEFAULT:
4561 case AUDIO_FORMAT_PCM_16_BIT:
4562 out->format = AUDIO_FORMAT_PCM_16_BIT;
4563 break;
4564 default:
4565 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
4566 config->format);
4567 config->format = AUDIO_FORMAT_PCM_16_BIT;
4568 ret = -EINVAL;
4569 goto error_open;
4570 }
4571
4572 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004573 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004574 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004575 case 0:
4576 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
4577 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07004578 case 8000:
4579 case 16000:
4580 case 48000:
4581 out->sample_rate = config->sample_rate;
4582 break;
4583 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004584 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
4585 config->sample_rate);
4586 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4587 ret = -EINVAL;
4588 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004589 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004590 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4591 switch (config->channel_mask) {
4592 case AUDIO_CHANNEL_NONE:
4593 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4594 break;
4595 case AUDIO_CHANNEL_OUT_STEREO:
4596 out->channel_mask = config->channel_mask;
4597 break;
4598 default:
4599 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
4600 config->channel_mask);
4601 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4602 ret = -EINVAL;
4603 break;
4604 }
4605 switch (config->format) {
4606 case AUDIO_FORMAT_DEFAULT:
4607 out->format = AUDIO_FORMAT_PCM_16_BIT;
4608 break;
4609 case AUDIO_FORMAT_PCM_16_BIT:
4610 out->format = config->format;
4611 break;
4612 default:
4613 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
4614 config->format);
4615 config->format = AUDIO_FORMAT_PCM_16_BIT;
4616 ret = -EINVAL;
4617 break;
4618 }
4619 if (ret != 0)
4620 goto error_open;
4621
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004622 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4623 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004624 out->config.rate = out->sample_rate;
4625 out->config.channels =
4626 audio_channel_count_from_out_mask(out->channel_mask);
4627 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004628 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004629 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
4630 switch (config->sample_rate) {
4631 case 0:
4632 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4633 break;
4634 case 8000:
4635 case 16000:
4636 case 32000:
4637 case 48000:
4638 out->sample_rate = config->sample_rate;
4639 break;
4640 default:
4641 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
4642 config->sample_rate);
4643 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4644 ret = -EINVAL;
4645 break;
4646 }
Eric Laurentad2dde92017-09-20 18:27:31 -07004647 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004648 switch (config->channel_mask) {
4649 case AUDIO_CHANNEL_NONE:
4650 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4651 break;
4652 case AUDIO_CHANNEL_OUT_STEREO:
4653 out->channel_mask = config->channel_mask;
4654 break;
4655 default:
4656 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
4657 config->channel_mask);
4658 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4659 ret = -EINVAL;
4660 break;
4661 }
4662 switch (config->format) {
4663 case AUDIO_FORMAT_DEFAULT:
4664 out->format = AUDIO_FORMAT_PCM_16_BIT;
4665 break;
4666 case AUDIO_FORMAT_PCM_16_BIT:
4667 out->format = config->format;
4668 break;
4669 default:
4670 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
4671 config->format);
4672 config->format = AUDIO_FORMAT_PCM_16_BIT;
4673 ret = -EINVAL;
4674 break;
4675 }
4676 if (ret != 0)
4677 goto error_open;
4678
vivek mehtaa68fea62017-06-08 19:04:02 -07004679 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07004680 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4681 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004682 out->config.rate = out->sample_rate;
4683 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07004684 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004685 out->sample_rate,
4686 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07004687 out->config.channels,
4688 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004689 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07004690 out->config.period_size = buffer_size / frame_size;
4691 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
4692 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004693 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004694 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07004695 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4696 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004697 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07004698 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
4699 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004700 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07004701 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004702 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004703 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004704 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004705 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4706 out->config = pcm_config_mmap_playback;
4707 out->stream.start = out_start;
4708 out->stream.stop = out_stop;
4709 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4710 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004711 } else {
4712 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4713 out->config = pcm_config_low_latency;
4714 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004715
4716 if (config->sample_rate == 0) {
4717 out->sample_rate = out->config.rate;
4718 } else {
4719 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004720 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004721 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
4722 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
4723 } else {
4724 out->channel_mask = config->channel_mask;
4725 }
4726 if (config->format == AUDIO_FORMAT_DEFAULT)
4727 out->format = audio_format_from_pcm_format(out->config.format);
4728 else if (!audio_is_linear_pcm(config->format)) {
4729 config->format = AUDIO_FORMAT_PCM_16_BIT;
4730 ret = -EINVAL;
4731 goto error_open;
4732 } else {
4733 out->format = config->format;
4734 }
4735
4736 out->config.rate = out->sample_rate;
4737 out->config.channels =
4738 audio_channel_count_from_out_mask(out->channel_mask);
4739 if (out->format != audio_format_from_pcm_format(out->config.format)) {
4740 out->config.format = pcm_format_from_audio_format(out->format);
4741 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004742 }
Kevin Rocard50eff892017-05-02 16:52:05 -07004743
4744 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
4745 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004746 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004747 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
4748 __func__, config->sample_rate, config->format, config->channel_mask);
4749 config->sample_rate = out->sample_rate;
4750 config->format = out->format;
4751 config->channel_mask = out->channel_mask;
4752 ret = -EINVAL;
4753 goto error_open;
4754 }
4755
Andy Hung6fcba9c2014-03-18 11:53:32 -07004756 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
4757 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004758
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004759 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004760 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004761 adev->primary_output = out;
4762 else {
4763 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004764 ret = -EEXIST;
4765 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004766 }
4767 }
4768
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004769 /* Check if this usecase is already existing */
4770 pthread_mutex_lock(&adev->lock);
4771 if (get_usecase_from_list(adev, out->usecase) != NULL) {
4772 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004773 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004774 ret = -EEXIST;
4775 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004776 }
4777 pthread_mutex_unlock(&adev->lock);
4778
4779 out->stream.common.get_sample_rate = out_get_sample_rate;
4780 out->stream.common.set_sample_rate = out_set_sample_rate;
4781 out->stream.common.get_buffer_size = out_get_buffer_size;
4782 out->stream.common.get_channels = out_get_channels;
4783 out->stream.common.get_format = out_get_format;
4784 out->stream.common.set_format = out_set_format;
4785 out->stream.common.standby = out_standby;
4786 out->stream.common.dump = out_dump;
4787 out->stream.common.set_parameters = out_set_parameters;
4788 out->stream.common.get_parameters = out_get_parameters;
4789 out->stream.common.add_audio_effect = out_add_audio_effect;
4790 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4791 out->stream.get_latency = out_get_latency;
4792 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004793#ifdef NO_AUDIO_OUT
4794 out->stream.write = out_write_for_no_output;
4795#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004796 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004797#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004798 out->stream.get_render_position = out_get_render_position;
4799 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004800 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004801
Eric Laurent0e46adf2016-12-16 12:49:24 -08004802 if (out->realtime)
4803 out->af_period_multiplier = af_period_multiplier;
4804 else
4805 out->af_period_multiplier = 1;
4806
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004807 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004808 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004809 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004810
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004811 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004812 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004813 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4814
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004815 config->format = out->stream.common.get_format(&out->stream.common);
4816 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4817 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4818
Kevin Rocarda325aa22018-04-03 09:15:52 -07004819 register_format(out->format, out->supported_formats);
4820 register_channel_mask(out->channel_mask, out->supported_channel_masks);
4821 register_sample_rate(out->sample_rate, out->supported_sample_rates);
4822
Andy Hunga452b0a2017-03-15 14:51:15 -07004823 out->error_log = error_log_create(
4824 ERROR_LOG_ENTRIES,
4825 1000000000 /* aggregate consecutive identical errors within one second in ns */);
4826
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004827 /*
4828 By locking output stream before registering, we allow the callback
4829 to update stream's state only after stream's initial state is set to
4830 adev state.
4831 */
4832 lock_output_stream(out);
4833 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4834 pthread_mutex_lock(&adev->lock);
4835 out->card_status = adev->card_status;
4836 pthread_mutex_unlock(&adev->lock);
4837 pthread_mutex_unlock(&out->lock);
4838
vivek mehta4a824772017-06-08 19:05:49 -07004839 stream_app_type_cfg_init(&out->app_type_cfg);
4840
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004841 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004842
Eric Laurent994a6932013-07-17 11:51:42 -07004843 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004844 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004845
4846error_open:
4847 free(out);
4848 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07004849 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004850 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004851}
4852
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004853static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004854 struct audio_stream_out *stream)
4855{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004856 struct stream_out *out = (struct stream_out *)stream;
4857 struct audio_device *adev = out->dev;
4858
Eric Laurent994a6932013-07-17 11:51:42 -07004859 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004860
4861 // must deregister from sndmonitor first to prevent races
4862 // between the callback and close_stream
4863 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004864 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004865 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
4866 destroy_offload_callback_thread(out);
4867
4868 if (out->compr_config.codec != NULL)
4869 free(out->compr_config.codec);
4870 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004871
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004872 out->a2dp_compress_mute = false;
4873
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004874 if (adev->voice_tx_output == out)
4875 adev->voice_tx_output = NULL;
4876
Andy Hunga452b0a2017-03-15 14:51:15 -07004877 error_log_destroy(out->error_log);
4878 out->error_log = NULL;
4879
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004880 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004881 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004882 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004883 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004884 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004885}
4886
4887static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4888{
4889 struct audio_device *adev = (struct audio_device *)dev;
4890 struct str_parms *parms;
4891 char *str;
4892 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004893 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004894 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07004895 int status = 0;
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004896 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004897
Joe Onorato188b6222016-03-01 11:02:27 -08004898 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004899
4900 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004901
4902 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004903 status = voice_set_parameters(adev, parms);
4904 if (status != 0) {
4905 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004906 }
4907
4908 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4909 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07004910 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004911 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4912 adev->bluetooth_nrec = true;
4913 else
4914 adev->bluetooth_nrec = false;
4915 }
4916
4917 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4918 if (ret >= 0) {
4919 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4920 adev->screen_off = false;
4921 else
4922 adev->screen_off = true;
4923 }
4924
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004925 ret = str_parms_get_int(parms, "rotation", &val);
4926 if (ret >= 0) {
4927 bool reverse_speakers = false;
Eric Laurent5f4ca952018-10-19 17:33:43 -07004928 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004929 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004930 // FIXME: note that the code below assumes that the speakers are in the correct placement
4931 // relative to the user when the device is rotated 90deg from its default rotation. This
4932 // assumption is device-specific, not platform-specific like this code.
4933 case 270:
4934 reverse_speakers = true;
Eric Laurent5f4ca952018-10-19 17:33:43 -07004935 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004936 break;
4937 case 0:
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004938 case 180:
Eric Laurent5f4ca952018-10-19 17:33:43 -07004939 camera_rotation = CAMERA_ROTATION_PORTRAIT;
4940 break;
4941 case 90:
4942 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004943 break;
4944 default:
4945 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07004946 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004947 }
Eric Laurent03f09432014-03-25 18:09:11 -07004948 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004949 // check and set swap
4950 // - check if orientation changed and speaker active
4951 // - set rotation and cache the rotation value
Eric Laurent5f4ca952018-10-19 17:33:43 -07004952 adev->camera_orientation =
4953 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
4954#ifndef MAXXAUDIO_QDSP_ENABLED
vivek mehtae59cfb22017-06-16 15:57:11 -07004955 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Eric Laurent5f4ca952018-10-19 17:33:43 -07004956#endif
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004957 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004958 }
4959
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004960 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4961 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004962 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004963 }
4964
David Linee3fe402017-03-13 10:00:42 -07004965 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4966 if (ret >= 0) {
4967 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004968 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004969 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4970 if (ret >= 0) {
4971 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004972 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004973 }
Eric Laurent99dab492017-06-17 15:19:08 -07004974 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004975 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4976 if (ret >= 0) {
4977 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004978 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004979 }
4980 }
4981 }
4982
4983 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4984 if (ret >= 0) {
4985 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004986 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004987 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4988 if (ret >= 0) {
4989 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004990 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004991 }
Eric Laurent99dab492017-06-17 15:19:08 -07004992 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004993 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4994 if (ret >= 0) {
4995 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004996 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004997 }
4998 }
4999 }
5000
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08005001 audio_extn_hfp_set_parameters(adev, parms);
jasmine cha270b7762018-03-30 15:41:33 +08005002 audio_extn_ma_set_parameters(adev, parms);
5003
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005004 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
5005 if (status >= 0 && a2dp_reconfig) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005006 struct audio_usecase *usecase;
5007 struct listnode *node;
5008 list_for_each(node, &adev->usecase_list) {
5009 usecase = node_to_item(node, struct audio_usecase, list);
5010 if ((usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005011 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005012 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
5013
5014 pthread_mutex_unlock(&adev->lock);
5015 lock_output_stream(usecase->stream.out);
5016 pthread_mutex_lock(&adev->lock);
5017 audio_extn_a2dp_set_handoff_mode(true);
5018 // force device switch to reconfigure encoder
5019 select_devices(adev, usecase->id);
5020 audio_extn_a2dp_set_handoff_mode(false);
5021 pthread_mutex_unlock(&usecase->stream.out->lock);
5022 break;
5023 }
5024 }
5025 }
5026
Eric Laurent5f4ca952018-10-19 17:33:43 -07005027 //FIXME: to be replaced by proper video capture properties API
5028 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
5029 if (ret >= 0) {
5030 int camera_facing = CAMERA_FACING_BACK;
5031 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
5032 camera_facing = CAMERA_FACING_FRONT;
5033 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
5034 camera_facing = CAMERA_FACING_BACK;
5035 else {
5036 ALOGW("%s: invalid camera facing value: %s", __func__, value);
5037 goto done;
5038 }
5039 adev->camera_orientation =
5040 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
5041 struct audio_usecase *usecase;
5042 struct listnode *node;
5043 list_for_each(node, &adev->usecase_list) {
5044 usecase = node_to_item(node, struct audio_usecase, list);
5045 struct stream_in *in = usecase->stream.in;
5046 if (usecase->type == PCM_CAPTURE && in != NULL &&
5047 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
5048 select_devices(adev, in->usecase);
5049 }
5050 }
5051 }
5052
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005053done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005054 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005055 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07005056 ALOGV("%s: exit with code(%d)", __func__, status);
5057 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005058}
5059
5060static char* adev_get_parameters(const struct audio_hw_device *dev,
5061 const char *keys)
5062{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005063 struct audio_device *adev = (struct audio_device *)dev;
5064 struct str_parms *reply = str_parms_create();
5065 struct str_parms *query = str_parms_create_str(keys);
5066 char *str;
5067
5068 pthread_mutex_lock(&adev->lock);
5069
5070 voice_get_parameters(adev, query, reply);
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005071 audio_extn_a2dp_get_parameters(query, reply);
5072
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005073 str = str_parms_to_str(reply);
5074 str_parms_destroy(query);
5075 str_parms_destroy(reply);
5076
5077 pthread_mutex_unlock(&adev->lock);
5078 ALOGV("%s: exit: returns - %s", __func__, str);
5079 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005080}
5081
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005082static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005083{
5084 return 0;
5085}
5086
Haynes Mathew George5191a852013-09-11 14:19:36 -07005087static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
5088{
5089 int ret;
5090 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005091
Eric Laurent4cc4ce12014-09-10 13:21:01 -05005092 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
5093
Haynes Mathew George5191a852013-09-11 14:19:36 -07005094 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005095 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07005096 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005097
Haynes Mathew George5191a852013-09-11 14:19:36 -07005098 return ret;
5099}
5100
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005101static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005102{
5103 return -ENOSYS;
5104}
5105
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005106static int adev_get_master_volume(struct audio_hw_device *dev __unused,
5107 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005108{
5109 return -ENOSYS;
5110}
5111
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005112static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005113{
5114 return -ENOSYS;
5115}
5116
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005117static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005118{
5119 return -ENOSYS;
5120}
5121
5122static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
5123{
5124 struct audio_device *adev = (struct audio_device *)dev;
5125
5126 pthread_mutex_lock(&adev->lock);
5127 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07005128 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005129 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07005130 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
5131 voice_is_in_call(adev)) {
5132 voice_stop_call(adev);
5133 adev->current_call_output = NULL;
5134 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005135 }
5136 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05005137
5138 audio_extn_extspk_set_mode(adev->extspk, mode);
5139
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005140 return 0;
5141}
5142
5143static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
5144{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005145 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005146 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005147
Eric Laurent2bafff12016-03-17 12:17:23 -07005148 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005149 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005150 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
5151 ret = audio_extn_hfp_set_mic_mute(adev, state);
5152 } else {
5153 ret = voice_set_mic_mute(adev, state);
5154 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07005155 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00005156 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005157
5158 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005159}
5160
5161static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
5162{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005163 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005164 return 0;
5165}
5166
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005167static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005168 const struct audio_config *config)
5169{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07005170 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005171
Eric Laurent74b55762017-07-09 17:04:53 -07005172 /* Don't know if USB HIFI in this context so use true to be conservative */
5173 if (check_input_parameters(config->sample_rate, config->format, channel_count,
5174 true /*is_usb_hifi */) != 0)
5175 return 0;
5176
vivek mehtaa68fea62017-06-08 19:04:02 -07005177 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5178 config->sample_rate, config->format,
5179 channel_count,
5180 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005181}
5182
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005183static bool adev_input_allow_hifi_record(struct audio_device *adev,
5184 audio_devices_t devices,
5185 audio_input_flags_t flags,
5186 audio_source_t source) {
5187 const bool allowed = true;
5188
5189 if (!audio_is_usb_in_device(devices))
5190 return !allowed;
5191
5192 switch (flags) {
5193 case AUDIO_INPUT_FLAG_NONE:
5194 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
5195 break;
5196 default:
5197 return !allowed;
5198 }
5199
5200 switch (source) {
5201 case AUDIO_SOURCE_DEFAULT:
5202 case AUDIO_SOURCE_MIC:
5203 case AUDIO_SOURCE_UNPROCESSED:
5204 break;
5205 default:
5206 return !allowed;
5207 }
5208
5209 switch (adev->mode) {
5210 case 0:
5211 break;
5212 default:
5213 return !allowed;
5214 }
5215
5216 return allowed;
5217}
5218
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005219static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005220 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005221 audio_devices_t devices,
5222 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005223 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07005224 audio_input_flags_t flags,
5225 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05005226 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005227{
5228 struct audio_device *adev = (struct audio_device *)dev;
5229 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005230 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07005231 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005232 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005233 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005234 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
5235 devices,
5236 flags,
5237 source);
Andy Hung88ce1d92018-10-29 18:31:12 -07005238 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
5239 " sample_rate %u, channel_mask %#x, format %#x",
5240 __func__, flags, is_usb_dev, may_use_hifi_record,
5241 config->sample_rate, config->channel_mask, config->format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005242 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005243
Andy Hungd9653bd2017-08-01 19:31:39 -07005244 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
5245 return -ENOSYS;
5246 }
5247
Eric Laurent74b55762017-07-09 17:04:53 -07005248 if (!(is_usb_dev && may_use_hifi_record)) {
5249 if (config->sample_rate == 0)
5250 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
5251 if (config->channel_mask == AUDIO_CHANNEL_NONE)
5252 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5253 if (config->format == AUDIO_FORMAT_DEFAULT)
5254 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005255
Eric Laurent74b55762017-07-09 17:04:53 -07005256 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
5257
5258 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
5259 return -EINVAL;
5260 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005261
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005262 if (audio_extn_tfa_98xx_is_supported() &&
5263 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005264 return -EINVAL;
5265
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005266 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
5267
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005268 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005269 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005270
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005271 in->stream.common.get_sample_rate = in_get_sample_rate;
5272 in->stream.common.set_sample_rate = in_set_sample_rate;
5273 in->stream.common.get_buffer_size = in_get_buffer_size;
5274 in->stream.common.get_channels = in_get_channels;
5275 in->stream.common.get_format = in_get_format;
5276 in->stream.common.set_format = in_set_format;
5277 in->stream.common.standby = in_standby;
5278 in->stream.common.dump = in_dump;
5279 in->stream.common.set_parameters = in_set_parameters;
5280 in->stream.common.get_parameters = in_get_parameters;
5281 in->stream.common.add_audio_effect = in_add_audio_effect;
5282 in->stream.common.remove_audio_effect = in_remove_audio_effect;
5283 in->stream.set_gain = in_set_gain;
5284 in->stream.read = in_read;
5285 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08005286 in->stream.get_capture_position = in_get_capture_position;
jiabin8962a4d2018-03-19 18:21:24 -07005287 in->stream.get_active_microphones = in_get_active_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005288
5289 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005290 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005291 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005292 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005293 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005294 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005295
Andy Hung88ce1d92018-10-29 18:31:12 -07005296 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Arun Mirpuriba2749a2018-04-17 14:32:24 -07005297 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
5298 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
5299 /* Force channel config requested to mono if incall
5300 record is being requested for only uplink/downlink */
5301 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
5302 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5303 ret = -EINVAL;
5304 goto err_open;
5305 }
5306 }
5307
Haynes Mathew George569b7482017-05-08 14:44:27 -07005308 if (is_usb_dev && may_use_hifi_record) {
5309 /* HiFi record selects an appropriate format, channel, rate combo
5310 depending on sink capabilities*/
5311 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
5312 &config->format,
5313 &in->supported_formats[0],
5314 MAX_SUPPORTED_FORMATS,
5315 &config->channel_mask,
5316 &in->supported_channel_masks[0],
5317 MAX_SUPPORTED_CHANNEL_MASKS,
5318 &config->sample_rate,
5319 &in->supported_sample_rates[0],
5320 MAX_SUPPORTED_SAMPLE_RATES);
5321 if (ret != 0) {
5322 ret = -EINVAL;
5323 goto err_open;
5324 }
Eric Laurent74b55762017-07-09 17:04:53 -07005325 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005326 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07005327 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07005328 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
5329 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
5330 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5331 bool ret_error = false;
5332 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5333 from HAL is 8_24
5334 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5335 8_24 return error indicating supported format is 8_24
5336 *> In case of any other source requesting 24 bit or float return error
5337 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07005338
vivek mehta57ff9b52016-04-28 14:13:08 -07005339 on error flinger will retry with supported format passed
5340 */
juyuchenbe5c67e2018-08-29 17:19:20 +08005341 if (!is_supported_24bits_audiosource(source)) {
vivek mehta57ff9b52016-04-28 14:13:08 -07005342 config->format = AUDIO_FORMAT_PCM_16_BIT;
5343 ret_error = true;
5344 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
5345 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
5346 ret_error = true;
5347 }
5348
5349 if (ret_error) {
5350 ret = -EINVAL;
5351 goto err_open;
5352 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005353 }
5354
vivek mehta57ff9b52016-04-28 14:13:08 -07005355 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07005356 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07005357
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005358 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005359 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
5360 if (config->sample_rate == 0)
5361 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5362 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5363 config->sample_rate != 8000) {
5364 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5365 ret = -EINVAL;
5366 goto err_open;
5367 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005368
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005369 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5370 config->format = AUDIO_FORMAT_PCM_16_BIT;
5371 ret = -EINVAL;
5372 goto err_open;
5373 }
5374
5375 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5376 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07005377 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005378 } else if (is_usb_dev && may_use_hifi_record) {
5379 in->usecase = USECASE_AUDIO_RECORD_HIFI;
5380 in->config = pcm_config_audio_capture;
5381 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005382 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5383 config->sample_rate,
5384 config->format,
5385 channel_count,
5386 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005387 in->config.period_size = buffer_size / frame_size;
5388 in->config.rate = config->sample_rate;
5389 in->af_period_multiplier = 1;
5390 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005391 } else {
5392 in->usecase = USECASE_AUDIO_RECORD;
5393 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08005394 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005395 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07005396#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005397 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07005398#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08005399 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005400 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08005401 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005402 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005403 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5404 config->sample_rate,
5405 config->format,
5406 channel_count,
5407 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005408 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005409 in->config.rate = config->sample_rate;
5410 in->af_period_multiplier = 1;
5411 } else {
5412 // period size is left untouched for rt mode playback
5413 in->config = pcm_config_audio_capture_rt;
5414 in->af_period_multiplier = af_period_multiplier;
5415 }
5416 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
5417 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005418 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08005419 in->usecase = USECASE_AUDIO_RECORD_MMAP;
5420 in->config = pcm_config_mmap_capture;
5421 in->stream.start = in_start;
5422 in->stream.stop = in_stop;
5423 in->stream.create_mmap_buffer = in_create_mmap_buffer;
5424 in->stream.get_mmap_position = in_get_mmap_position;
5425 in->af_period_multiplier = 1;
5426 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07005427 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07005428 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07005429 (config->sample_rate == 8000 ||
5430 config->sample_rate == 16000 ||
5431 config->sample_rate == 32000 ||
5432 config->sample_rate == 48000) &&
5433 channel_count == 1) {
5434 in->usecase = USECASE_AUDIO_RECORD_VOIP;
5435 in->config = pcm_config_audio_capture;
5436 frame_size = audio_stream_in_frame_size(&in->stream);
5437 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
5438 config->sample_rate,
5439 config->format,
5440 channel_count, false /*is_low_latency*/);
5441 in->config.period_size = buffer_size / frame_size;
5442 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
5443 in->config.rate = config->sample_rate;
5444 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005445 } else {
5446 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005447 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005448 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5449 config->sample_rate,
5450 config->format,
5451 channel_count,
5452 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005453 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005454 in->config.rate = config->sample_rate;
5455 in->af_period_multiplier = 1;
5456 }
5457 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
5458 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005459 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08005460
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005461 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07005462 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005463
Kevin Rocarda325aa22018-04-03 09:15:52 -07005464
5465 register_format(in->format, in->supported_formats);
5466 register_channel_mask(in->channel_mask, in->supported_channel_masks);
5467 register_sample_rate(in->sample_rate, in->supported_sample_rates);
5468
Andy Hungd13f0d32017-06-12 13:58:37 -07005469 in->error_log = error_log_create(
5470 ERROR_LOG_ENTRIES,
5471 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
5472
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005473 /* This stream could be for sound trigger lab,
5474 get sound trigger pcm if present */
5475 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005476
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005477 lock_input_stream(in);
5478 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5479 pthread_mutex_lock(&adev->lock);
5480 in->card_status = adev->card_status;
5481 pthread_mutex_unlock(&adev->lock);
5482 pthread_mutex_unlock(&in->lock);
5483
vivek mehta4a824772017-06-08 19:05:49 -07005484 stream_app_type_cfg_init(&in->app_type_cfg);
5485
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005486 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005487 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005488 return 0;
5489
5490err_open:
5491 free(in);
5492 *stream_in = NULL;
5493 return ret;
5494}
5495
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005496static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005497 struct audio_stream_in *stream)
5498{
Andy Hungd13f0d32017-06-12 13:58:37 -07005499 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005500 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005501
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005502 // must deregister from sndmonitor first to prevent races
5503 // between the callback and close_stream
5504 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005505 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07005506
5507 error_log_destroy(in->error_log);
5508 in->error_log = NULL;
5509
Andy Hung0dbb52b2017-08-09 13:51:38 -07005510 pthread_mutex_destroy(&in->pre_lock);
5511 pthread_mutex_destroy(&in->lock);
5512
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005513 free(stream);
5514
5515 return;
5516}
5517
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005518static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005519{
5520 return 0;
5521}
5522
Andy Hung31aca912014-03-20 17:14:59 -07005523/* verifies input and output devices and their capabilities.
5524 *
5525 * This verification is required when enabling extended bit-depth or
5526 * sampling rates, as not all qcom products support it.
5527 *
5528 * Suitable for calling only on initialization such as adev_open().
5529 * It fills the audio_device use_case_table[] array.
5530 *
5531 * Has a side-effect that it needs to configure audio routing / devices
5532 * in order to power up the devices and read the device parameters.
5533 * It does not acquire any hw device lock. Should restore the devices
5534 * back to "normal state" upon completion.
5535 */
5536static int adev_verify_devices(struct audio_device *adev)
5537{
5538 /* enumeration is a bit difficult because one really wants to pull
5539 * the use_case, device id, etc from the hidden pcm_device_table[].
5540 * In this case there are the following use cases and device ids.
5541 *
5542 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
5543 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005544 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07005545 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
5546 * [USECASE_AUDIO_RECORD] = {0, 0},
5547 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
5548 * [USECASE_VOICE_CALL] = {2, 2},
5549 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005550 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07005551 * USECASE_VOICE_CALL omitted, but possible for either input or output.
5552 */
5553
5554 /* should be the usecases enabled in adev_open_input_stream() */
5555 static const int test_in_usecases[] = {
5556 USECASE_AUDIO_RECORD,
5557 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
5558 };
5559 /* should be the usecases enabled in adev_open_output_stream()*/
5560 static const int test_out_usecases[] = {
5561 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
5562 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
5563 };
5564 static const usecase_type_t usecase_type_by_dir[] = {
5565 PCM_PLAYBACK,
5566 PCM_CAPTURE,
5567 };
5568 static const unsigned flags_by_dir[] = {
5569 PCM_OUT,
5570 PCM_IN,
5571 };
5572
5573 size_t i;
5574 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005575 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07005576 char info[512]; /* for possible debug info */
5577
5578 for (dir = 0; dir < 2; ++dir) {
5579 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
5580 const unsigned flags_dir = flags_by_dir[dir];
5581 const size_t testsize =
5582 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
5583 const int *testcases =
5584 dir ? test_in_usecases : test_out_usecases;
5585 const audio_devices_t audio_device =
5586 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
5587
5588 for (i = 0; i < testsize; ++i) {
5589 const audio_usecase_t audio_usecase = testcases[i];
5590 int device_id;
5591 snd_device_t snd_device;
5592 struct pcm_params **pparams;
5593 struct stream_out out;
5594 struct stream_in in;
5595 struct audio_usecase uc_info;
5596 int retval;
5597
5598 pparams = &adev->use_case_table[audio_usecase];
5599 pcm_params_free(*pparams); /* can accept null input */
5600 *pparams = NULL;
5601
5602 /* find the device ID for the use case (signed, for error) */
5603 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
5604 if (device_id < 0)
5605 continue;
5606
5607 /* prepare structures for device probing */
5608 memset(&uc_info, 0, sizeof(uc_info));
5609 uc_info.id = audio_usecase;
5610 uc_info.type = usecase_type;
5611 if (dir) {
Andy Hung31aca912014-03-20 17:14:59 -07005612 memset(&in, 0, sizeof(in));
5613 in.device = audio_device;
5614 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
5615 uc_info.stream.in = &in;
Andy Hung31aca912014-03-20 17:14:59 -07005616 }
5617 memset(&out, 0, sizeof(out));
5618 out.devices = audio_device; /* only field needed in select_devices */
5619 uc_info.stream.out = &out;
5620 uc_info.devices = audio_device;
5621 uc_info.in_snd_device = SND_DEVICE_NONE;
5622 uc_info.out_snd_device = SND_DEVICE_NONE;
5623 list_add_tail(&adev->usecase_list, &uc_info.list);
5624
5625 /* select device - similar to start_(in/out)put_stream() */
5626 retval = select_devices(adev, audio_usecase);
5627 if (retval >= 0) {
5628 *pparams = pcm_params_get(card_id, device_id, flags_dir);
5629#if LOG_NDEBUG == 0
5630 if (*pparams) {
5631 ALOGV("%s: (%s) card %d device %d", __func__,
5632 dir ? "input" : "output", card_id, device_id);
5633 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07005634 } else {
5635 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
5636 }
5637#endif
5638 }
5639
5640 /* deselect device - similar to stop_(in/out)put_stream() */
5641 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07005642 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07005643 /* 2. Disable the rx device */
5644 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07005645 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07005646 list_remove(&uc_info.list);
5647 }
5648 }
Andy Hung31aca912014-03-20 17:14:59 -07005649 return 0;
5650}
5651
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005652static int adev_close(hw_device_t *device)
5653{
Andy Hung31aca912014-03-20 17:14:59 -07005654 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005655 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005656
5657 if (!adev)
5658 return 0;
5659
5660 pthread_mutex_lock(&adev_init_lock);
5661
5662 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005663 audio_extn_snd_mon_unregister_listener(adev);
5664 audio_extn_tfa_98xx_deinit();
jasmine cha270b7762018-03-30 15:41:33 +08005665 audio_extn_ma_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005666 audio_route_free(adev->audio_route);
5667 free(adev->snd_dev_ref_cnt);
5668 platform_deinit(adev->platform);
5669 audio_extn_extspk_deinit(adev->extspk);
5670 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005671 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005672 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
5673 pcm_params_free(adev->use_case_table[i]);
5674 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005675 if (adev->adm_deinit)
5676 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005677 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005678 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07005679 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07005680
5681 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005682
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005683 return 0;
5684}
5685
Glenn Kasten4f993392014-05-14 07:30:48 -07005686/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5687 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5688 * just that it _might_ work.
5689 */
5690static int period_size_is_plausible_for_low_latency(int period_size)
5691{
5692 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005693 case 48:
5694 case 96:
5695 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07005696 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005697 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07005698 case 240:
5699 case 320:
5700 case 480:
5701 return 1;
5702 default:
5703 return 0;
5704 }
5705}
5706
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005707static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
5708{
5709 int card;
5710 card_status_t status;
5711
5712 if (!parms)
5713 return;
5714
5715 if (parse_snd_card_status(parms, &card, &status) < 0)
5716 return;
5717
5718 pthread_mutex_lock(&adev->lock);
5719 bool valid_cb = (card == adev->snd_card);
5720 if (valid_cb) {
5721 if (adev->card_status != status) {
5722 adev->card_status = status;
5723 platform_snd_card_update(adev->platform, status);
5724 }
5725 }
5726 pthread_mutex_unlock(&adev->lock);
5727 return;
5728}
5729
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005730/* out and adev lock held */
5731static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
5732{
5733 struct audio_usecase *uc_info;
5734 float left_p;
5735 float right_p;
5736 audio_devices_t devices;
5737
5738 uc_info = get_usecase_from_list(adev, out->usecase);
5739 if (uc_info == NULL) {
5740 ALOGE("%s: Could not find the usecase (%d) in the list",
5741 __func__, out->usecase);
5742 return -EINVAL;
5743 }
5744
5745 ALOGD("%s: enter: usecase(%d: %s)", __func__,
5746 out->usecase, use_case_table[out->usecase]);
5747
5748 if (restore) {
5749 // restore A2DP device for active usecases and unmute if required
5750 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
5751 !is_a2dp_device(uc_info->out_snd_device)) {
5752 ALOGD("%s: restoring A2DP and unmuting stream", __func__);
5753 select_devices(adev, uc_info->id);
5754 pthread_mutex_lock(&out->compr_mute_lock);
5755 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5756 (out->a2dp_compress_mute)) {
5757 out->a2dp_compress_mute = false;
5758 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5759 }
5760 pthread_mutex_unlock(&out->compr_mute_lock);
5761 }
5762 } else {
5763 // mute compress stream if suspended
5764 pthread_mutex_lock(&out->compr_mute_lock);
5765 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5766 (!out->a2dp_compress_mute)) {
5767 if (!out->standby) {
5768 ALOGD("%s: selecting speaker and muting stream", __func__);
5769 devices = out->devices;
5770 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
5771 left_p = out->volume_l;
5772 right_p = out->volume_r;
5773 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5774 compress_pause(out->compr);
5775 set_compr_volume(&out->stream, 0.0f, 0.0f);
5776 out->a2dp_compress_mute = true;
5777 select_devices(adev, out->usecase);
5778 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5779 compress_resume(out->compr);
5780 out->devices = devices;
5781 out->volume_l = left_p;
5782 out->volume_r = right_p;
5783 }
5784 }
5785 pthread_mutex_unlock(&out->compr_mute_lock);
5786 }
5787 ALOGV("%s: exit", __func__);
5788 return 0;
5789}
5790
5791int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
5792{
5793 int ret = 0;
5794
5795 lock_output_stream(out);
5796 pthread_mutex_lock(&adev->lock);
5797
5798 ret = check_a2dp_restore_l(adev, out, restore);
5799
5800 pthread_mutex_unlock(&adev->lock);
5801 pthread_mutex_unlock(&out->lock);
5802 return ret;
5803}
5804
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005805static int adev_open(const hw_module_t *module, const char *name,
5806 hw_device_t **device)
5807{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005808 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005809
Eric Laurent2bafff12016-03-17 12:17:23 -07005810 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005811 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005812 pthread_mutex_lock(&adev_init_lock);
5813 if (audio_device_ref_count != 0) {
5814 *device = &adev->device.common;
5815 audio_device_ref_count++;
5816 ALOGV("%s: returning existing instance of adev", __func__);
5817 ALOGV("%s: exit", __func__);
5818 pthread_mutex_unlock(&adev_init_lock);
5819 return 0;
5820 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005821 adev = calloc(1, sizeof(struct audio_device));
5822
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005823 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5824
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005825 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5826 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5827 adev->device.common.module = (struct hw_module_t *)module;
5828 adev->device.common.close = adev_close;
5829
5830 adev->device.init_check = adev_init_check;
5831 adev->device.set_voice_volume = adev_set_voice_volume;
5832 adev->device.set_master_volume = adev_set_master_volume;
5833 adev->device.get_master_volume = adev_get_master_volume;
5834 adev->device.set_master_mute = adev_set_master_mute;
5835 adev->device.get_master_mute = adev_get_master_mute;
5836 adev->device.set_mode = adev_set_mode;
5837 adev->device.set_mic_mute = adev_set_mic_mute;
5838 adev->device.get_mic_mute = adev_get_mic_mute;
5839 adev->device.set_parameters = adev_set_parameters;
5840 adev->device.get_parameters = adev_get_parameters;
5841 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5842 adev->device.open_output_stream = adev_open_output_stream;
5843 adev->device.close_output_stream = adev_close_output_stream;
5844 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005845
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005846 adev->device.close_input_stream = adev_close_input_stream;
5847 adev->device.dump = adev_dump;
jiabin8962a4d2018-03-19 18:21:24 -07005848 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005849
5850 /* Set the default route before the PCM stream is opened */
5851 pthread_mutex_lock(&adev->lock);
5852 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005853 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005854 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005855 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005856 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005857 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005858 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005859 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005860 pthread_mutex_unlock(&adev->lock);
5861
5862 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005863 adev->platform = platform_init(adev);
5864 if (!adev->platform) {
5865 free(adev->snd_dev_ref_cnt);
5866 free(adev);
5867 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5868 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005869 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005870 return -EINVAL;
5871 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05005872 adev->extspk = audio_extn_extspk_init(adev);
5873
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005874 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5875 if (adev->visualizer_lib == NULL) {
5876 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5877 } else {
5878 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5879 adev->visualizer_start_output =
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07005880 (int (*)(audio_io_handle_t, int, int, int))dlsym(adev->visualizer_lib,
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005881 "visualizer_hal_start_output");
5882 adev->visualizer_stop_output =
5883 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5884 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07005885 }
5886
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005887 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5888 if (adev->offload_effects_lib == NULL) {
5889 ALOGW("%s: DLOPEN failed for %s", __func__,
5890 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5891 } else {
5892 ALOGV("%s: DLOPEN successful for %s", __func__,
5893 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5894 adev->offload_effects_start_output =
5895 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5896 "offload_effects_bundle_hal_start_output");
5897 adev->offload_effects_stop_output =
5898 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5899 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07005900 }
5901
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005902 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5903 if (adev->adm_lib == NULL) {
5904 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5905 } else {
5906 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5907 adev->adm_init = (adm_init_t)
5908 dlsym(adev->adm_lib, "adm_init");
5909 adev->adm_deinit = (adm_deinit_t)
5910 dlsym(adev->adm_lib, "adm_deinit");
5911 adev->adm_register_input_stream = (adm_register_input_stream_t)
5912 dlsym(adev->adm_lib, "adm_register_input_stream");
5913 adev->adm_register_output_stream = (adm_register_output_stream_t)
5914 dlsym(adev->adm_lib, "adm_register_output_stream");
5915 adev->adm_deregister_stream = (adm_deregister_stream_t)
5916 dlsym(adev->adm_lib, "adm_deregister_stream");
5917 adev->adm_request_focus = (adm_request_focus_t)
5918 dlsym(adev->adm_lib, "adm_request_focus");
5919 adev->adm_abandon_focus = (adm_abandon_focus_t)
5920 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08005921 adev->adm_set_config = (adm_set_config_t)
5922 dlsym(adev->adm_lib, "adm_set_config");
5923 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5924 dlsym(adev->adm_lib, "adm_request_focus_v2");
5925 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5926 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5927 adev->adm_on_routing_change = (adm_on_routing_change_t)
5928 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005929 }
5930
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005931 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005932 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005933
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005934 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005935
Andy Hung31aca912014-03-20 17:14:59 -07005936 if (k_enable_extended_precision)
5937 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005938
Glenn Kasten4f993392014-05-14 07:30:48 -07005939 char value[PROPERTY_VALUE_MAX];
5940 int trial;
5941 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5942 trial = atoi(value);
5943 if (period_size_is_plausible_for_low_latency(trial)) {
5944 pcm_config_low_latency.period_size = trial;
5945 pcm_config_low_latency.start_threshold = trial / 4;
5946 pcm_config_low_latency.avail_min = trial / 4;
5947 configured_low_latency_capture_period_size = trial;
5948 }
5949 }
5950 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5951 trial = atoi(value);
5952 if (period_size_is_plausible_for_low_latency(trial)) {
5953 configured_low_latency_capture_period_size = trial;
5954 }
5955 }
5956
Vignesh Kulothunganb6f0a9c2018-03-22 13:50:22 -07005957 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
5958
Eric Laurent5f4ca952018-10-19 17:33:43 -07005959 adev->camera_orientation = CAMERA_DEFAULT;
5960
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005961 // commented as full set of app type cfg is sent from platform
5962 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005963 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005964
5965 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5966 af_period_multiplier = atoi(value);
5967 if (af_period_multiplier < 0) {
5968 af_period_multiplier = 2;
5969 } else if (af_period_multiplier > 4) {
5970 af_period_multiplier = 4;
5971 }
5972 ALOGV("new period_multiplier = %d", af_period_multiplier);
5973 }
5974
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005975 audio_extn_tfa_98xx_init(adev);
jasmine cha270b7762018-03-30 15:41:33 +08005976 audio_extn_ma_init(adev->platform);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005977
vivek mehta1a9b7c02015-06-25 11:49:38 -07005978 pthread_mutex_unlock(&adev_init_lock);
5979
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005980 if (adev->adm_init)
5981 adev->adm_data = adev->adm_init();
5982
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005983 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005984 audio_extn_snd_mon_init();
5985 pthread_mutex_lock(&adev->lock);
5986 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
5987 adev->card_status = CARD_STATUS_ONLINE;
5988 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005989 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005990
Eric Laurent2bafff12016-03-17 12:17:23 -07005991 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005992 return 0;
5993}
5994
5995static struct hw_module_methods_t hal_module_methods = {
5996 .open = adev_open,
5997};
5998
5999struct audio_module HAL_MODULE_INFO_SYM = {
6000 .common = {
6001 .tag = HARDWARE_MODULE_TAG,
6002 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
6003 .hal_api_version = HARDWARE_HAL_API_VERSION,
6004 .id = AUDIO_HARDWARE_MODULE_ID,
6005 .name = "QCOM Audio HAL",
6006 .author = "Code Aurora Forum",
6007 .methods = &hal_module_methods,
6008 },
6009};