blob: 657a627dbefc339cf1f915c5388ed886956914fa [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>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080043
Eric Laurentb23d5282013-05-14 15:27:20 -070044#include <hardware/audio_effect.h>
Andy Hung31aca912014-03-20 17:14:59 -070045#include <hardware/audio_alsaops.h>
Suren Baghdasaryan7f924c22018-12-21 15:07:18 -080046#include <processgroup/sched_policy.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 &&
Carter Hsu0a1160c2018-10-04 09:24:36 +08001176 ((uc_info->type == VOICE_CALL &&
1177 usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL) ||
1178 platform_check_backends_match(snd_device,\
1179 usecase->in_snd_device)) &&
Anish Kumarff864712015-06-03 13:35:11 -07001180 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001181 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1182 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001183 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001184 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001185 switch_device[usecase->id] = true;
1186 num_uc_to_switch++;
1187 }
1188 }
1189
1190 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001191 list_for_each(node, &adev->usecase_list) {
1192 usecase = node_to_item(node, struct audio_usecase, list);
1193 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001194 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001195 }
1196 }
1197
1198 list_for_each(node, &adev->usecase_list) {
1199 usecase = node_to_item(node, struct audio_usecase, list);
1200 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001201 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001202 }
1203 }
1204
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001205 /* Re-route all the usecases on the shared backend other than the
1206 specified usecase to new snd devices */
1207 list_for_each(node, &adev->usecase_list) {
1208 usecase = node_to_item(node, struct audio_usecase, list);
1209 /* Update the in_snd_device only before enabling the audio route */
1210 if (switch_device[usecase->id] ) {
1211 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001212 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001213 }
1214 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001215 }
1216}
1217
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001218/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001219static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001220{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001221 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001222 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001223
1224 switch (channels) {
1225 /*
1226 * Do not handle stereo output in Multi-channel cases
1227 * Stereo case is handled in normal playback path
1228 */
1229 case 6:
1230 ALOGV("%s: HDMI supports 5.1", __func__);
1231 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1232 break;
1233 case 8:
1234 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
1235 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1236 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
1237 break;
1238 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001239 ALOGE("HDMI does not support multi channel playback");
1240 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001241 break;
1242 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001243 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001244}
1245
Andy Hung18859412017-08-09 11:47:21 -07001246static ssize_t read_usb_sup_sample_rates(bool is_playback,
1247 uint32_t *supported_sample_rates,
1248 uint32_t max_rates)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001249{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001250 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1251 supported_sample_rates,
1252 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001253#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001254 for (ssize_t i=0; i<count; i++) {
1255 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1256 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001257 }
1258#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001259 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001260}
1261
Haynes Mathew George569b7482017-05-08 14:44:27 -07001262static int read_usb_sup_channel_masks(bool is_playback,
1263 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001264 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001265{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001266 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001267 int channel_count;
1268 uint32_t num_masks = 0;
1269 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1270 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001271 }
Eric Laurent74b55762017-07-09 17:04:53 -07001272 if (is_playback) {
Andy Hung6c1afb12017-12-22 11:34:41 -08001273 // start from 2 channels as framework currently doesn't support mono.
1274 // TODO: consider only supporting channel index masks beyond stereo here.
1275 for (channel_count = FCC_2;
1276 channel_count <= channels && num_masks < max_masks;
1277 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001278 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1279 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001280 for (channel_count = FCC_2;
1281 channel_count <= channels && num_masks < max_masks;
1282 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001283 supported_channel_masks[num_masks++] =
1284 audio_channel_mask_for_index_assignment_from_count(channel_count);
1285 }
1286 } else {
1287 // For capture we report all supported channel masks from 1 channel up.
1288 channel_count = MIN_CHANNEL_COUNT;
1289 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1290 // indexed mask
1291 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
Andy Hung88ce1d92018-10-29 18:31:12 -07001292 const audio_channel_mask_t mask =
Eric Laurent74b55762017-07-09 17:04:53 -07001293 audio_channel_in_mask_from_count(channel_count);
Andy Hung88ce1d92018-10-29 18:31:12 -07001294 supported_channel_masks[num_masks++] = mask;
1295 const audio_channel_mask_t index_mask =
1296 audio_channel_mask_for_index_assignment_from_count(channel_count);
1297 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
1298 supported_channel_masks[num_masks++] = index_mask;
1299 }
Eric Laurent74b55762017-07-09 17:04:53 -07001300 }
1301 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001302#ifdef NDEBUG
1303 for (size_t i = 0; i < num_masks; ++i) {
1304 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1305 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
1306 }
1307#endif
Eric Laurent74b55762017-07-09 17:04:53 -07001308 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001309}
1310
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001311static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001312 audio_format_t *supported_formats,
1313 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001314{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001315 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001316 switch (bitwidth) {
1317 case 24:
1318 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001319 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001320 break;
1321 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001322 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001323 break;
1324 case 16:
1325 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001326 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001327 break;
1328 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001329 ALOGV("%s: %s supported format %d", __func__,
1330 is_playback ? "P" : "C", bitwidth);
1331 return 1;
1332}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001333
Haynes Mathew George569b7482017-05-08 14:44:27 -07001334static int read_usb_sup_params_and_compare(bool is_playback,
1335 audio_format_t *format,
1336 audio_format_t *supported_formats,
1337 uint32_t max_formats,
1338 audio_channel_mask_t *mask,
1339 audio_channel_mask_t *supported_channel_masks,
1340 uint32_t max_masks,
1341 uint32_t *rate,
1342 uint32_t *supported_sample_rates,
1343 uint32_t max_rates) {
1344 int ret = 0;
1345 int num_formats;
1346 int num_masks;
1347 int num_rates;
1348 int i;
1349
1350 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1351 max_formats);
1352 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1353 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001354
Haynes Mathew George569b7482017-05-08 14:44:27 -07001355 num_rates = read_usb_sup_sample_rates(is_playback,
1356 supported_sample_rates, max_rates);
1357
1358#define LUT(table, len, what, dflt) \
1359 for (i=0; i<len && (table[i] != what); i++); \
1360 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1361
1362 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1363 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1364 LUT(supported_sample_rates, num_rates, *rate, 0);
1365
1366#undef LUT
1367 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001368}
1369
Andy Hungd9653bd2017-08-01 19:31:39 -07001370static bool is_usb_ready(struct audio_device *adev, bool is_playback)
1371{
1372 // Check if usb is ready.
1373 // The usb device may have been removed quickly after insertion and hence
1374 // no longer available. This will show up as empty channel masks, or rates.
1375
1376 pthread_mutex_lock(&adev->lock);
1377 uint32_t supported_sample_rate;
1378
1379 // we consider usb ready if we can fetch at least one sample rate.
1380 const bool ready = read_usb_sup_sample_rates(
1381 is_playback, &supported_sample_rate, 1 /* max_rates */) > 0;
1382 pthread_mutex_unlock(&adev->lock);
1383 return ready;
1384}
1385
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001386static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1387{
1388 struct audio_usecase *usecase;
1389 struct listnode *node;
1390
1391 list_for_each(node, &adev->usecase_list) {
1392 usecase = node_to_item(node, struct audio_usecase, list);
1393 if (usecase->type == VOICE_CALL) {
1394 ALOGV("%s: usecase id %d", __func__, usecase->id);
1395 return usecase->id;
1396 }
1397 }
1398 return USECASE_INVALID;
1399}
1400
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001401struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1402 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001403{
1404 struct audio_usecase *usecase;
1405 struct listnode *node;
1406
1407 list_for_each(node, &adev->usecase_list) {
1408 usecase = node_to_item(node, struct audio_usecase, list);
1409 if (usecase->id == uc_id)
1410 return usecase;
1411 }
1412 return NULL;
1413}
1414
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001415static bool force_device_switch(struct audio_usecase *usecase)
1416{
1417 if (usecase->stream.out == NULL) {
1418 ALOGE("%s: stream.out is NULL", __func__);
1419 return false;
1420 }
1421
1422 // Force all A2DP output devices to reconfigure for proper AFE encode format
1423 // Also handle a case where in earlier A2DP start failed as A2DP stream was
1424 // in suspended state, hence try to trigger a retry when we again get a routing request.
1425 if ((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
1426 audio_extn_a2dp_is_force_device_switch()) {
1427 ALOGD("%s: Force A2DP device switch to update new encoder config", __func__);
1428 return true;
1429 }
1430
1431 return false;
1432}
1433
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001434struct stream_in *adev_get_active_input(const struct audio_device *adev)
1435{
1436 struct listnode *node;
1437 struct stream_in *last_active_in = NULL;
1438
1439 /* Get last added active input.
1440 * TODO: We may use a priority mechanism to pick highest priority active source */
1441 list_for_each(node, &adev->usecase_list)
1442 {
1443 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
1444 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL) {
1445 last_active_in = usecase->stream.in;
1446 }
1447 }
1448
1449 return last_active_in;
1450}
1451
1452struct stream_in *get_voice_communication_input(const struct audio_device *adev)
1453{
1454 struct listnode *node;
1455
1456 /* First check active inputs with voice communication source and then
1457 * any input if audio mode is in communication */
1458 list_for_each(node, &adev->usecase_list)
1459 {
1460 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
1461 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
1462 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1463 return usecase->stream.in;
1464 }
1465 }
1466 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
1467 return adev_get_active_input(adev);
1468 }
1469 return NULL;
1470}
1471
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001472int select_devices(struct audio_device *adev,
1473 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001474{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001475 snd_device_t out_snd_device = SND_DEVICE_NONE;
1476 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001477 struct audio_usecase *usecase = NULL;
1478 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001479 struct audio_usecase *hfp_usecase = NULL;
1480 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001481 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001482 int status = 0;
Eric Laurentf4520b02017-09-20 18:31:58 -07001483 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1484 USECASE_AUDIO_PLAYBACK_VOIP);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001485
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001486 usecase = get_usecase_from_list(adev, uc_id);
1487 if (usecase == NULL) {
1488 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1489 return -EINVAL;
1490 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001491
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001492 if ((usecase->type == VOICE_CALL) ||
1493 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001494 out_snd_device = platform_get_output_snd_device(adev->platform,
1495 usecase->stream.out->devices);
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001496 in_snd_device = platform_get_input_snd_device(adev->platform,
1497 NULL,
1498 usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001499 usecase->devices = usecase->stream.out->devices;
1500 } else {
1501 /*
1502 * If the voice call is active, use the sound devices of voice call usecase
1503 * so that it would not result any device switch. All the usecases will
1504 * be switched to new device when select_devices() is called for voice call
1505 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001506 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001507 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001508 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001509 vc_usecase = get_usecase_from_list(adev,
1510 get_voice_usecase_id_from_list(adev));
1511 if ((vc_usecase != NULL) &&
1512 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1513 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001514 in_snd_device = vc_usecase->in_snd_device;
1515 out_snd_device = vc_usecase->out_snd_device;
1516 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001517 } else if (audio_extn_hfp_is_active(adev)) {
1518 hfp_ucid = audio_extn_hfp_get_usecase();
1519 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1520 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1521 in_snd_device = hfp_usecase->in_snd_device;
1522 out_snd_device = hfp_usecase->out_snd_device;
1523 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001524 }
1525 if (usecase->type == PCM_PLAYBACK) {
1526 usecase->devices = usecase->stream.out->devices;
1527 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001528 if (out_snd_device == SND_DEVICE_NONE) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001529 struct stream_out *voip_out = adev->primary_output;
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001530 struct stream_in *voip_in = get_voice_communication_input(adev);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001531
Eric Laurentb23d5282013-05-14 15:27:20 -07001532 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001533 usecase->stream.out->devices);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001534
1535 if (voip_usecase)
1536 voip_out = voip_usecase->stream.out;
1537
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001538 if (usecase->stream.out == voip_out && voip_in != NULL) {
1539 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001540 }
1541 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001542 } else if (usecase->type == PCM_CAPTURE) {
1543 usecase->devices = usecase->stream.in->device;
1544 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001545 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001546 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001547 struct stream_in *voip_in = get_voice_communication_input(adev);
1548
1549 if (voip_in != NULL) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001550
1551 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1552 USECASE_AUDIO_PLAYBACK_VOIP);
1553
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001554 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001555 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1556 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001557 } else if (voip_usecase) {
1558 out_device = voip_usecase->stream.out->devices;
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001559 } else if (adev->primary_output) {
1560 out_device = adev->primary_output->devices;
1561 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001562 }
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001563 in_snd_device = platform_get_input_snd_device(adev->platform,
1564 usecase->stream.in,
1565 out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001566 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001567 }
1568 }
1569
1570 if (out_snd_device == usecase->out_snd_device &&
1571 in_snd_device == usecase->in_snd_device) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001572 if (!force_device_switch(usecase))
1573 return 0;
1574 }
1575
1576 if (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready()) {
1577 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1578 return 0;
1579 }
1580
Aniket Kumar Lata9723a962018-05-16 17:41:55 -07001581 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
1582 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001583 (!audio_extn_a2dp_is_ready())) {
1584 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
juyuchen9baad392018-06-05 19:02:10 +08001585 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
1586 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
1587 else
1588 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001589 }
1590
juyuchen66c4ecf2018-08-06 15:39:34 +08001591 if (usecase->id == USECASE_INCALL_MUSIC_UPLINK) {
1592 out_snd_device = SND_DEVICE_OUT_VOICE_MUSIC_TX;
1593 }
1594
Eric Laurent2bafff12016-03-17 12:17:23 -07001595 if (out_snd_device != SND_DEVICE_NONE &&
1596 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1597 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1598 __func__,
1599 use_case_table[uc_id],
1600 adev->last_logged_snd_device[uc_id][0],
1601 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1602 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1603 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1604 -1,
1605 out_snd_device,
1606 platform_get_snd_device_name(out_snd_device),
1607 platform_get_snd_device_acdb_id(out_snd_device));
1608 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1609 }
1610 if (in_snd_device != SND_DEVICE_NONE &&
1611 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1612 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1613 __func__,
1614 use_case_table[uc_id],
1615 adev->last_logged_snd_device[uc_id][1],
1616 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1617 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1618 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1619 -1,
1620 in_snd_device,
1621 platform_get_snd_device_name(in_snd_device),
1622 platform_get_snd_device_acdb_id(in_snd_device));
1623 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1624 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001625
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001626 /*
1627 * Limitation: While in call, to do a device switch we need to disable
1628 * and enable both RX and TX devices though one of them is same as current
1629 * device.
1630 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001631 if ((usecase->type == VOICE_CALL) &&
1632 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1633 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001634 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001635 /* Disable sidetone only if voice call already exists */
1636 if (voice_is_call_state_active(adev))
1637 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001638 }
1639
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001640 /* Disable current sound devices */
1641 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001642 disable_audio_route(adev, usecase);
1643 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001644 }
1645
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001646 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001647 disable_audio_route(adev, usecase);
1648 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001649 }
1650
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001651 /* Applicable only on the targets that has external modem.
1652 * New device information should be sent to modem before enabling
1653 * the devices to reduce in-call device switch time.
1654 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001655 if ((usecase->type == VOICE_CALL) &&
1656 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1657 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001658 status = platform_switch_voice_call_enable_device_config(adev->platform,
1659 out_snd_device,
1660 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001661 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001662
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001663 /* Enable new sound devices */
1664 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001665 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001666 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) ||
1667 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001668 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001669 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001670 }
1671
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001672 if (in_snd_device != SND_DEVICE_NONE) {
1673 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001674 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001675 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001676
Eric Laurentb23d5282013-05-14 15:27:20 -07001677 if (usecase->type == VOICE_CALL)
1678 status = platform_switch_voice_call_device_post(adev->platform,
1679 out_snd_device,
1680 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001681
sangwoo170731f2013-06-08 15:36:36 +09001682 usecase->in_snd_device = in_snd_device;
1683 usecase->out_snd_device = out_snd_device;
1684
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001685 audio_extn_tfa_98xx_set_mode();
1686
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001687 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001688
Jasmine Cha70771b62018-05-15 15:02:43 +08001689 audio_extn_ma_set_device(usecase);
jasmine cha270b7762018-03-30 15:41:33 +08001690
Vignesh Kulothungan64698822018-01-23 11:25:18 -08001691 /* If input stream is already running the effect needs to be
1692 applied on the new input device that's being enabled here. */
1693 if (in_snd_device != SND_DEVICE_NONE)
1694 check_and_enable_effect(adev);
1695
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001696 /* Applicable only on the targets that has external modem.
1697 * Enable device command should be sent to modem only after
1698 * enabling voice call mixer controls
1699 */
vivek mehta765eb642015-08-07 19:46:06 -07001700 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001701 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1702 out_snd_device,
1703 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001704 /* Enable sidetone only if voice call already exists */
1705 if (voice_is_call_state_active(adev))
1706 voice_set_sidetone(adev, out_snd_device, true);
1707 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001708
Yung Ti Sue9d64f92018-06-22 17:38:47 +08001709 if (usecase->type != PCM_CAPTURE && voip_usecase) {
Eric Laurentf4520b02017-09-20 18:31:58 -07001710 struct stream_out *voip_out = voip_usecase->stream.out;
1711 audio_extn_utils_send_app_type_gain(adev,
1712 voip_out->app_type_cfg.app_type,
1713 &voip_out->app_type_cfg.gain[0]);
1714 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001715 return status;
1716}
1717
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001718static int stop_input_stream(struct stream_in *in)
1719{
1720 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001721 struct audio_usecase *uc_info;
1722 struct audio_device *adev = in->dev;
1723
Eric Laurent994a6932013-07-17 11:51:42 -07001724 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001725 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001726
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001727 uc_info = get_usecase_from_list(adev, in->usecase);
1728 if (uc_info == NULL) {
1729 ALOGE("%s: Could not find the usecase (%d) in the list",
1730 __func__, in->usecase);
1731 return -EINVAL;
1732 }
1733
vivek mehta781065c2017-04-04 12:55:01 -07001734 /* Close in-call recording streams */
1735 voice_check_and_stop_incall_rec_usecase(adev, in);
1736
Eric Laurent150dbfe2013-02-27 14:31:02 -08001737 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001738 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001739
1740 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001741 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001742
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001743 list_remove(&uc_info->list);
1744 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001745
Eric Laurent994a6932013-07-17 11:51:42 -07001746 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001747 return ret;
1748}
1749
1750int start_input_stream(struct stream_in *in)
1751{
1752 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001753 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001754 struct audio_usecase *uc_info;
1755 struct audio_device *adev = in->dev;
1756
Eric Laurent994a6932013-07-17 11:51:42 -07001757 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001758
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001759 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1760 return -EIO;
1761
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001762 if (in->card_status == CARD_STATUS_OFFLINE ||
1763 adev->card_status == CARD_STATUS_OFFLINE) {
1764 ALOGW("in->card_status or adev->card_status offline, try again");
1765 ret = -EAGAIN;
1766 goto error_config;
1767 }
1768
vivek mehta781065c2017-04-04 12:55:01 -07001769 /* Check if source matches incall recording usecase criteria */
1770 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1771 if (ret)
1772 goto error_config;
1773 else
1774 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1775
Eric Laurentb23d5282013-05-14 15:27:20 -07001776 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001777 if (in->pcm_device_id < 0) {
1778 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1779 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001780 ret = -EINVAL;
1781 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001782 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001783
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001784 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1785 uc_info->id = in->usecase;
1786 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001787 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001788 uc_info->devices = in->device;
1789 uc_info->in_snd_device = SND_DEVICE_NONE;
1790 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001791
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001792 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001793
Wei Wangf4837d52017-11-21 14:51:20 -08001794 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001795 audio_extn_perf_lock_acquire();
1796
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001797 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001798
Eric Laurent0e46adf2016-12-16 12:49:24 -08001799 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001800 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001801 ALOGE("%s: pcm stream not ready", __func__);
1802 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001803 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001804 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001805 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001806 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1807 goto error_open;
1808 }
1809 } else {
1810 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1811 unsigned int pcm_open_retry_count = 0;
1812
1813 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1814 flags |= PCM_MMAP | PCM_NOIRQ;
1815 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1816 } else if (in->realtime) {
1817 flags |= PCM_MMAP | PCM_NOIRQ;
1818 }
1819
1820 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1821 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1822
1823 while (1) {
1824 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1825 flags, &in->config);
1826 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1827 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1828 if (in->pcm != NULL) {
1829 pcm_close(in->pcm);
1830 in->pcm = NULL;
1831 }
1832 if (pcm_open_retry_count-- == 0) {
1833 ret = -EIO;
1834 goto error_open;
1835 }
1836 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1837 continue;
1838 }
1839 break;
1840 }
1841
1842 ALOGV("%s: pcm_prepare", __func__);
1843 ret = pcm_prepare(in->pcm);
1844 if (ret < 0) {
1845 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001846 pcm_close(in->pcm);
1847 in->pcm = NULL;
1848 goto error_open;
1849 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001850 if (in->realtime) {
1851 ret = pcm_start(in->pcm);
1852 if (ret < 0) {
1853 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1854 pcm_close(in->pcm);
1855 in->pcm = NULL;
1856 goto error_open;
1857 }
1858 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001859 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001860 register_in_stream(in);
Vignesh Kulothungan64698822018-01-23 11:25:18 -08001861 check_and_enable_effect(adev);
Wei Wangf4837d52017-11-21 14:51:20 -08001862 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001863 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001864 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001865
Eric Laurent0e46adf2016-12-16 12:49:24 -08001866 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001867
1868error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001869 stop_input_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001870 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001871 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001872
1873error_config:
Eric Laurent2bafff12016-03-17 12:17:23 -07001874 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001875 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001876}
1877
Eric Laurenta1478072015-09-21 17:21:52 -07001878void lock_input_stream(struct stream_in *in)
1879{
1880 pthread_mutex_lock(&in->pre_lock);
1881 pthread_mutex_lock(&in->lock);
1882 pthread_mutex_unlock(&in->pre_lock);
1883}
1884
1885void lock_output_stream(struct stream_out *out)
1886{
1887 pthread_mutex_lock(&out->pre_lock);
1888 pthread_mutex_lock(&out->lock);
1889 pthread_mutex_unlock(&out->pre_lock);
1890}
1891
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001892/* must be called with out->lock locked */
1893static int send_offload_cmd_l(struct stream_out* out, int command)
1894{
1895 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1896
1897 ALOGVV("%s %d", __func__, command);
1898
1899 cmd->cmd = command;
1900 list_add_tail(&out->offload_cmd_list, &cmd->node);
1901 pthread_cond_signal(&out->offload_cond);
1902 return 0;
1903}
1904
1905/* must be called iwth out->lock locked */
1906static void stop_compressed_output_l(struct stream_out *out)
1907{
1908 out->offload_state = OFFLOAD_STATE_IDLE;
1909 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001910 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001911 if (out->compr != NULL) {
1912 compress_stop(out->compr);
1913 while (out->offload_thread_blocked) {
1914 pthread_cond_wait(&out->cond, &out->lock);
1915 }
1916 }
1917}
1918
1919static void *offload_thread_loop(void *context)
1920{
1921 struct stream_out *out = (struct stream_out *) context;
1922 struct listnode *item;
1923
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001924 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1925 set_sched_policy(0, SP_FOREGROUND);
1926 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1927
1928 ALOGV("%s", __func__);
juyuchenb0f5bfd2018-12-12 17:58:09 +08001929
Eric Laurenta1478072015-09-21 17:21:52 -07001930 lock_output_stream(out);
juyuchenb0f5bfd2018-12-12 17:58:09 +08001931 out->offload_state = OFFLOAD_STATE_IDLE;
1932 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001933 for (;;) {
1934 struct offload_cmd *cmd = NULL;
1935 stream_callback_event_t event;
1936 bool send_callback = false;
1937
1938 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1939 __func__, list_empty(&out->offload_cmd_list),
1940 out->offload_state);
1941 if (list_empty(&out->offload_cmd_list)) {
1942 ALOGV("%s SLEEPING", __func__);
1943 pthread_cond_wait(&out->offload_cond, &out->lock);
1944 ALOGV("%s RUNNING", __func__);
1945 continue;
1946 }
1947
1948 item = list_head(&out->offload_cmd_list);
1949 cmd = node_to_item(item, struct offload_cmd, node);
1950 list_remove(item);
1951
1952 ALOGVV("%s STATE %d CMD %d out->compr %p",
1953 __func__, out->offload_state, cmd->cmd, out->compr);
1954
1955 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1956 free(cmd);
1957 break;
1958 }
1959
1960 if (out->compr == NULL) {
1961 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001962 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001963 pthread_cond_signal(&out->cond);
1964 continue;
1965 }
1966 out->offload_thread_blocked = true;
1967 pthread_mutex_unlock(&out->lock);
1968 send_callback = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001969 switch (cmd->cmd) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001970 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1971 compress_wait(out->compr, -1);
1972 send_callback = true;
1973 event = STREAM_CBK_EVENT_WRITE_READY;
1974 break;
1975 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001976 compress_next_track(out->compr);
1977 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001978 send_callback = true;
1979 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001980 /* Resend the metadata for next iteration */
1981 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001982 break;
1983 case OFFLOAD_CMD_DRAIN:
1984 compress_drain(out->compr);
1985 send_callback = true;
1986 event = STREAM_CBK_EVENT_DRAIN_READY;
1987 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001988 case OFFLOAD_CMD_ERROR:
1989 send_callback = true;
1990 event = STREAM_CBK_EVENT_ERROR;
1991 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001992 default:
1993 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1994 break;
1995 }
Eric Laurenta1478072015-09-21 17:21:52 -07001996 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001997 out->offload_thread_blocked = false;
1998 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001999 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08002000 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002001 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002002 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002003 free(cmd);
2004 }
2005
2006 pthread_cond_signal(&out->cond);
2007 while (!list_empty(&out->offload_cmd_list)) {
2008 item = list_head(&out->offload_cmd_list);
2009 list_remove(item);
2010 free(node_to_item(item, struct offload_cmd, node));
2011 }
2012 pthread_mutex_unlock(&out->lock);
2013
2014 return NULL;
2015}
2016
2017static int create_offload_callback_thread(struct stream_out *out)
2018{
2019 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2020 list_init(&out->offload_cmd_list);
2021 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2022 offload_thread_loop, out);
2023 return 0;
2024}
2025
2026static int destroy_offload_callback_thread(struct stream_out *out)
2027{
Eric Laurenta1478072015-09-21 17:21:52 -07002028 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002029 stop_compressed_output_l(out);
2030 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2031
2032 pthread_mutex_unlock(&out->lock);
2033 pthread_join(out->offload_thread, (void **) NULL);
2034 pthread_cond_destroy(&out->offload_cond);
2035
2036 return 0;
2037}
2038
Eric Laurent07eeafd2013-10-06 12:52:49 -07002039static bool allow_hdmi_channel_config(struct audio_device *adev)
2040{
2041 struct listnode *node;
2042 struct audio_usecase *usecase;
2043 bool ret = true;
2044
2045 list_for_each(node, &adev->usecase_list) {
2046 usecase = node_to_item(node, struct audio_usecase, list);
2047 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2048 /*
2049 * If voice call is already existing, do not proceed further to avoid
2050 * disabling/enabling both RX and TX devices, CSD calls, etc.
2051 * Once the voice call done, the HDMI channels can be configured to
2052 * max channels of remaining use cases.
2053 */
2054 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08002055 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07002056 __func__);
2057 ret = false;
2058 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002059 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
2060 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07002061 "no change in HDMI channels", __func__);
2062 ret = false;
2063 break;
2064 }
2065 }
2066 }
2067 return ret;
2068}
2069
2070static int check_and_set_hdmi_channels(struct audio_device *adev,
2071 unsigned int channels)
2072{
2073 struct listnode *node;
2074 struct audio_usecase *usecase;
2075
2076 /* Check if change in HDMI channel config is allowed */
2077 if (!allow_hdmi_channel_config(adev))
2078 return 0;
2079
2080 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08002081 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002082 return 0;
2083 }
2084
2085 platform_set_hdmi_channels(adev->platform, channels);
2086 adev->cur_hdmi_channels = channels;
2087
2088 /*
2089 * Deroute all the playback streams routed to HDMI so that
2090 * the back end is deactivated. Note that backend will not
2091 * be deactivated if any one stream is connected to it.
2092 */
2093 list_for_each(node, &adev->usecase_list) {
2094 usecase = node_to_item(node, struct audio_usecase, list);
2095 if (usecase->type == PCM_PLAYBACK &&
2096 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002097 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002098 }
2099 }
2100
2101 /*
2102 * Enable all the streams disabled above. Now the HDMI backend
2103 * will be activated with new channel configuration
2104 */
2105 list_for_each(node, &adev->usecase_list) {
2106 usecase = node_to_item(node, struct audio_usecase, list);
2107 if (usecase->type == PCM_PLAYBACK &&
2108 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002109 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002110 }
2111 }
2112
2113 return 0;
2114}
2115
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002116static int check_and_set_usb_service_interval(struct audio_device *adev,
2117 struct audio_usecase *uc_info,
2118 bool min)
2119{
2120 struct listnode *node;
2121 struct audio_usecase *usecase;
2122 bool switch_usecases = false;
2123 bool reconfig = false;
2124
2125 if ((uc_info->id != USECASE_AUDIO_PLAYBACK_MMAP) &&
2126 (uc_info->id != USECASE_AUDIO_PLAYBACK_ULL))
2127 return -1;
2128
2129 /* set if the valid usecase do not already exist */
2130 list_for_each(node, &adev->usecase_list) {
2131 usecase = node_to_item(node, struct audio_usecase, list);
2132 if (usecase->type == PCM_PLAYBACK &&
2133 (audio_is_usb_out_device(usecase->devices & AUDIO_DEVICE_OUT_ALL_USB))) {
2134 switch (usecase->id) {
2135 case USECASE_AUDIO_PLAYBACK_MMAP:
2136 case USECASE_AUDIO_PLAYBACK_ULL:
2137 // cannot reconfig while mmap/ull is present.
2138 return -1;
2139 default:
2140 switch_usecases = true;
2141 break;
2142 }
2143 }
2144 if (switch_usecases)
2145 break;
2146 }
2147 /*
2148 * client can try to set service interval in start_output_stream
2149 * to min or to 0 (i.e reset) in stop_output_stream .
2150 */
2151 unsigned long service_interval =
2152 audio_extn_usb_find_service_interval(min, true /*playback*/);
2153 int ret = platform_set_usb_service_interval(adev->platform,
2154 true /*playback*/,
2155 service_interval,
2156 &reconfig);
2157 /* no change or not supported or no active usecases */
2158 if (ret || !reconfig || !switch_usecases)
2159 return -1;
2160 return 0;
2161#undef VALID_USECASE
2162}
2163
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002164static int stop_output_stream(struct stream_out *out)
2165{
2166 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002167 struct audio_usecase *uc_info;
2168 struct audio_device *adev = out->dev;
HW Lee88512e92018-06-12 15:26:09 +08002169 bool has_voip_usecase =
2170 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002171
Eric Laurent994a6932013-07-17 11:51:42 -07002172 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002173 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002174 uc_info = get_usecase_from_list(adev, out->usecase);
2175 if (uc_info == NULL) {
2176 ALOGE("%s: Could not find the usecase (%d) in the list",
2177 __func__, out->usecase);
2178 return -EINVAL;
2179 }
2180
Haynes Mathew George41f86652014-06-17 14:22:15 -07002181 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2182 if (adev->visualizer_stop_output != NULL)
2183 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
2184 if (adev->offload_effects_stop_output != NULL)
2185 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002186 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2187 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2188 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07002189 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002190
Arun Mirpuri0cc2f312018-05-29 17:26:07 -07002191 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
2192 voice_set_device_mute_flag(adev, false);
2193
Eric Laurent150dbfe2013-02-27 14:31:02 -08002194 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002195 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002196
2197 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002198 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002199
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002200 list_remove(&uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002201
Eric Laurent0499d4f2014-08-25 22:39:29 -05002202 audio_extn_extspk_update(adev->extspk);
2203
Eric Laurent07eeafd2013-10-06 12:52:49 -07002204 /* Must be called after removing the usecase from list */
2205 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2206 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
HW Lee88512e92018-06-12 15:26:09 +08002207 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002208 ret = check_and_set_usb_service_interval(adev, uc_info, false /*min*/);
2209 if (ret == 0) {
2210 /* default service interval was successfully updated,
2211 reopen USB backend with new service interval */
2212 check_and_route_playback_usecases(adev, uc_info, uc_info->out_snd_device);
2213 }
2214 ret = 0;
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07002215 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002216
HW Lee88512e92018-06-12 15:26:09 +08002217 if (has_voip_usecase ||
2218 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
2219 struct listnode *node;
2220 struct audio_usecase *usecase;
2221 list_for_each(node, &adev->usecase_list) {
2222 usecase = node_to_item(node, struct audio_usecase, list);
2223 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
2224 continue;
2225
2226 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
2227 __func__, usecase->id, use_case_table[usecase->id],
2228 out->usecase, use_case_table[out->usecase]);
2229 select_devices(adev, usecase->id);
2230 }
2231 }
2232
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002233 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07002234 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002235 return ret;
2236}
2237
2238int start_output_stream(struct stream_out *out)
2239{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002240 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002241 struct audio_usecase *uc_info;
2242 struct audio_device *adev = out->dev;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002243 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002244
Eric Laurent994a6932013-07-17 11:51:42 -07002245 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002246 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002247
2248 if (out->card_status == CARD_STATUS_OFFLINE ||
2249 adev->card_status == CARD_STATUS_OFFLINE) {
2250 ALOGW("out->card_status or adev->card_status offline, try again");
2251 ret = -EAGAIN;
2252 goto error_config;
2253 }
2254
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002255 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2256 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002257 if (out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002258 a2dp_combo = true;
2259 } else {
2260 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2261 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2262 ret = -EAGAIN;
2263 goto error_config;
2264 }
2265 }
2266 }
2267 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002268 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002269 if (out->pcm_device_id < 0) {
2270 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2271 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002272 ret = -EINVAL;
2273 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002274 }
2275
2276 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
2277 uc_info->id = out->usecase;
2278 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002279 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002280 uc_info->devices = out->devices;
2281 uc_info->in_snd_device = SND_DEVICE_NONE;
2282 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002283
Eric Laurent07eeafd2013-10-06 12:52:49 -07002284 /* This must be called before adding this usecase to the list */
2285 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2286 check_and_set_hdmi_channels(adev, out->config.channels);
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002287 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
2288 check_and_set_usb_service_interval(adev, uc_info, true /*min*/);
2289 /* USB backend is not reopened immediately.
2290 This is eventually done as part of select_devices */
2291 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002292
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002293 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002294
Wei Wangf4837d52017-11-21 14:51:20 -08002295 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002296 audio_extn_perf_lock_acquire();
2297
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002298 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2299 (!audio_extn_a2dp_is_ready())) {
2300 if (!a2dp_combo) {
2301 check_a2dp_restore_l(adev, out, false);
2302 } else {
2303 audio_devices_t dev = out->devices;
juyuchen9baad392018-06-05 19:02:10 +08002304 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2305 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2306 else
2307 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002308 select_devices(adev, out->usecase);
2309 out->devices = dev;
2310 }
2311 } else {
2312 select_devices(adev, out->usecase);
2313 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002314
Eric Laurent0499d4f2014-08-25 22:39:29 -05002315 audio_extn_extspk_update(adev->extspk);
2316
Arun Mirpuri0cc2f312018-05-29 17:26:07 -07002317 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
2318 voice_set_device_mute_flag(adev, true);
2319
Andy Hung31aca912014-03-20 17:14:59 -07002320 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002321 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002322 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2323 out->pcm = NULL;
2324 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
2325 COMPRESS_IN, &out->compr_config);
2326 if (out->compr && !is_compress_ready(out->compr)) {
2327 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2328 compress_close(out->compr);
2329 out->compr = NULL;
2330 ret = -EIO;
2331 goto error_open;
2332 }
2333 if (out->offload_callback)
2334 compress_nonblock(out->compr, out->non_blocking);
2335
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07002336 if (adev->visualizer_start_output != NULL) {
2337 int capture_device_id =
2338 platform_get_pcm_device_id(USECASE_AUDIO_RECORD_AFE_PROXY,
2339 PCM_CAPTURE);
2340 adev->visualizer_start_output(out->handle, out->pcm_device_id,
2341 adev->snd_card, capture_device_id);
2342 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002343 if (adev->offload_effects_start_output != NULL)
2344 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
2345 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002346 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002347 ALOGE("%s: pcm stream not ready", __func__);
2348 goto error_open;
2349 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002350 ret = pcm_start(out->pcm);
2351 if (ret < 0) {
2352 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2353 goto error_open;
2354 }
2355 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07002356 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002357 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002358
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002359 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2360 flags |= PCM_MMAP | PCM_NOIRQ;
2361 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002362 } else if (out->realtime) {
2363 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07002364 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002365
2366 while (1) {
2367 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2368 flags, &out->config);
2369 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2370 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2371 if (out->pcm != NULL) {
2372 pcm_close(out->pcm);
2373 out->pcm = NULL;
2374 }
2375 if (pcm_open_retry_count-- == 0) {
2376 ret = -EIO;
2377 goto error_open;
2378 }
2379 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2380 continue;
2381 }
2382 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002383 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002384 ALOGV("%s: pcm_prepare", __func__);
2385 if (pcm_is_ready(out->pcm)) {
2386 ret = pcm_prepare(out->pcm);
2387 if (ret < 0) {
2388 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2389 pcm_close(out->pcm);
2390 out->pcm = NULL;
2391 goto error_open;
2392 }
2393 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002394 if (out->realtime) {
2395 ret = pcm_start(out->pcm);
2396 if (ret < 0) {
2397 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
2398 pcm_close(out->pcm);
2399 out->pcm = NULL;
2400 goto error_open;
2401 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002402 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002403 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002404 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08002405 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002406 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002407 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07002408
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002409 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2410 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2411 audio_low_latency_hint_start();
2412 }
2413
vivek mehtae59cfb22017-06-16 15:57:11 -07002414 // consider a scenario where on pause lower layers are tear down.
2415 // so on resume, swap mixer control need to be sent only when
2416 // backend is active, hence rather than sending from enable device
2417 // sending it from start of streamtream
2418
2419 platform_set_swap_channels(adev, true);
2420
Eric Laurent994a6932013-07-17 11:51:42 -07002421 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002422 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002423error_open:
Wei Wangf4837d52017-11-21 14:51:20 -08002424 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002425 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002426 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002427error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002428 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002429}
2430
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002431static int check_input_parameters(uint32_t sample_rate,
2432 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07002433 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002434{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002435 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2436 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002437 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2438 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002439 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2440 return -EINVAL;
2441 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002442
Eric Laurent74b55762017-07-09 17:04:53 -07002443 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2444 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002445 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002446 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002447 return -EINVAL;
2448 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002449
2450 switch (sample_rate) {
2451 case 8000:
2452 case 11025:
2453 case 12000:
2454 case 16000:
2455 case 22050:
2456 case 24000:
2457 case 32000:
2458 case 44100:
2459 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002460 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002461 break;
2462 default:
vivek mehtadae44712015-07-27 14:13:18 -07002463 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002464 return -EINVAL;
2465 }
2466
2467 return 0;
2468}
2469
Kevin Rocarda325aa22018-04-03 09:15:52 -07002470/** Add a value in a list if not already present.
2471 * @return true if value was successfully inserted or already present,
2472 * false if the list is full and does not contain the value.
2473 */
2474static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
2475 for (size_t i = 0; i < list_length; i++) {
2476 if (list[i] == value) return true; // value is already present
2477 if (list[i] == 0) { // no values in this slot
2478 list[i] = value;
2479 return true; // value inserted
2480 }
2481 }
2482 return false; // could not insert value
2483}
2484
2485/** Add channel_mask in supported_channel_masks if not already present.
2486 * @return true if channel_mask was successfully inserted or already present,
2487 * false if supported_channel_masks is full and does not contain channel_mask.
2488 */
2489static void register_channel_mask(audio_channel_mask_t channel_mask,
2490 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
2491 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
2492 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
2493}
2494
2495/** Add format in supported_formats if not already present.
2496 * @return true if format was successfully inserted or already present,
2497 * false if supported_formats is full and does not contain format.
2498 */
2499static void register_format(audio_format_t format,
2500 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
2501 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
2502 "%s: stream can not declare supporting its format %x", __func__, format);
2503}
2504/** Add sample_rate in supported_sample_rates if not already present.
2505 * @return true if sample_rate was successfully inserted or already present,
2506 * false if supported_sample_rates is full and does not contain sample_rate.
2507 */
2508static void register_sample_rate(uint32_t sample_rate,
2509 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
2510 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
2511 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
2512}
2513
vivek mehtaa68fea62017-06-08 19:04:02 -07002514static size_t get_stream_buffer_size(size_t duration_ms,
2515 uint32_t sample_rate,
2516 audio_format_t format,
2517 int channel_count,
2518 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002519{
2520 size_t size = 0;
2521
vivek mehtaa68fea62017-06-08 19:04:02 -07002522 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002523 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002524 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002525
2526 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002527
Glenn Kasten4f993392014-05-14 07:30:48 -07002528 /* make sure the size is multiple of 32 bytes
2529 * At 48 kHz mono 16-bit PCM:
2530 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2531 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2532 */
2533 size += 0x1f;
2534 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002535
2536 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002537}
2538
2539static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2540{
2541 struct stream_out *out = (struct stream_out *)stream;
2542
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002543 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002544}
2545
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002546static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002547{
2548 return -ENOSYS;
2549}
2550
2551static size_t out_get_buffer_size(const struct audio_stream *stream)
2552{
2553 struct stream_out *out = (struct stream_out *)stream;
2554
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002555 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2556 return out->compr_config.fragment_size;
2557 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002558 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002559 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002560}
2561
2562static uint32_t out_get_channels(const struct audio_stream *stream)
2563{
2564 struct stream_out *out = (struct stream_out *)stream;
2565
2566 return out->channel_mask;
2567}
2568
2569static audio_format_t out_get_format(const struct audio_stream *stream)
2570{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002571 struct stream_out *out = (struct stream_out *)stream;
2572
2573 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002574}
2575
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002576static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002577{
2578 return -ENOSYS;
2579}
2580
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002581/* must be called with out->lock locked */
2582static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002583{
2584 struct stream_out *out = (struct stream_out *)stream;
2585 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002586 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002587
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002588 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002589 if (adev->adm_deregister_stream)
2590 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002591 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002592 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002593 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2594 if (out->pcm) {
2595 pcm_close(out->pcm);
2596 out->pcm = NULL;
2597 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002598 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002599 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002600 out->playback_started = false;
2601 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002602 } else {
2603 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002604 out->gapless_mdata.encoder_delay = 0;
2605 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002606 if (out->compr != NULL) {
2607 compress_close(out->compr);
2608 out->compr = NULL;
2609 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002610 }
Phil Burkbc991042017-02-24 08:06:44 -08002611 if (do_stop) {
2612 stop_output_stream(out);
2613 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002614 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002615 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002616 return 0;
2617}
2618
2619static int out_standby(struct audio_stream *stream)
2620{
2621 struct stream_out *out = (struct stream_out *)stream;
2622
2623 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2624 out->usecase, use_case_table[out->usecase]);
2625
2626 lock_output_stream(out);
2627 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002628 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002629 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002630 return 0;
2631}
2632
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002633static int out_on_error(struct audio_stream *stream)
2634{
2635 struct stream_out *out = (struct stream_out *)stream;
2636 struct audio_device *adev = out->dev;
2637 bool do_standby = false;
2638
2639 lock_output_stream(out);
2640 if (!out->standby) {
2641 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2642 stop_compressed_output_l(out);
2643 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2644 } else
2645 do_standby = true;
2646 }
2647 pthread_mutex_unlock(&out->lock);
2648
2649 if (do_standby)
2650 return out_standby(&out->stream.common);
2651
2652 return 0;
2653}
2654
Andy Hung7401c7c2016-09-21 12:41:21 -07002655static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002656{
Andy Hung7401c7c2016-09-21 12:41:21 -07002657 struct stream_out *out = (struct stream_out *)stream;
2658
2659 // We try to get the lock for consistency,
2660 // but it isn't necessary for these variables.
2661 // If we're not in standby, we may be blocked on a write.
2662 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2663 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2664 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2665
2666 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002667 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002668 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002669
2670 // dump error info
2671 (void)error_log_dump(
2672 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002673
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002674 return 0;
2675}
2676
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002677static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2678{
2679 int ret = 0;
2680 char value[32];
2681 struct compr_gapless_mdata tmp_mdata;
2682
2683 if (!out || !parms) {
2684 return -EINVAL;
2685 }
2686
2687 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2688 if (ret >= 0) {
2689 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2690 } else {
2691 return -EINVAL;
2692 }
2693
2694 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2695 if (ret >= 0) {
2696 tmp_mdata.encoder_padding = atoi(value);
2697 } else {
2698 return -EINVAL;
2699 }
2700
2701 out->gapless_mdata = tmp_mdata;
2702 out->send_new_metadata = 1;
2703 ALOGV("%s new encoder delay %u and padding %u", __func__,
2704 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2705
2706 return 0;
2707}
2708
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002709static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2710{
2711 return out == adev->primary_output || out == adev->voice_tx_output;
2712}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002713
Kevin Rocard1e02c882017-08-09 15:26:07 -07002714static int get_alive_usb_card(struct str_parms* parms) {
2715 int card;
2716 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2717 !audio_extn_usb_alive(card)) {
2718 return card;
2719 }
2720 return -ENODEV;
2721}
2722
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002723static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2724{
2725 struct stream_out *out = (struct stream_out *)stream;
2726 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002727 struct audio_usecase *usecase;
2728 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002729 struct str_parms *parms;
2730 char value[32];
2731 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002732 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002733 int status = 0;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002734 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002735
Eric Laurent2e140aa2016-06-30 17:14:46 -07002736 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002737 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002738 parms = str_parms_create_str(kvpairs);
2739 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2740 if (ret >= 0) {
2741 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002742
Eric Laurenta1478072015-09-21 17:21:52 -07002743 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002744
2745 // The usb driver needs to be closed after usb device disconnection
2746 // otherwise audio is no longer played on the new usb devices.
2747 // By forcing the stream in standby, the usb stack refcount drops to 0
2748 // and the driver is closed.
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002749 if (val == AUDIO_DEVICE_NONE &&
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002750 audio_is_usb_out_device(out->devices)) {
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002751 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2752 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2753 out_standby_l(&out->stream.common);
2754 }
2755 val = AUDIO_DEVICE_OUT_SPEAKER;
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002756 }
2757
Eric Laurent150dbfe2013-02-27 14:31:02 -08002758 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002759
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002760 /*
2761 * When HDMI cable is unplugged the music playback is paused and
2762 * the policy manager sends routing=0. But the audioflinger
2763 * continues to write data until standby time (3sec).
2764 * As the HDMI core is turned off, the write gets blocked.
2765 * Avoid this by routing audio to speaker until standby.
2766 */
2767 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2768 val == AUDIO_DEVICE_NONE) {
2769 val = AUDIO_DEVICE_OUT_SPEAKER;
2770 }
2771
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002772 /*
2773 * When A2DP is disconnected the
2774 * music playback is paused and the policy manager sends routing=0
2775 * But the audioflingercontinues to write data until standby time
2776 * (3sec). As BT is turned off, the write gets blocked.
2777 * Avoid this by routing audio to speaker until standby.
2778 */
2779 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2780 (val == AUDIO_DEVICE_NONE) &&
2781 !audio_extn_a2dp_is_ready()) {
2782 val = AUDIO_DEVICE_OUT_SPEAKER;
2783 }
2784
2785 /* To avoid a2dp to sco overlapping / BT device improper state
2786 * check with BT lib about a2dp streaming support before routing
2787 */
2788 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2789 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002790 if (val & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002791 //combo usecase just by pass a2dp
2792 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2793 bypass_a2dp = true;
2794 } else {
2795 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2796 /* update device to a2dp and don't route as BT returned error
2797 * However it is still possible a2dp routing called because
2798 * of current active device disconnection (like wired headset)
2799 */
2800 out->devices = val;
2801 pthread_mutex_unlock(&out->lock);
2802 pthread_mutex_unlock(&adev->lock);
2803 status = -ENOSYS;
2804 goto routing_fail;
2805 }
2806 }
2807 }
2808
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002809 audio_devices_t new_dev = val;
2810
2811 // Workaround: If routing to an non existing usb device, fail gracefully
2812 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002813 int card;
2814 if (audio_is_usb_out_device(new_dev) &&
2815 (card = get_alive_usb_card(parms)) >= 0) {
2816
2817 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002818 pthread_mutex_unlock(&adev->lock);
2819 pthread_mutex_unlock(&out->lock);
2820 status = -ENOSYS;
2821 goto routing_fail;
2822 }
2823
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002824 /*
2825 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002826 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002827 * the select_devices(). But how do we undo this?
2828 *
2829 * For example, music playback is active on headset (deep-buffer usecase)
2830 * and if we go to ringtones and select a ringtone, low-latency usecase
2831 * will be started on headset+speaker. As we can't enable headset+speaker
2832 * and headset devices at the same time, select_devices() switches the music
2833 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2834 * So when the ringtone playback is completed, how do we undo the same?
2835 *
2836 * We are relying on the out_set_parameters() call on deep-buffer output,
2837 * once the ringtone playback is ended.
2838 * NOTE: We should not check if the current devices are same as new devices.
2839 * Because select_devices() must be called to switch back the music
2840 * playback to headset.
2841 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002842 if (new_dev != AUDIO_DEVICE_NONE) {
2843 bool same_dev = out->devices == new_dev;
2844 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002845
Eric Laurenta7657192014-10-09 21:09:33 -07002846 if (output_drives_call(adev, out)) {
Vignesh Kulothungana5c9da12017-11-10 11:41:24 -08002847 if (!voice_is_call_state_active(adev)) {
Eric Laurenta7657192014-10-09 21:09:33 -07002848 if (adev->mode == AUDIO_MODE_IN_CALL) {
2849 adev->current_call_output = out;
2850 ret = voice_start_call(adev);
2851 }
2852 } else {
2853 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002854 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002855 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002856 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002857
2858 if (!out->standby) {
2859 if (!same_dev) {
2860 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002861 // inform adm before actual routing to prevent glitches.
2862 if (adev->adm_on_routing_change) {
2863 adev->adm_on_routing_change(adev->adm_data,
2864 out->handle);
2865 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002866 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002867 if (!bypass_a2dp) {
2868 select_devices(adev, out->usecase);
2869 } else {
juyuchen9baad392018-06-05 19:02:10 +08002870 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2871 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2872 else
2873 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002874 select_devices(adev, out->usecase);
2875 out->devices = new_dev;
2876 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002877 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002878
2879 // on device switch force swap, lower functions will make sure
2880 // to check if swap is allowed or not.
2881
2882 if (!same_dev)
2883 platform_set_swap_channels(adev, true);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002884
2885 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2886 out->a2dp_compress_mute &&
2887 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
2888 pthread_mutex_lock(&out->compr_mute_lock);
2889 out->a2dp_compress_mute = false;
2890 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
2891 pthread_mutex_unlock(&out->compr_mute_lock);
2892 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002893 }
2894
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002895 }
2896
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002897 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002898 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002899
2900 /*handles device and call state changes*/
2901 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002902 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002903 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002904
2905 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2906 parse_compress_metadata(out, parms);
2907 }
2908
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002909 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002910 ALOGV("%s: exit: code(%d)", __func__, status);
2911 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002912}
2913
Haynes Mathew George569b7482017-05-08 14:44:27 -07002914static bool stream_get_parameter_channels(struct str_parms *query,
2915 struct str_parms *reply,
2916 audio_channel_mask_t *supported_channel_masks) {
2917 int ret = -1;
Andy Hung64fdb452018-09-07 11:25:33 -07002918 char value[ARRAY_SIZE(channels_name_to_enum_table) * 32 /* max channel name size */];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002919 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002920 size_t i, j;
2921
2922 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2923 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002924 value[0] = '\0';
2925 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002926 while (supported_channel_masks[i] != 0) {
2927 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2928 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002929 if (!first) {
2930 strcat(value, "|");
2931 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002932 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002933 first = false;
2934 break;
2935 }
2936 }
2937 i++;
2938 }
2939 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002940 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002941 return ret >= 0;
2942}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002943
Haynes Mathew George569b7482017-05-08 14:44:27 -07002944static bool stream_get_parameter_formats(struct str_parms *query,
2945 struct str_parms *reply,
2946 audio_format_t *supported_formats) {
2947 int ret = -1;
2948 char value[256];
2949 int i;
2950
2951 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2952 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002953 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002954 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002955 case AUDIO_FORMAT_PCM_16_BIT:
2956 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2957 break;
2958 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2959 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2960 break;
2961 case AUDIO_FORMAT_PCM_32_BIT:
2962 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2963 break;
2964 default:
2965 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002966 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002967 break;
2968 }
2969 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002970 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002971 return ret >= 0;
2972}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002973
Haynes Mathew George569b7482017-05-08 14:44:27 -07002974static bool stream_get_parameter_rates(struct str_parms *query,
2975 struct str_parms *reply,
2976 uint32_t *supported_sample_rates) {
2977
2978 int i;
2979 char value[256];
2980 int ret = -1;
2981 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2982 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002983 value[0] = '\0';
2984 i=0;
2985 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002986 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002987 int avail = sizeof(value) - cursor;
2988 ret = snprintf(value + cursor, avail, "%s%d",
2989 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002990 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002991 if (ret < 0 || ret >= avail) {
2992 // if cursor is at the last element of the array
2993 // overwrite with \0 is duplicate work as
2994 // snprintf already put a \0 in place.
2995 // else
2996 // we had space to write the '|' at value[cursor]
2997 // (which will be overwritten) or no space to fill
2998 // the first element (=> cursor == 0)
2999 value[cursor] = '\0';
3000 break;
3001 }
3002 cursor += ret;
3003 ++i;
3004 }
3005 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
3006 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003007 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003008 return ret >= 0;
3009}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003010
Haynes Mathew George569b7482017-05-08 14:44:27 -07003011static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
3012{
3013 struct stream_out *out = (struct stream_out *)stream;
3014 struct str_parms *query = str_parms_create_str(keys);
3015 char *str;
3016 struct str_parms *reply = str_parms_create();
3017 bool replied = false;
3018 ALOGV("%s: enter: keys - %s", __func__, keys);
3019
3020 replied |= stream_get_parameter_channels(query, reply,
3021 &out->supported_channel_masks[0]);
3022 replied |= stream_get_parameter_formats(query, reply,
3023 &out->supported_formats[0]);
3024 replied |= stream_get_parameter_rates(query, reply,
3025 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003026 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003027 str = str_parms_to_str(reply);
3028 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07003029 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003030 }
3031 str_parms_destroy(query);
3032 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07003033 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003034 return str;
3035}
3036
3037static uint32_t out_get_latency(const struct audio_stream_out *stream)
3038{
Haynes Mathew George03c40102016-01-29 17:57:48 -08003039 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003040 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003041 uint32_t latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003042
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003043 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3044 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003045 else if ((out->realtime) ||
3046 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003047 // since the buffer won't be filled up faster than realtime,
3048 // return a smaller number
3049 period_ms = (out->af_period_multiplier * out->config.period_size *
3050 1000) / (out->config.rate);
3051 hw_delay = platform_render_latency(out->usecase)/1000;
3052 return period_ms + hw_delay;
3053 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003054
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003055 latency = (out->config.period_count * out->config.period_size * 1000) /
3056 (out->config.rate);
3057
3058 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
3059 latency += audio_extn_a2dp_get_encoder_latency();
3060
3061 return latency;
3062}
3063
3064static int set_compr_volume(struct audio_stream_out *stream, float left,
3065 float right)
3066{
3067 struct stream_out *out = (struct stream_out *)stream;
3068 int volume[2];
3069 char mixer_ctl_name[128];
3070 struct audio_device *adev = out->dev;
3071 struct mixer_ctl *ctl;
3072 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
3073 PCM_PLAYBACK);
3074
3075 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3076 "Compress Playback %d Volume", pcm_device_id);
3077 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3078 if (!ctl) {
3079 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3080 __func__, mixer_ctl_name);
3081 return -EINVAL;
3082 }
3083 ALOGV("%s: ctl for mixer cmd - %s, left %f, right %f",
3084 __func__, mixer_ctl_name, left, right);
3085 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3086 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3087 mixer_ctl_set_array(ctl, volume, sizeof(volume) / sizeof(volume[0]));
3088
3089 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003090}
3091
3092static int out_set_volume(struct audio_stream_out *stream, float left,
3093 float right)
3094{
Eric Laurenta9024de2013-04-04 09:19:12 -07003095 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003096 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003097
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003098 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07003099 /* only take left channel into account: the API is for stereo anyway */
3100 out->muted = (left == 0.0f);
3101 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003102 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003103 pthread_mutex_lock(&out->compr_mute_lock);
3104 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
3105 if (!out->a2dp_compress_mute)
3106 ret = set_compr_volume(stream, left, right);
3107 out->volume_l = left;
3108 out->volume_r = right;
3109 pthread_mutex_unlock(&out->compr_mute_lock);
3110 return ret;
vivek mehtaa68fea62017-06-08 19:04:02 -07003111 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07003112 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
3113 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
3114 if (!out->standby) {
3115 // if in standby, cached volume will be sent after stream is opened
3116 audio_extn_utils_send_app_type_gain(out->dev,
3117 out->app_type_cfg.app_type,
3118 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07003119 }
vivek mehtaa68fea62017-06-08 19:04:02 -07003120 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07003121 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003122
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003123 return -ENOSYS;
3124}
3125
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003126// note: this call is safe only if the stream_cb is
3127// removed first in close_output_stream (as is done now).
3128static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3129{
3130 if (!stream || !parms)
3131 return;
3132
3133 struct stream_out *out = (struct stream_out *)stream;
3134 struct audio_device *adev = out->dev;
3135
3136 card_status_t status;
3137 int card;
3138 if (parse_snd_card_status(parms, &card, &status) < 0)
3139 return;
3140
3141 pthread_mutex_lock(&adev->lock);
3142 bool valid_cb = (card == adev->snd_card);
3143 pthread_mutex_unlock(&adev->lock);
3144
3145 if (!valid_cb)
3146 return;
3147
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003148 lock_output_stream(out);
3149 if (out->card_status != status)
3150 out->card_status = status;
3151 pthread_mutex_unlock(&out->lock);
3152
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07003153 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
3154 use_case_table[out->usecase],
3155 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3156
3157 if (status == CARD_STATUS_OFFLINE)
3158 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003159
3160 return;
3161}
3162
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003163#ifdef NO_AUDIO_OUT
3164static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05003165 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003166{
3167 struct stream_out *out = (struct stream_out *)stream;
3168
3169 /* No Output device supported other than BT for playback.
3170 * Sleep for the amount of buffer duration
3171 */
Eric Laurenta1478072015-09-21 17:21:52 -07003172 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05003173 usleep(bytes * 1000000 / audio_stream_out_frame_size(
3174 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003175 out_get_sample_rate(&out->stream.common));
3176 pthread_mutex_unlock(&out->lock);
3177 return bytes;
3178}
3179#endif
3180
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003181static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3182 size_t bytes)
3183{
3184 struct stream_out *out = (struct stream_out *)stream;
3185 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07003186 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07003187 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003188
Eric Laurenta1478072015-09-21 17:21:52 -07003189 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07003190 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07003191 const size_t frame_size = audio_stream_out_frame_size(stream);
3192 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07003193
Eric Laurent0e46adf2016-12-16 12:49:24 -08003194 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3195 error_code = ERROR_CODE_WRITE;
3196 goto exit;
3197 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003198
3199 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3200 (audio_extn_a2dp_is_suspended())) {
juyuchen9baad392018-06-05 19:02:10 +08003201 if (!(out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003202 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3203 ret = -EIO;
3204 goto exit;
3205 }
3206 }
3207 }
3208
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003209 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003210 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003211 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003212 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07003213
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003214 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003215 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003216 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07003217 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003218 goto exit;
3219 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07003220
vivek mehta40125092017-08-21 18:48:51 -07003221 // after standby always force set last known cal step
3222 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
3223 ALOGD("%s: retry previous failed cal level set", __func__);
3224 send_gain_dep_calibration_l();
3225 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003226 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003227
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003228 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003229 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003230 if (out->send_new_metadata) {
3231 ALOGVV("send new gapless metadata");
3232 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3233 out->send_new_metadata = 0;
3234 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003235 unsigned int avail;
3236 struct timespec tstamp;
3237 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
3238 /* Do not limit write size if the available frames count is unknown */
3239 if (ret != 0) {
3240 avail = bytes;
3241 }
3242 if (avail == 0) {
3243 ret = 0;
3244 } else {
3245 if (avail > bytes) {
3246 avail = bytes;
3247 }
3248 ret = compress_write(out->compr, buffer, avail);
3249 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
3250 __func__, avail, ret);
3251 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003252
Eric Laurent6e895242013-09-05 16:10:57 -07003253 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003254 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
3255 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003256 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003257 compress_start(out->compr);
3258 out->playback_started = 1;
3259 out->offload_state = OFFLOAD_STATE_PLAYING;
3260 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003261 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07003262 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07003263 } else {
3264 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07003265 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003266 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07003267 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003268 return ret;
3269 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07003270 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003271 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003272 size_t bytes_to_write = bytes;
3273
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003274 if (out->muted)
3275 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07003276 // FIXME: this can be removed once audio flinger mixer supports mono output
Nadav Bar3d72cfc2018-01-07 12:19:24 +02003277 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP || out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003278 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3279 int16_t *src = (int16_t *)buffer;
3280 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003281
Eric Laurentad2dde92017-09-20 18:27:31 -07003282 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
3283 out->format != AUDIO_FORMAT_PCM_16_BIT,
3284 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003285
Eric Laurentad2dde92017-09-20 18:27:31 -07003286 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
3287 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
3288 }
3289 bytes_to_write /= 2;
3290 }
3291 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes_to_write);
3292
Glenn Kasten5a59dff2018-02-22 08:05:35 -08003293 long ns = (frames * (int64_t) NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003294 request_out_focus(out, ns);
3295
3296 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3297 if (use_mmap)
Eric Laurentad2dde92017-09-20 18:27:31 -07003298 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003299 else
Eric Laurentad2dde92017-09-20 18:27:31 -07003300 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003301
Haynes Mathew George03c40102016-01-29 17:57:48 -08003302 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07003303 } else {
3304 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003305 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003306 }
3307
3308exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07003309 // For PCM we always consume the buffer and return #bytes regardless of ret.
3310 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003311 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07003312 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003313 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07003314
Andy Hung7401c7c2016-09-21 12:41:21 -07003315 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07003316 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07003317 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3318 ALOGE_IF(out->pcm != NULL,
3319 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07003320 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003321 // usleep not guaranteed for values over 1 second but we don't limit here.
3322 }
3323 }
Andy Hungda9b56b2016-09-16 20:06:35 -07003324
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003325 pthread_mutex_unlock(&out->lock);
3326
3327 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07003328 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003329 if (sleeptime_us != 0)
3330 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003331 }
3332 return bytes;
3333}
3334
3335static int out_get_render_position(const struct audio_stream_out *stream,
3336 uint32_t *dsp_frames)
3337{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003338 struct stream_out *out = (struct stream_out *)stream;
3339 *dsp_frames = 0;
3340 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07003341 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003342 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003343 unsigned long frames = 0;
3344 // TODO: check return value
3345 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
3346 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003347 ALOGVV("%s rendered frames %d sample_rate %d",
3348 __func__, *dsp_frames, out->sample_rate);
3349 }
3350 pthread_mutex_unlock(&out->lock);
3351 return 0;
3352 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003353 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003354}
3355
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003356static int out_add_audio_effect(const struct audio_stream *stream __unused,
3357 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003358{
3359 return 0;
3360}
3361
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003362static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3363 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003364{
3365 return 0;
3366}
3367
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003368static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3369 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003370{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003371 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003372}
3373
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003374static int out_get_presentation_position(const struct audio_stream_out *stream,
3375 uint64_t *frames, struct timespec *timestamp)
3376{
3377 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003378 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07003379 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003380
Eric Laurenta1478072015-09-21 17:21:52 -07003381 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003382
Eric Laurent949a0892013-09-20 09:20:13 -07003383 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3384 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003385 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07003386 compress_get_tstamp(out->compr, &dsp_frames,
3387 &out->sample_rate);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003388 // Adjustment accounts for A2DP encoder latency with offload usecases
3389 // Note: Encoder latency is returned in ms.
3390 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3391 unsigned long offset =
3392 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3393 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
3394 }
Eric Laurent949a0892013-09-20 09:20:13 -07003395 ALOGVV("%s rendered frames %ld sample_rate %d",
3396 __func__, dsp_frames, out->sample_rate);
3397 *frames = dsp_frames;
3398 ret = 0;
3399 /* this is the best we can do */
3400 clock_gettime(CLOCK_MONOTONIC, timestamp);
3401 }
3402 } else {
3403 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07003404 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003405 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3406 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003407 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003408 // This adjustment accounts for buffering after app processor.
3409 // It is based on estimated DSP latency per use case, rather than exact.
3410 signed_frames -=
3411 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3412
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003413 // Adjustment accounts for A2DP encoder latency with non-offload usecases
3414 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3415 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3416 signed_frames -=
3417 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3418 }
3419
Eric Laurent949a0892013-09-20 09:20:13 -07003420 // It would be unusual for this value to be negative, but check just in case ...
3421 if (signed_frames >= 0) {
3422 *frames = signed_frames;
3423 ret = 0;
3424 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003425 }
3426 }
3427 }
3428
3429 pthread_mutex_unlock(&out->lock);
3430
3431 return ret;
3432}
3433
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003434static int out_set_callback(struct audio_stream_out *stream,
3435 stream_callback_t callback, void *cookie)
3436{
3437 struct stream_out *out = (struct stream_out *)stream;
3438
3439 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003440 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003441 out->offload_callback = callback;
3442 out->offload_cookie = cookie;
3443 pthread_mutex_unlock(&out->lock);
3444 return 0;
3445}
3446
3447static int out_pause(struct audio_stream_out* stream)
3448{
3449 struct stream_out *out = (struct stream_out *)stream;
3450 int status = -ENOSYS;
3451 ALOGV("%s", __func__);
3452 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003453 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003454 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
3455 status = compress_pause(out->compr);
3456 out->offload_state = OFFLOAD_STATE_PAUSED;
3457 }
3458 pthread_mutex_unlock(&out->lock);
3459 }
3460 return status;
3461}
3462
3463static int out_resume(struct audio_stream_out* stream)
3464{
3465 struct stream_out *out = (struct stream_out *)stream;
3466 int status = -ENOSYS;
3467 ALOGV("%s", __func__);
3468 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3469 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07003470 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003471 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
3472 status = compress_resume(out->compr);
3473 out->offload_state = OFFLOAD_STATE_PLAYING;
3474 }
3475 pthread_mutex_unlock(&out->lock);
3476 }
3477 return status;
3478}
3479
3480static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3481{
3482 struct stream_out *out = (struct stream_out *)stream;
3483 int status = -ENOSYS;
3484 ALOGV("%s", __func__);
3485 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003486 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003487 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3488 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3489 else
3490 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3491 pthread_mutex_unlock(&out->lock);
3492 }
3493 return status;
3494}
3495
3496static int out_flush(struct audio_stream_out* stream)
3497{
3498 struct stream_out *out = (struct stream_out *)stream;
3499 ALOGV("%s", __func__);
3500 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003501 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003502 stop_compressed_output_l(out);
3503 pthread_mutex_unlock(&out->lock);
3504 return 0;
3505 }
3506 return -ENOSYS;
3507}
3508
Eric Laurent0e46adf2016-12-16 12:49:24 -08003509static int out_stop(const struct audio_stream_out* stream)
3510{
3511 struct stream_out *out = (struct stream_out *)stream;
3512 struct audio_device *adev = out->dev;
3513 int ret = -ENOSYS;
3514
3515 ALOGV("%s", __func__);
3516 pthread_mutex_lock(&adev->lock);
3517 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3518 out->playback_started && out->pcm != NULL) {
3519 pcm_stop(out->pcm);
3520 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08003521 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003522 }
3523 pthread_mutex_unlock(&adev->lock);
3524 return ret;
3525}
3526
3527static int out_start(const struct audio_stream_out* stream)
3528{
3529 struct stream_out *out = (struct stream_out *)stream;
3530 struct audio_device *adev = out->dev;
3531 int ret = -ENOSYS;
3532
3533 ALOGV("%s", __func__);
3534 pthread_mutex_lock(&adev->lock);
3535 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3536 !out->playback_started && out->pcm != NULL) {
3537 ret = start_output_stream(out);
3538 if (ret == 0) {
3539 out->playback_started = true;
3540 }
3541 }
3542 pthread_mutex_unlock(&adev->lock);
3543 return ret;
3544}
3545
Phil Burkbc991042017-02-24 08:06:44 -08003546/*
3547 * Modify config->period_count based on min_size_frames
3548 */
3549static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
3550{
3551 int periodCountRequested = (min_size_frames + config->period_size - 1)
3552 / config->period_size;
3553 int periodCount = MMAP_PERIOD_COUNT_MIN;
3554
3555 ALOGV("%s original config.period_size = %d config.period_count = %d",
3556 __func__, config->period_size, config->period_count);
3557
3558 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
3559 periodCount *= 2;
3560 }
3561 config->period_count = periodCount;
3562
3563 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
3564}
3565
Eric Laurent0e46adf2016-12-16 12:49:24 -08003566static int out_create_mmap_buffer(const struct audio_stream_out *stream,
3567 int32_t min_size_frames,
3568 struct audio_mmap_buffer_info *info)
3569{
3570 struct stream_out *out = (struct stream_out *)stream;
3571 struct audio_device *adev = out->dev;
3572 int ret = 0;
3573 unsigned int offset1;
3574 unsigned int frames1;
3575 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003576 uint32_t mmap_size;
3577 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003578
3579 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003580 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003581 pthread_mutex_lock(&adev->lock);
3582
3583 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003584 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003585 ret = -EINVAL;
3586 goto exit;
3587 }
3588 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003589 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003590 ret = -ENOSYS;
3591 goto exit;
3592 }
3593 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3594 if (out->pcm_device_id < 0) {
3595 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3596 __func__, out->pcm_device_id, out->usecase);
3597 ret = -EINVAL;
3598 goto exit;
3599 }
Phil Burkbc991042017-02-24 08:06:44 -08003600
3601 adjust_mmap_period_count(&out->config, min_size_frames);
3602
Eric Laurent0e46adf2016-12-16 12:49:24 -08003603 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3604 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3605 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3606 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3607 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3608 step = "open";
3609 ret = -ENODEV;
3610 goto exit;
3611 }
3612 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3613 if (ret < 0) {
3614 step = "begin";
3615 goto exit;
3616 }
3617 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003618 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003619 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003620 ret = platform_get_mmap_data_fd(adev->platform,
3621 out->pcm_device_id, 0 /*playback*/,
3622 &info->shared_memory_fd,
3623 &mmap_size);
3624 if (ret < 0) {
3625 // Fall back to non exclusive mode
3626 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3627 } else {
3628 if (mmap_size < buffer_size) {
3629 step = "mmap";
3630 goto exit;
3631 }
3632 // FIXME: indicate exclusive mode support by returning a negative buffer size
3633 info->buffer_size_frames *= -1;
3634 }
3635 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003636
3637 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3638 if (ret < 0) {
3639 step = "commit";
3640 goto exit;
3641 }
Phil Burkbc991042017-02-24 08:06:44 -08003642
3643 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003644 ret = 0;
3645
3646 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3647 __func__, info->shared_memory_address, info->buffer_size_frames);
3648
3649exit:
3650 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003651 if (out->pcm == NULL) {
3652 ALOGE("%s: %s - %d", __func__, step, ret);
3653 } else {
3654 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003655 pcm_close(out->pcm);
3656 out->pcm = NULL;
3657 }
3658 }
3659 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003660 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003661 return ret;
3662}
3663
3664static int out_get_mmap_position(const struct audio_stream_out *stream,
3665 struct audio_mmap_position *position)
3666{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003667 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003668 struct stream_out *out = (struct stream_out *)stream;
3669 ALOGVV("%s", __func__);
3670 if (position == NULL) {
3671 return -EINVAL;
3672 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003673 lock_output_stream(out);
3674 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3675 out->pcm == NULL) {
3676 ret = -ENOSYS;
3677 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003678 }
3679
3680 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003681 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003682 if (ret < 0) {
3683 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003684 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003685 }
Andy Hungfc044e12017-03-20 09:24:22 -07003686 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003687exit:
3688 pthread_mutex_unlock(&out->lock);
3689 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003690}
3691
3692
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003693/** audio_stream_in implementation **/
3694static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3695{
3696 struct stream_in *in = (struct stream_in *)stream;
3697
3698 return in->config.rate;
3699}
3700
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003701static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003702{
3703 return -ENOSYS;
3704}
3705
3706static size_t in_get_buffer_size(const struct audio_stream *stream)
3707{
3708 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003709 return in->config.period_size * in->af_period_multiplier *
3710 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003711}
3712
3713static uint32_t in_get_channels(const struct audio_stream *stream)
3714{
3715 struct stream_in *in = (struct stream_in *)stream;
3716
3717 return in->channel_mask;
3718}
3719
vivek mehta4ed66e62016-04-15 23:33:34 -07003720static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003721{
vivek mehta4ed66e62016-04-15 23:33:34 -07003722 struct stream_in *in = (struct stream_in *)stream;
3723 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003724}
3725
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003726static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003727{
3728 return -ENOSYS;
3729}
3730
3731static int in_standby(struct audio_stream *stream)
3732{
3733 struct stream_in *in = (struct stream_in *)stream;
3734 struct audio_device *adev = in->dev;
3735 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003736 bool do_stop = true;
3737
Eric Laurent994a6932013-07-17 11:51:42 -07003738 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003739
3740 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003741
3742 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003743 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003744 audio_extn_sound_trigger_stop_lab(in);
3745 in->standby = true;
3746 }
3747
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003748 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003749 if (adev->adm_deregister_stream)
3750 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3751
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003752 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003753 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003754 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003755 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003756 in->capture_started = false;
3757 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003758 if (in->pcm) {
3759 pcm_close(in->pcm);
3760 in->pcm = NULL;
3761 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003762 adev->enable_voicerx = false;
3763 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003764 if (do_stop) {
3765 status = stop_input_stream(in);
3766 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003767 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003768 }
3769 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003770 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003771 return status;
3772}
3773
Andy Hungd13f0d32017-06-12 13:58:37 -07003774static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003775{
Andy Hungd13f0d32017-06-12 13:58:37 -07003776 struct stream_in *in = (struct stream_in *)stream;
3777
3778 // We try to get the lock for consistency,
3779 // but it isn't necessary for these variables.
3780 // If we're not in standby, we may be blocked on a read.
3781 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3782 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3783 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3784 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3785
3786 if (locked) {
3787 pthread_mutex_unlock(&in->lock);
3788 }
3789
3790 // dump error info
3791 (void)error_log_dump(
3792 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003793 return 0;
3794}
3795
3796static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3797{
3798 struct stream_in *in = (struct stream_in *)stream;
3799 struct audio_device *adev = in->dev;
3800 struct str_parms *parms;
3801 char *str;
3802 char value[32];
3803 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003804 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003805
Eric Laurent994a6932013-07-17 11:51:42 -07003806 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003807 parms = str_parms_create_str(kvpairs);
3808
3809 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3810
Eric Laurenta1478072015-09-21 17:21:52 -07003811 lock_input_stream(in);
3812
Eric Laurent150dbfe2013-02-27 14:31:02 -08003813 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003814 if (ret >= 0) {
3815 val = atoi(value);
3816 /* no audio source uses val == 0 */
3817 if ((in->source != val) && (val != 0)) {
3818 in->source = val;
3819 }
3820 }
3821
3822 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003823
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003824 if (ret >= 0) {
3825 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003826 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003827
3828 // Workaround: If routing to an non existing usb device, fail gracefully
3829 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003830 int card;
3831 if (audio_is_usb_in_device(val) &&
3832 (card = get_alive_usb_card(parms)) >= 0) {
3833
3834 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003835 status = -ENOSYS;
3836 } else {
3837
3838 in->device = val;
3839 /* If recording is in progress, change the tx device to new device */
3840 if (!in->standby) {
3841 ALOGV("update input routing change");
3842 // inform adm before actual routing to prevent glitches.
3843 if (adev->adm_on_routing_change) {
3844 adev->adm_on_routing_change(adev->adm_data,
3845 in->capture_handle);
3846 }
3847 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003848 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003849 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003850 }
3851 }
3852
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003853 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003854 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003855
3856 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003857 ALOGV("%s: exit: status(%d)", __func__, status);
3858 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003859}
3860
Haynes Mathew George569b7482017-05-08 14:44:27 -07003861static char* in_get_parameters(const struct audio_stream *stream,
3862 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003863{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003864 struct stream_in *in = (struct stream_in *)stream;
3865 struct str_parms *query = str_parms_create_str(keys);
3866 char *str;
3867 struct str_parms *reply = str_parms_create();
3868 bool replied = false;
3869
3870 ALOGV("%s: enter: keys - %s", __func__, keys);
3871 replied |= stream_get_parameter_channels(query, reply,
3872 &in->supported_channel_masks[0]);
3873 replied |= stream_get_parameter_formats(query, reply,
3874 &in->supported_formats[0]);
3875 replied |= stream_get_parameter_rates(query, reply,
3876 &in->supported_sample_rates[0]);
3877 if (replied) {
3878 str = str_parms_to_str(reply);
3879 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003880 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003881 }
3882 str_parms_destroy(query);
3883 str_parms_destroy(reply);
3884 ALOGV("%s: exit: returns - %s", __func__, str);
3885 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003886}
3887
Eric Laurent51f3c662018-04-10 18:21:34 -07003888static int in_set_gain(struct audio_stream_in *stream, float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003889{
Eric Laurent51f3c662018-04-10 18:21:34 -07003890 struct stream_in *in = (struct stream_in *)stream;
3891 char mixer_ctl_name[128];
3892 struct mixer_ctl *ctl;
3893 int ctl_value;
3894
3895 ALOGV("%s: gain %f", __func__, gain);
3896
3897 if (stream == NULL)
3898 return -EINVAL;
3899
3900 /* in_set_gain() only used to silence MMAP capture for now */
3901 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
3902 return -ENOSYS;
3903
3904 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
3905
3906 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
3907 if (!ctl) {
3908 ALOGW("%s: Could not get ctl for mixer cmd - %s",
3909 __func__, mixer_ctl_name);
3910 return -ENOSYS;
3911 }
3912
3913 if (gain < RECORD_GAIN_MIN)
3914 gain = RECORD_GAIN_MIN;
3915 else if (gain > RECORD_GAIN_MAX)
3916 gain = RECORD_GAIN_MAX;
3917 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
3918
3919 mixer_ctl_set_value(ctl, 0, ctl_value);
3920 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003921}
3922
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003923static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3924{
3925 if (!stream || !parms)
3926 return;
3927
3928 struct stream_in *in = (struct stream_in *)stream;
3929 struct audio_device *adev = in->dev;
3930
3931 card_status_t status;
3932 int card;
3933 if (parse_snd_card_status(parms, &card, &status) < 0)
3934 return;
3935
3936 pthread_mutex_lock(&adev->lock);
3937 bool valid_cb = (card == adev->snd_card);
3938 pthread_mutex_unlock(&adev->lock);
3939
3940 if (!valid_cb)
3941 return;
3942
3943 lock_input_stream(in);
3944 if (in->card_status != status)
3945 in->card_status = status;
3946 pthread_mutex_unlock(&in->lock);
3947
3948 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3949 use_case_table[in->usecase],
3950 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3951
3952 // a better solution would be to report error back to AF and let
3953 // it put the stream to standby
3954 if (status == CARD_STATUS_OFFLINE)
3955 in_standby(&in->stream.common);
3956
3957 return;
3958}
3959
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003960static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3961 size_t bytes)
3962{
3963 struct stream_in *in = (struct stream_in *)stream;
3964 struct audio_device *adev = in->dev;
3965 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003966 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003967 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003968
Eric Laurenta1478072015-09-21 17:21:52 -07003969 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003970 const size_t frame_size = audio_stream_in_frame_size(stream);
3971 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003972
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003973 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003974 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003975 /* Read from sound trigger HAL */
3976 audio_extn_sound_trigger_read(in, buffer, bytes);
3977 pthread_mutex_unlock(&in->lock);
3978 return bytes;
3979 }
3980
Eric Laurent0e46adf2016-12-16 12:49:24 -08003981 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3982 ret = -ENOSYS;
3983 goto exit;
3984 }
3985
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003986 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003987 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003988 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003989 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003990 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003991 goto exit;
3992 }
3993 in->standby = 0;
3994 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003995
Andy Hungd13f0d32017-06-12 13:58:37 -07003996 // errors that occur here are read errors.
3997 error_code = ERROR_CODE_READ;
3998
Haynes Mathew George03c40102016-01-29 17:57:48 -08003999 //what's the duration requested by the client?
4000 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
4001 in->config.rate;
4002 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004003
Haynes Mathew George03c40102016-01-29 17:57:48 -08004004 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004005 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08004006 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004007 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07004008 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004009 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004010 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004011 if (ret < 0) {
4012 ALOGE("Failed to read w/err %s", strerror(errno));
4013 ret = -errno;
4014 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004015 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4016 if (bytes % 4 == 0) {
4017 /* data from DSP comes in 24_8 format, convert it to 8_24 */
4018 int_buf_stream = buffer;
4019 for (size_t itt=0; itt < bytes/4 ; itt++) {
4020 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07004021 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004022 } else {
4023 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
4024 ret = -EINVAL;
4025 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07004026 }
4027 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004028 }
4029
Haynes Mathew George03c40102016-01-29 17:57:48 -08004030 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004031
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004032 /*
4033 * Instead of writing zeroes here, we could trust the hardware
4034 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004035 * 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 -08004036 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08004037 if (ret == 0 && adev->mic_muted &&
4038 !voice_is_in_call_rec_stream(in) &&
4039 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004040 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07004041 in->frames_muted += frames;
4042 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004043
4044exit:
4045 pthread_mutex_unlock(&in->lock);
4046
4047 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07004048 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004049 in_standby(&in->stream.common);
4050 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07004051 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08004052 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07004053 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08004054 }
4055 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07004056 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004057 }
4058 return bytes;
4059}
4060
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004061static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004062{
4063 return 0;
4064}
4065
Andy Hung6ebe5962016-01-15 17:46:57 -08004066static int in_get_capture_position(const struct audio_stream_in *stream,
4067 int64_t *frames, int64_t *time)
4068{
4069 if (stream == NULL || frames == NULL || time == NULL) {
4070 return -EINVAL;
4071 }
4072 struct stream_in *in = (struct stream_in *)stream;
4073 int ret = -ENOSYS;
4074
4075 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08004076 // note: ST sessions do not close the alsa pcm driver synchronously
4077 // on standby. Therefore, we may return an error even though the
4078 // pcm stream is still opened.
4079 if (in->standby) {
4080 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
4081 "%s stream in standby but pcm not NULL for non ST session", __func__);
4082 goto exit;
4083 }
Andy Hung6ebe5962016-01-15 17:46:57 -08004084 if (in->pcm) {
4085 struct timespec timestamp;
4086 unsigned int avail;
4087 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
4088 *frames = in->frames_read + avail;
4089 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
4090 ret = 0;
4091 }
4092 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08004093exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08004094 pthread_mutex_unlock(&in->lock);
4095 return ret;
4096}
4097
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004098static int add_remove_audio_effect(const struct audio_stream *stream,
4099 effect_handle_t effect,
4100 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004101{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004102 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004103 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004104 int status = 0;
4105 effect_descriptor_t desc;
4106
4107 status = (*effect)->get_descriptor(effect, &desc);
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004108 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
4109
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004110 if (status != 0)
4111 return status;
4112
Eric Laurenta1478072015-09-21 17:21:52 -07004113 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004114 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07004115 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07004116 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07004117 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004118 in->enable_aec != enable &&
4119 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
4120 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004121 if (!enable)
4122 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07004123 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
4124 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
4125 adev->enable_voicerx = enable;
4126 struct audio_usecase *usecase;
4127 struct listnode *node;
4128 list_for_each(node, &adev->usecase_list) {
4129 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07004130 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07004131 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05004132 }
4133 }
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004134 if (!in->standby
4135 && enable_disable_effect(in->dev, in, EFFECT_AEC, enable) == -ENOSYS)
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004136 select_devices(in->dev, in->usecase);
4137 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07004138 if (in->enable_ns != enable &&
4139 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
4140 in->enable_ns = enable;
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004141 if (!in->standby) {
4142 if (in->source != AUDIO_SOURCE_VOICE_COMMUNICATION
4143 || enable_disable_effect(in->dev, in, EFFECT_NS, enable) == -ENOSYS)
4144 select_devices(in->dev, in->usecase);
4145 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07004146 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004147 pthread_mutex_unlock(&in->dev->lock);
4148 pthread_mutex_unlock(&in->lock);
4149
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004150 return 0;
4151}
4152
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004153static int in_add_audio_effect(const struct audio_stream *stream,
4154 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004155{
Eric Laurent994a6932013-07-17 11:51:42 -07004156 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004157 return add_remove_audio_effect(stream, effect, true);
4158}
4159
4160static int in_remove_audio_effect(const struct audio_stream *stream,
4161 effect_handle_t effect)
4162{
Eric Laurent994a6932013-07-17 11:51:42 -07004163 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004164 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004165}
4166
Eric Laurent0e46adf2016-12-16 12:49:24 -08004167static int in_stop(const struct audio_stream_in* stream)
4168{
4169 struct stream_in *in = (struct stream_in *)stream;
4170 struct audio_device *adev = in->dev;
4171
4172 int ret = -ENOSYS;
4173 ALOGV("%s", __func__);
4174 pthread_mutex_lock(&adev->lock);
4175 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4176 in->capture_started && in->pcm != NULL) {
4177 pcm_stop(in->pcm);
4178 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08004179 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004180 }
4181 pthread_mutex_unlock(&adev->lock);
4182 return ret;
4183}
4184
4185static int in_start(const struct audio_stream_in* stream)
4186{
4187 struct stream_in *in = (struct stream_in *)stream;
4188 struct audio_device *adev = in->dev;
4189 int ret = -ENOSYS;
4190
4191 ALOGV("%s in %p", __func__, in);
4192 pthread_mutex_lock(&adev->lock);
4193 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4194 !in->capture_started && in->pcm != NULL) {
4195 if (!in->capture_started) {
4196 ret = start_input_stream(in);
4197 if (ret == 0) {
4198 in->capture_started = true;
4199 }
4200 }
4201 }
4202 pthread_mutex_unlock(&adev->lock);
4203 return ret;
4204}
4205
4206static int in_create_mmap_buffer(const struct audio_stream_in *stream,
4207 int32_t min_size_frames,
4208 struct audio_mmap_buffer_info *info)
4209{
4210 struct stream_in *in = (struct stream_in *)stream;
4211 struct audio_device *adev = in->dev;
4212 int ret = 0;
4213 unsigned int offset1;
4214 unsigned int frames1;
4215 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07004216 uint32_t mmap_size;
4217 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004218
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004219 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004220 pthread_mutex_lock(&adev->lock);
4221 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08004222
Eric Laurent0e46adf2016-12-16 12:49:24 -08004223 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004224 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004225 ret = -EINVAL;
4226 goto exit;
4227 }
4228 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08004229 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004230 ALOGV("%s in %p", __func__, in);
4231 ret = -ENOSYS;
4232 goto exit;
4233 }
4234 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
4235 if (in->pcm_device_id < 0) {
4236 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4237 __func__, in->pcm_device_id, in->usecase);
4238 ret = -EINVAL;
4239 goto exit;
4240 }
Phil Burkbc991042017-02-24 08:06:44 -08004241
4242 adjust_mmap_period_count(&in->config, min_size_frames);
4243
Eric Laurent0e46adf2016-12-16 12:49:24 -08004244 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4245 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
4246 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
4247 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
4248 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
4249 step = "open";
4250 ret = -ENODEV;
4251 goto exit;
4252 }
4253
4254 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
4255 if (ret < 0) {
4256 step = "begin";
4257 goto exit;
4258 }
4259 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07004260 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004261 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07004262 ret = platform_get_mmap_data_fd(adev->platform,
4263 in->pcm_device_id, 1 /*capture*/,
4264 &info->shared_memory_fd,
4265 &mmap_size);
4266 if (ret < 0) {
4267 // Fall back to non exclusive mode
4268 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
4269 } else {
4270 if (mmap_size < buffer_size) {
4271 step = "mmap";
4272 goto exit;
4273 }
4274 // FIXME: indicate exclusive mode support by returning a negative buffer size
4275 info->buffer_size_frames *= -1;
4276 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08004277
Haynes Mathew George96483a22017-03-28 14:52:47 -07004278 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004279
4280 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4281 if (ret < 0) {
4282 step = "commit";
4283 goto exit;
4284 }
4285
Phil Burkbc991042017-02-24 08:06:44 -08004286 in->standby = false;
4287 ret = 0;
4288
Eric Laurent0e46adf2016-12-16 12:49:24 -08004289 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4290 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004291
4292exit:
4293 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004294 if (in->pcm == NULL) {
4295 ALOGE("%s: %s - %d", __func__, step, ret);
4296 } else {
4297 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08004298 pcm_close(in->pcm);
4299 in->pcm = NULL;
4300 }
4301 }
4302 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004303 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004304 return ret;
4305}
4306
4307static int in_get_mmap_position(const struct audio_stream_in *stream,
4308 struct audio_mmap_position *position)
4309{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004310 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004311 struct stream_in *in = (struct stream_in *)stream;
4312 ALOGVV("%s", __func__);
4313 if (position == NULL) {
4314 return -EINVAL;
4315 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004316 lock_input_stream(in);
4317 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
4318 in->pcm == NULL) {
4319 ret = -ENOSYS;
4320 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004321 }
4322 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004323 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004324 if (ret < 0) {
4325 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004326 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004327 }
Andy Hungfc044e12017-03-20 09:24:22 -07004328 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004329exit:
4330 pthread_mutex_unlock(&in->lock);
4331 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004332}
4333
jiabin8962a4d2018-03-19 18:21:24 -07004334static int in_get_active_microphones(const struct audio_stream_in *stream,
4335 struct audio_microphone_characteristic_t *mic_array,
4336 size_t *mic_count) {
4337 struct stream_in *in = (struct stream_in *)stream;
4338 struct audio_device *adev = in->dev;
4339 ALOGVV("%s", __func__);
4340
4341 lock_input_stream(in);
4342 pthread_mutex_lock(&adev->lock);
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004343 int ret = platform_get_active_microphones(adev->platform,
jiabin8962a4d2018-03-19 18:21:24 -07004344 audio_channel_count_from_in_mask(in->channel_mask),
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004345 in->usecase, mic_array, mic_count);
jiabin8962a4d2018-03-19 18:21:24 -07004346 pthread_mutex_unlock(&adev->lock);
4347 pthread_mutex_unlock(&in->lock);
4348
4349 return ret;
4350}
4351
4352static int adev_get_microphones(const struct audio_hw_device *dev,
4353 struct audio_microphone_characteristic_t *mic_array,
4354 size_t *mic_count) {
4355 struct audio_device *adev = (struct audio_device *)dev;
4356 ALOGVV("%s", __func__);
4357
4358 pthread_mutex_lock(&adev->lock);
4359 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
4360 pthread_mutex_unlock(&adev->lock);
4361
4362 return ret;
4363}
Eric Laurent0e46adf2016-12-16 12:49:24 -08004364
Paul McLean57530d52018-12-17 08:24:21 -07004365static int in_set_microphone_direction(const struct audio_stream_in *stream,
4366 audio_microphone_direction_t dir) {
4367 (void)stream;
4368 (void)dir;
4369 ALOGVV("%s", __func__);
4370 return -ENOSYS;
4371}
4372
4373static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
4374 (void)stream;
4375 (void)zoom;
4376 ALOGVV("%s", __func__);
4377 return -ENOSYS;
4378}
4379
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004380static int adev_open_output_stream(struct audio_hw_device *dev,
4381 audio_io_handle_t handle,
4382 audio_devices_t devices,
4383 audio_output_flags_t flags,
4384 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07004385 struct audio_stream_out **stream_out,
4386 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004387{
4388 struct audio_device *adev = (struct audio_device *)dev;
4389 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004390 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004391 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
4392 bool is_usb_dev = audio_is_usb_out_device(devices) &&
4393 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004394
Andy Hungd9653bd2017-08-01 19:31:39 -07004395 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
4396 return -ENOSYS;
4397 }
4398
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004399 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
4400 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004401 *stream_out = NULL;
4402 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4403
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004404 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
4405
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004406 if (devices == AUDIO_DEVICE_NONE)
4407 devices = AUDIO_DEVICE_OUT_SPEAKER;
4408
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004409 out->flags = flags;
4410 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004411 out->dev = adev;
Eric Laurentc4aef752013-09-12 17:45:53 -07004412 out->handle = handle;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004413 out->a2dp_compress_mute = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004414
4415 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004416 if ((is_hdmi || is_usb_dev) &&
4417 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
4418 (flags == AUDIO_OUTPUT_FLAG_NONE ||
4419 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Eric Laurentab805ee2018-03-30 12:20:38 -07004420 audio_format_t req_format = config->format;
4421 audio_channel_mask_t req_channel_mask = config->channel_mask;
4422 uint32_t req_sample_rate = config->sample_rate;
4423
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004424 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004425 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004426 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004427 if (config->sample_rate == 0)
4428 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Eric Laurentab805ee2018-03-30 12:20:38 -07004429 if (config->channel_mask == AUDIO_CHANNEL_NONE)
Haynes Mathew George569b7482017-05-08 14:44:27 -07004430 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
4431 if (config->format == AUDIO_FORMAT_DEFAULT)
4432 config->format = AUDIO_FORMAT_PCM_16_BIT;
4433 } else if (is_usb_dev) {
4434 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
4435 &config->format,
4436 &out->supported_formats[0],
4437 MAX_SUPPORTED_FORMATS,
4438 &config->channel_mask,
4439 &out->supported_channel_masks[0],
4440 MAX_SUPPORTED_CHANNEL_MASKS,
4441 &config->sample_rate,
4442 &out->supported_sample_rates[0],
4443 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004444 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004445 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004446 pthread_mutex_unlock(&adev->lock);
Eric Laurentab805ee2018-03-30 12:20:38 -07004447 if (ret != 0) {
4448 // For MMAP NO IRQ, allow conversions in ADSP
4449 if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
4450 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004451
Eric Laurentab805ee2018-03-30 12:20:38 -07004452 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
4453 config->sample_rate = req_sample_rate;
4454 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
4455 config->channel_mask = req_channel_mask;
4456 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
4457 config->format = req_format;
4458 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004459
Haynes Mathew George569b7482017-05-08 14:44:27 -07004460 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004461 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004462 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004463 if (is_hdmi) {
4464 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4465 out->config = pcm_config_hdmi_multi;
4466 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
4467 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4468 out->config = pcm_config_mmap_playback;
4469 out->stream.start = out_start;
4470 out->stream.stop = out_stop;
4471 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4472 out->stream.get_mmap_position = out_get_mmap_position;
4473 } else {
4474 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4475 out->config = pcm_config_hifi;
4476 }
4477
4478 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004479 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004480 if (is_hdmi) {
4481 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
4482 audio_bytes_per_sample(out->format));
4483 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004484 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004485 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07004486 pthread_mutex_lock(&adev->lock);
4487 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4488 pthread_mutex_unlock(&adev->lock);
4489
4490 // reject offload during card offline to allow
4491 // fallback to s/w paths
4492 if (offline) {
4493 ret = -ENODEV;
4494 goto error_open;
4495 }
4496
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004497 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4498 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4499 ALOGE("%s: Unsupported Offload information", __func__);
4500 ret = -EINVAL;
4501 goto error_open;
4502 }
4503 if (!is_supported_format(config->offload_info.format)) {
4504 ALOGE("%s: Unsupported audio format", __func__);
4505 ret = -EINVAL;
4506 goto error_open;
4507 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004508 out->sample_rate = config->offload_info.sample_rate;
4509 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
4510 out->channel_mask = config->offload_info.channel_mask;
4511 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
4512 out->channel_mask = config->channel_mask;
4513 else
4514 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4515
4516 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004517
4518 out->compr_config.codec = (struct snd_codec *)
4519 calloc(1, sizeof(struct snd_codec));
4520
4521 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004522
4523 out->stream.set_callback = out_set_callback;
4524 out->stream.pause = out_pause;
4525 out->stream.resume = out_resume;
4526 out->stream.drain = out_drain;
4527 out->stream.flush = out_flush;
4528
4529 out->compr_config.codec->id =
4530 get_snd_codec_id(config->offload_info.format);
4531 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
4532 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004533 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004534 out->compr_config.codec->bit_rate =
4535 config->offload_info.bit_rate;
4536 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004537 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004538 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
4539
4540 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4541 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004542
4543 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004544 create_offload_callback_thread(out);
4545 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4546 __func__, config->offload_info.version,
4547 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02004548 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4549 switch (config->sample_rate) {
4550 case 0:
4551 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4552 break;
4553 case 8000:
4554 case 16000:
4555 case 48000:
4556 out->sample_rate = config->sample_rate;
4557 break;
4558 default:
4559 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
4560 config->sample_rate);
4561 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4562 ret = -EINVAL;
4563 goto error_open;
4564 }
4565 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4566 switch (config->channel_mask) {
4567 case AUDIO_CHANNEL_NONE:
4568 case AUDIO_CHANNEL_OUT_STEREO:
4569 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4570 break;
4571 default:
4572 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
4573 config->channel_mask);
4574 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4575 ret = -EINVAL;
4576 goto error_open;
4577 }
4578 switch (config->format) {
4579 case AUDIO_FORMAT_DEFAULT:
4580 case AUDIO_FORMAT_PCM_16_BIT:
4581 out->format = AUDIO_FORMAT_PCM_16_BIT;
4582 break;
4583 default:
4584 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
4585 config->format);
4586 config->format = AUDIO_FORMAT_PCM_16_BIT;
4587 ret = -EINVAL;
4588 goto error_open;
4589 }
4590
4591 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004592 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004593 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004594 case 0:
4595 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
4596 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07004597 case 8000:
4598 case 16000:
4599 case 48000:
4600 out->sample_rate = config->sample_rate;
4601 break;
4602 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004603 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
4604 config->sample_rate);
4605 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4606 ret = -EINVAL;
4607 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004608 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004609 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4610 switch (config->channel_mask) {
4611 case AUDIO_CHANNEL_NONE:
4612 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4613 break;
4614 case AUDIO_CHANNEL_OUT_STEREO:
4615 out->channel_mask = config->channel_mask;
4616 break;
4617 default:
4618 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
4619 config->channel_mask);
4620 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4621 ret = -EINVAL;
4622 break;
4623 }
4624 switch (config->format) {
4625 case AUDIO_FORMAT_DEFAULT:
4626 out->format = AUDIO_FORMAT_PCM_16_BIT;
4627 break;
4628 case AUDIO_FORMAT_PCM_16_BIT:
4629 out->format = config->format;
4630 break;
4631 default:
4632 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
4633 config->format);
4634 config->format = AUDIO_FORMAT_PCM_16_BIT;
4635 ret = -EINVAL;
4636 break;
4637 }
4638 if (ret != 0)
4639 goto error_open;
4640
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004641 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4642 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004643 out->config.rate = out->sample_rate;
4644 out->config.channels =
4645 audio_channel_count_from_out_mask(out->channel_mask);
4646 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004647 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004648 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
4649 switch (config->sample_rate) {
4650 case 0:
4651 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4652 break;
4653 case 8000:
4654 case 16000:
4655 case 32000:
4656 case 48000:
4657 out->sample_rate = config->sample_rate;
4658 break;
4659 default:
4660 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
4661 config->sample_rate);
4662 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4663 ret = -EINVAL;
4664 break;
4665 }
Eric Laurentad2dde92017-09-20 18:27:31 -07004666 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004667 switch (config->channel_mask) {
4668 case AUDIO_CHANNEL_NONE:
4669 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4670 break;
4671 case AUDIO_CHANNEL_OUT_STEREO:
4672 out->channel_mask = config->channel_mask;
4673 break;
4674 default:
4675 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
4676 config->channel_mask);
4677 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4678 ret = -EINVAL;
4679 break;
4680 }
4681 switch (config->format) {
4682 case AUDIO_FORMAT_DEFAULT:
4683 out->format = AUDIO_FORMAT_PCM_16_BIT;
4684 break;
4685 case AUDIO_FORMAT_PCM_16_BIT:
4686 out->format = config->format;
4687 break;
4688 default:
4689 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
4690 config->format);
4691 config->format = AUDIO_FORMAT_PCM_16_BIT;
4692 ret = -EINVAL;
4693 break;
4694 }
4695 if (ret != 0)
4696 goto error_open;
4697
vivek mehtaa68fea62017-06-08 19:04:02 -07004698 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07004699 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4700 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004701 out->config.rate = out->sample_rate;
4702 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07004703 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004704 out->sample_rate,
4705 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07004706 out->config.channels,
4707 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004708 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07004709 out->config.period_size = buffer_size / frame_size;
4710 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
4711 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004712 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004713 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07004714 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4715 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004716 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07004717 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
4718 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004719 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07004720 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004721 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004722 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004723 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004724 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4725 out->config = pcm_config_mmap_playback;
4726 out->stream.start = out_start;
4727 out->stream.stop = out_stop;
4728 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4729 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004730 } else {
4731 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4732 out->config = pcm_config_low_latency;
4733 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004734
4735 if (config->sample_rate == 0) {
4736 out->sample_rate = out->config.rate;
4737 } else {
4738 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004739 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004740 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
4741 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
4742 } else {
4743 out->channel_mask = config->channel_mask;
4744 }
4745 if (config->format == AUDIO_FORMAT_DEFAULT)
4746 out->format = audio_format_from_pcm_format(out->config.format);
4747 else if (!audio_is_linear_pcm(config->format)) {
4748 config->format = AUDIO_FORMAT_PCM_16_BIT;
4749 ret = -EINVAL;
4750 goto error_open;
4751 } else {
4752 out->format = config->format;
4753 }
4754
4755 out->config.rate = out->sample_rate;
4756 out->config.channels =
4757 audio_channel_count_from_out_mask(out->channel_mask);
4758 if (out->format != audio_format_from_pcm_format(out->config.format)) {
4759 out->config.format = pcm_format_from_audio_format(out->format);
4760 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004761 }
Kevin Rocard50eff892017-05-02 16:52:05 -07004762
4763 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
4764 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004765 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004766 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
4767 __func__, config->sample_rate, config->format, config->channel_mask);
4768 config->sample_rate = out->sample_rate;
4769 config->format = out->format;
4770 config->channel_mask = out->channel_mask;
4771 ret = -EINVAL;
4772 goto error_open;
4773 }
4774
Andy Hung6fcba9c2014-03-18 11:53:32 -07004775 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
4776 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004777
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004778 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004779 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004780 adev->primary_output = out;
4781 else {
4782 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004783 ret = -EEXIST;
4784 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004785 }
4786 }
4787
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004788 /* Check if this usecase is already existing */
4789 pthread_mutex_lock(&adev->lock);
4790 if (get_usecase_from_list(adev, out->usecase) != NULL) {
4791 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004792 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004793 ret = -EEXIST;
4794 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004795 }
4796 pthread_mutex_unlock(&adev->lock);
4797
4798 out->stream.common.get_sample_rate = out_get_sample_rate;
4799 out->stream.common.set_sample_rate = out_set_sample_rate;
4800 out->stream.common.get_buffer_size = out_get_buffer_size;
4801 out->stream.common.get_channels = out_get_channels;
4802 out->stream.common.get_format = out_get_format;
4803 out->stream.common.set_format = out_set_format;
4804 out->stream.common.standby = out_standby;
4805 out->stream.common.dump = out_dump;
4806 out->stream.common.set_parameters = out_set_parameters;
4807 out->stream.common.get_parameters = out_get_parameters;
4808 out->stream.common.add_audio_effect = out_add_audio_effect;
4809 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4810 out->stream.get_latency = out_get_latency;
4811 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004812#ifdef NO_AUDIO_OUT
4813 out->stream.write = out_write_for_no_output;
4814#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004815 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004816#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004817 out->stream.get_render_position = out_get_render_position;
4818 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004819 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004820
Eric Laurent0e46adf2016-12-16 12:49:24 -08004821 if (out->realtime)
4822 out->af_period_multiplier = af_period_multiplier;
4823 else
4824 out->af_period_multiplier = 1;
4825
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004826 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004827 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004828 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004829
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004830 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004831 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004832 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4833
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004834 config->format = out->stream.common.get_format(&out->stream.common);
4835 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4836 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4837
Kevin Rocarda325aa22018-04-03 09:15:52 -07004838 register_format(out->format, out->supported_formats);
4839 register_channel_mask(out->channel_mask, out->supported_channel_masks);
4840 register_sample_rate(out->sample_rate, out->supported_sample_rates);
4841
Andy Hunga452b0a2017-03-15 14:51:15 -07004842 out->error_log = error_log_create(
4843 ERROR_LOG_ENTRIES,
4844 1000000000 /* aggregate consecutive identical errors within one second in ns */);
4845
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004846 /*
4847 By locking output stream before registering, we allow the callback
4848 to update stream's state only after stream's initial state is set to
4849 adev state.
4850 */
4851 lock_output_stream(out);
4852 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4853 pthread_mutex_lock(&adev->lock);
4854 out->card_status = adev->card_status;
4855 pthread_mutex_unlock(&adev->lock);
4856 pthread_mutex_unlock(&out->lock);
4857
vivek mehta4a824772017-06-08 19:05:49 -07004858 stream_app_type_cfg_init(&out->app_type_cfg);
4859
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004860 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004861
Eric Laurent994a6932013-07-17 11:51:42 -07004862 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004863 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004864
4865error_open:
4866 free(out);
4867 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07004868 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004869 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004870}
4871
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004872static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004873 struct audio_stream_out *stream)
4874{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004875 struct stream_out *out = (struct stream_out *)stream;
4876 struct audio_device *adev = out->dev;
4877
Eric Laurent994a6932013-07-17 11:51:42 -07004878 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004879
4880 // must deregister from sndmonitor first to prevent races
4881 // between the callback and close_stream
4882 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004883 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004884 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
4885 destroy_offload_callback_thread(out);
4886
4887 if (out->compr_config.codec != NULL)
4888 free(out->compr_config.codec);
4889 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004890
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004891 out->a2dp_compress_mute = false;
4892
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004893 if (adev->voice_tx_output == out)
4894 adev->voice_tx_output = NULL;
4895
Andy Hunga452b0a2017-03-15 14:51:15 -07004896 error_log_destroy(out->error_log);
4897 out->error_log = NULL;
4898
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004899 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004900 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004901 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004902 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004903 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004904}
4905
4906static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4907{
4908 struct audio_device *adev = (struct audio_device *)dev;
4909 struct str_parms *parms;
4910 char *str;
4911 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004912 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004913 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07004914 int status = 0;
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004915 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004916
Joe Onorato188b6222016-03-01 11:02:27 -08004917 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004918
4919 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004920
4921 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004922 status = voice_set_parameters(adev, parms);
4923 if (status != 0) {
4924 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004925 }
4926
4927 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4928 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07004929 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004930 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4931 adev->bluetooth_nrec = true;
4932 else
4933 adev->bluetooth_nrec = false;
4934 }
4935
4936 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4937 if (ret >= 0) {
4938 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4939 adev->screen_off = false;
4940 else
4941 adev->screen_off = true;
4942 }
4943
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004944 ret = str_parms_get_int(parms, "rotation", &val);
4945 if (ret >= 0) {
4946 bool reverse_speakers = false;
Eric Laurent5f4ca952018-10-19 17:33:43 -07004947 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004948 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004949 // FIXME: note that the code below assumes that the speakers are in the correct placement
4950 // relative to the user when the device is rotated 90deg from its default rotation. This
4951 // assumption is device-specific, not platform-specific like this code.
4952 case 270:
4953 reverse_speakers = true;
Eric Laurent5f4ca952018-10-19 17:33:43 -07004954 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004955 break;
4956 case 0:
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004957 case 180:
Eric Laurent5f4ca952018-10-19 17:33:43 -07004958 camera_rotation = CAMERA_ROTATION_PORTRAIT;
4959 break;
4960 case 90:
4961 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004962 break;
4963 default:
4964 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07004965 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004966 }
Eric Laurent03f09432014-03-25 18:09:11 -07004967 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004968 // check and set swap
4969 // - check if orientation changed and speaker active
4970 // - set rotation and cache the rotation value
Eric Laurent5f4ca952018-10-19 17:33:43 -07004971 adev->camera_orientation =
4972 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
4973#ifndef MAXXAUDIO_QDSP_ENABLED
vivek mehtae59cfb22017-06-16 15:57:11 -07004974 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Eric Laurent5f4ca952018-10-19 17:33:43 -07004975#endif
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004976 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004977 }
4978
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004979 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4980 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004981 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004982 }
4983
David Linee3fe402017-03-13 10:00:42 -07004984 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4985 if (ret >= 0) {
4986 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004987 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004988 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4989 if (ret >= 0) {
4990 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004991 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004992 }
Eric Laurent99dab492017-06-17 15:19:08 -07004993 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004994 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4995 if (ret >= 0) {
4996 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004997 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004998 }
4999 }
5000 }
5001
5002 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
5003 if (ret >= 0) {
5004 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07005005 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005006 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5007 if (ret >= 0) {
5008 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005009 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005010 }
Eric Laurent99dab492017-06-17 15:19:08 -07005011 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005012 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5013 if (ret >= 0) {
5014 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005015 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005016 }
5017 }
5018 }
5019
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08005020 audio_extn_hfp_set_parameters(adev, parms);
jasmine cha270b7762018-03-30 15:41:33 +08005021 audio_extn_ma_set_parameters(adev, parms);
5022
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005023 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
5024 if (status >= 0 && a2dp_reconfig) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005025 struct audio_usecase *usecase;
5026 struct listnode *node;
5027 list_for_each(node, &adev->usecase_list) {
5028 usecase = node_to_item(node, struct audio_usecase, list);
5029 if ((usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005030 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005031 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
5032
5033 pthread_mutex_unlock(&adev->lock);
5034 lock_output_stream(usecase->stream.out);
5035 pthread_mutex_lock(&adev->lock);
5036 audio_extn_a2dp_set_handoff_mode(true);
5037 // force device switch to reconfigure encoder
5038 select_devices(adev, usecase->id);
5039 audio_extn_a2dp_set_handoff_mode(false);
5040 pthread_mutex_unlock(&usecase->stream.out->lock);
5041 break;
5042 }
5043 }
5044 }
5045
Eric Laurent5f4ca952018-10-19 17:33:43 -07005046 //FIXME: to be replaced by proper video capture properties API
5047 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
5048 if (ret >= 0) {
5049 int camera_facing = CAMERA_FACING_BACK;
5050 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
5051 camera_facing = CAMERA_FACING_FRONT;
5052 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
5053 camera_facing = CAMERA_FACING_BACK;
5054 else {
5055 ALOGW("%s: invalid camera facing value: %s", __func__, value);
5056 goto done;
5057 }
5058 adev->camera_orientation =
5059 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
5060 struct audio_usecase *usecase;
5061 struct listnode *node;
5062 list_for_each(node, &adev->usecase_list) {
5063 usecase = node_to_item(node, struct audio_usecase, list);
5064 struct stream_in *in = usecase->stream.in;
5065 if (usecase->type == PCM_CAPTURE && in != NULL &&
5066 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
5067 select_devices(adev, in->usecase);
5068 }
5069 }
5070 }
5071
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005072done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005073 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005074 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07005075 ALOGV("%s: exit with code(%d)", __func__, status);
5076 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005077}
5078
5079static char* adev_get_parameters(const struct audio_hw_device *dev,
5080 const char *keys)
5081{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005082 struct audio_device *adev = (struct audio_device *)dev;
5083 struct str_parms *reply = str_parms_create();
5084 struct str_parms *query = str_parms_create_str(keys);
5085 char *str;
5086
5087 pthread_mutex_lock(&adev->lock);
5088
5089 voice_get_parameters(adev, query, reply);
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005090 audio_extn_a2dp_get_parameters(query, reply);
5091
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005092 str = str_parms_to_str(reply);
5093 str_parms_destroy(query);
5094 str_parms_destroy(reply);
5095
5096 pthread_mutex_unlock(&adev->lock);
5097 ALOGV("%s: exit: returns - %s", __func__, str);
5098 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005099}
5100
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005101static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005102{
5103 return 0;
5104}
5105
Haynes Mathew George5191a852013-09-11 14:19:36 -07005106static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
5107{
5108 int ret;
5109 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005110
Eric Laurent4cc4ce12014-09-10 13:21:01 -05005111 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
5112
Haynes Mathew George5191a852013-09-11 14:19:36 -07005113 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005114 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07005115 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005116
Haynes Mathew George5191a852013-09-11 14:19:36 -07005117 return ret;
5118}
5119
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005120static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005121{
5122 return -ENOSYS;
5123}
5124
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005125static int adev_get_master_volume(struct audio_hw_device *dev __unused,
5126 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005127{
5128 return -ENOSYS;
5129}
5130
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005131static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005132{
5133 return -ENOSYS;
5134}
5135
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005136static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005137{
5138 return -ENOSYS;
5139}
5140
5141static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
5142{
5143 struct audio_device *adev = (struct audio_device *)dev;
5144
5145 pthread_mutex_lock(&adev->lock);
5146 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07005147 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005148 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07005149 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
5150 voice_is_in_call(adev)) {
5151 voice_stop_call(adev);
5152 adev->current_call_output = NULL;
5153 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005154 }
5155 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05005156
5157 audio_extn_extspk_set_mode(adev->extspk, mode);
5158
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005159 return 0;
5160}
5161
5162static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
5163{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005164 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005165 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005166
Eric Laurent2bafff12016-03-17 12:17:23 -07005167 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005168 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005169 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
5170 ret = audio_extn_hfp_set_mic_mute(adev, state);
5171 } else {
5172 ret = voice_set_mic_mute(adev, state);
5173 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07005174 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00005175 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005176
5177 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005178}
5179
5180static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
5181{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005182 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005183 return 0;
5184}
5185
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005186static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005187 const struct audio_config *config)
5188{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07005189 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005190
Eric Laurent74b55762017-07-09 17:04:53 -07005191 /* Don't know if USB HIFI in this context so use true to be conservative */
5192 if (check_input_parameters(config->sample_rate, config->format, channel_count,
5193 true /*is_usb_hifi */) != 0)
5194 return 0;
5195
vivek mehtaa68fea62017-06-08 19:04:02 -07005196 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5197 config->sample_rate, config->format,
5198 channel_count,
5199 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005200}
5201
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005202static bool adev_input_allow_hifi_record(struct audio_device *adev,
5203 audio_devices_t devices,
5204 audio_input_flags_t flags,
5205 audio_source_t source) {
5206 const bool allowed = true;
5207
5208 if (!audio_is_usb_in_device(devices))
5209 return !allowed;
5210
5211 switch (flags) {
5212 case AUDIO_INPUT_FLAG_NONE:
5213 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
5214 break;
5215 default:
5216 return !allowed;
5217 }
5218
5219 switch (source) {
5220 case AUDIO_SOURCE_DEFAULT:
5221 case AUDIO_SOURCE_MIC:
5222 case AUDIO_SOURCE_UNPROCESSED:
5223 break;
5224 default:
5225 return !allowed;
5226 }
5227
5228 switch (adev->mode) {
5229 case 0:
5230 break;
5231 default:
5232 return !allowed;
5233 }
5234
5235 return allowed;
5236}
5237
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005238static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005239 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005240 audio_devices_t devices,
5241 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005242 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07005243 audio_input_flags_t flags,
5244 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05005245 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005246{
5247 struct audio_device *adev = (struct audio_device *)dev;
5248 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005249 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07005250 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005251 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005252 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005253 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
5254 devices,
5255 flags,
5256 source);
Andy Hung88ce1d92018-10-29 18:31:12 -07005257 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
5258 " sample_rate %u, channel_mask %#x, format %#x",
5259 __func__, flags, is_usb_dev, may_use_hifi_record,
5260 config->sample_rate, config->channel_mask, config->format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005261 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005262
Andy Hungd9653bd2017-08-01 19:31:39 -07005263 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
5264 return -ENOSYS;
5265 }
5266
Eric Laurent74b55762017-07-09 17:04:53 -07005267 if (!(is_usb_dev && may_use_hifi_record)) {
5268 if (config->sample_rate == 0)
5269 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
5270 if (config->channel_mask == AUDIO_CHANNEL_NONE)
5271 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5272 if (config->format == AUDIO_FORMAT_DEFAULT)
5273 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005274
Eric Laurent74b55762017-07-09 17:04:53 -07005275 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
5276
5277 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
5278 return -EINVAL;
5279 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005280
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005281 if (audio_extn_tfa_98xx_is_supported() &&
5282 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005283 return -EINVAL;
5284
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005285 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
5286
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005287 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005288 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005289
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005290 in->stream.common.get_sample_rate = in_get_sample_rate;
5291 in->stream.common.set_sample_rate = in_set_sample_rate;
5292 in->stream.common.get_buffer_size = in_get_buffer_size;
5293 in->stream.common.get_channels = in_get_channels;
5294 in->stream.common.get_format = in_get_format;
5295 in->stream.common.set_format = in_set_format;
5296 in->stream.common.standby = in_standby;
5297 in->stream.common.dump = in_dump;
5298 in->stream.common.set_parameters = in_set_parameters;
5299 in->stream.common.get_parameters = in_get_parameters;
5300 in->stream.common.add_audio_effect = in_add_audio_effect;
5301 in->stream.common.remove_audio_effect = in_remove_audio_effect;
5302 in->stream.set_gain = in_set_gain;
5303 in->stream.read = in_read;
5304 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08005305 in->stream.get_capture_position = in_get_capture_position;
jiabin8962a4d2018-03-19 18:21:24 -07005306 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLean57530d52018-12-17 08:24:21 -07005307 in->stream.set_microphone_direction = in_set_microphone_direction;
5308 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005309
5310 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005311 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005312 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005313 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005314 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005315 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005316
Andy Hung88ce1d92018-10-29 18:31:12 -07005317 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Arun Mirpuriba2749a2018-04-17 14:32:24 -07005318 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
5319 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
5320 /* Force channel config requested to mono if incall
5321 record is being requested for only uplink/downlink */
5322 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
5323 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5324 ret = -EINVAL;
5325 goto err_open;
5326 }
5327 }
5328
Haynes Mathew George569b7482017-05-08 14:44:27 -07005329 if (is_usb_dev && may_use_hifi_record) {
5330 /* HiFi record selects an appropriate format, channel, rate combo
5331 depending on sink capabilities*/
5332 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
5333 &config->format,
5334 &in->supported_formats[0],
5335 MAX_SUPPORTED_FORMATS,
5336 &config->channel_mask,
5337 &in->supported_channel_masks[0],
5338 MAX_SUPPORTED_CHANNEL_MASKS,
5339 &config->sample_rate,
5340 &in->supported_sample_rates[0],
5341 MAX_SUPPORTED_SAMPLE_RATES);
5342 if (ret != 0) {
5343 ret = -EINVAL;
5344 goto err_open;
5345 }
Eric Laurent74b55762017-07-09 17:04:53 -07005346 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005347 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07005348 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07005349 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
5350 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
5351 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5352 bool ret_error = false;
5353 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5354 from HAL is 8_24
5355 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5356 8_24 return error indicating supported format is 8_24
5357 *> In case of any other source requesting 24 bit or float return error
5358 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07005359
vivek mehta57ff9b52016-04-28 14:13:08 -07005360 on error flinger will retry with supported format passed
5361 */
juyuchenbe5c67e2018-08-29 17:19:20 +08005362 if (!is_supported_24bits_audiosource(source)) {
vivek mehta57ff9b52016-04-28 14:13:08 -07005363 config->format = AUDIO_FORMAT_PCM_16_BIT;
5364 ret_error = true;
5365 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
5366 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
5367 ret_error = true;
5368 }
5369
5370 if (ret_error) {
5371 ret = -EINVAL;
5372 goto err_open;
5373 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005374 }
5375
vivek mehta57ff9b52016-04-28 14:13:08 -07005376 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07005377 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07005378
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005379 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005380 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
5381 if (config->sample_rate == 0)
5382 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5383 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5384 config->sample_rate != 8000) {
5385 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5386 ret = -EINVAL;
5387 goto err_open;
5388 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005389
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005390 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5391 config->format = AUDIO_FORMAT_PCM_16_BIT;
5392 ret = -EINVAL;
5393 goto err_open;
5394 }
5395
5396 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5397 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07005398 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005399 } else if (is_usb_dev && may_use_hifi_record) {
5400 in->usecase = USECASE_AUDIO_RECORD_HIFI;
5401 in->config = pcm_config_audio_capture;
5402 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 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005408 in->config.period_size = buffer_size / frame_size;
5409 in->config.rate = config->sample_rate;
5410 in->af_period_multiplier = 1;
5411 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005412 } else {
5413 in->usecase = USECASE_AUDIO_RECORD;
5414 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08005415 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005416 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07005417#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005418 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07005419#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08005420 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005421 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08005422 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005423 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005424 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5425 config->sample_rate,
5426 config->format,
5427 channel_count,
5428 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005429 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005430 in->config.rate = config->sample_rate;
5431 in->af_period_multiplier = 1;
5432 } else {
5433 // period size is left untouched for rt mode playback
5434 in->config = pcm_config_audio_capture_rt;
5435 in->af_period_multiplier = af_period_multiplier;
5436 }
5437 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
5438 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005439 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08005440 in->usecase = USECASE_AUDIO_RECORD_MMAP;
5441 in->config = pcm_config_mmap_capture;
5442 in->stream.start = in_start;
5443 in->stream.stop = in_stop;
5444 in->stream.create_mmap_buffer = in_create_mmap_buffer;
5445 in->stream.get_mmap_position = in_get_mmap_position;
5446 in->af_period_multiplier = 1;
5447 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07005448 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07005449 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07005450 (config->sample_rate == 8000 ||
5451 config->sample_rate == 16000 ||
5452 config->sample_rate == 32000 ||
5453 config->sample_rate == 48000) &&
5454 channel_count == 1) {
5455 in->usecase = USECASE_AUDIO_RECORD_VOIP;
5456 in->config = pcm_config_audio_capture;
5457 frame_size = audio_stream_in_frame_size(&in->stream);
5458 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
5459 config->sample_rate,
5460 config->format,
5461 channel_count, false /*is_low_latency*/);
5462 in->config.period_size = buffer_size / frame_size;
5463 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
5464 in->config.rate = config->sample_rate;
5465 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005466 } else {
5467 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005468 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005469 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5470 config->sample_rate,
5471 config->format,
5472 channel_count,
5473 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005474 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005475 in->config.rate = config->sample_rate;
5476 in->af_period_multiplier = 1;
5477 }
5478 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
5479 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005480 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08005481
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005482 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07005483 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005484
Kevin Rocarda325aa22018-04-03 09:15:52 -07005485
5486 register_format(in->format, in->supported_formats);
5487 register_channel_mask(in->channel_mask, in->supported_channel_masks);
5488 register_sample_rate(in->sample_rate, in->supported_sample_rates);
5489
Andy Hungd13f0d32017-06-12 13:58:37 -07005490 in->error_log = error_log_create(
5491 ERROR_LOG_ENTRIES,
5492 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
5493
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005494 /* This stream could be for sound trigger lab,
5495 get sound trigger pcm if present */
5496 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005497
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005498 lock_input_stream(in);
5499 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5500 pthread_mutex_lock(&adev->lock);
5501 in->card_status = adev->card_status;
5502 pthread_mutex_unlock(&adev->lock);
5503 pthread_mutex_unlock(&in->lock);
5504
vivek mehta4a824772017-06-08 19:05:49 -07005505 stream_app_type_cfg_init(&in->app_type_cfg);
5506
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005507 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005508 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005509 return 0;
5510
5511err_open:
5512 free(in);
5513 *stream_in = NULL;
5514 return ret;
5515}
5516
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005517static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005518 struct audio_stream_in *stream)
5519{
Andy Hungd13f0d32017-06-12 13:58:37 -07005520 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005521 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005522
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005523 // must deregister from sndmonitor first to prevent races
5524 // between the callback and close_stream
5525 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005526 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07005527
5528 error_log_destroy(in->error_log);
5529 in->error_log = NULL;
5530
Andy Hung0dbb52b2017-08-09 13:51:38 -07005531 pthread_mutex_destroy(&in->pre_lock);
5532 pthread_mutex_destroy(&in->lock);
5533
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005534 free(stream);
5535
5536 return;
5537}
5538
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005539static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005540{
5541 return 0;
5542}
5543
Andy Hung31aca912014-03-20 17:14:59 -07005544/* verifies input and output devices and their capabilities.
5545 *
5546 * This verification is required when enabling extended bit-depth or
5547 * sampling rates, as not all qcom products support it.
5548 *
5549 * Suitable for calling only on initialization such as adev_open().
5550 * It fills the audio_device use_case_table[] array.
5551 *
5552 * Has a side-effect that it needs to configure audio routing / devices
5553 * in order to power up the devices and read the device parameters.
5554 * It does not acquire any hw device lock. Should restore the devices
5555 * back to "normal state" upon completion.
5556 */
5557static int adev_verify_devices(struct audio_device *adev)
5558{
5559 /* enumeration is a bit difficult because one really wants to pull
5560 * the use_case, device id, etc from the hidden pcm_device_table[].
5561 * In this case there are the following use cases and device ids.
5562 *
5563 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
5564 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005565 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07005566 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
5567 * [USECASE_AUDIO_RECORD] = {0, 0},
5568 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
5569 * [USECASE_VOICE_CALL] = {2, 2},
5570 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005571 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07005572 * USECASE_VOICE_CALL omitted, but possible for either input or output.
5573 */
5574
5575 /* should be the usecases enabled in adev_open_input_stream() */
5576 static const int test_in_usecases[] = {
5577 USECASE_AUDIO_RECORD,
5578 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
5579 };
5580 /* should be the usecases enabled in adev_open_output_stream()*/
5581 static const int test_out_usecases[] = {
5582 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
5583 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
5584 };
5585 static const usecase_type_t usecase_type_by_dir[] = {
5586 PCM_PLAYBACK,
5587 PCM_CAPTURE,
5588 };
5589 static const unsigned flags_by_dir[] = {
5590 PCM_OUT,
5591 PCM_IN,
5592 };
5593
5594 size_t i;
5595 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005596 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07005597 char info[512]; /* for possible debug info */
5598
5599 for (dir = 0; dir < 2; ++dir) {
5600 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
5601 const unsigned flags_dir = flags_by_dir[dir];
5602 const size_t testsize =
5603 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
5604 const int *testcases =
5605 dir ? test_in_usecases : test_out_usecases;
5606 const audio_devices_t audio_device =
5607 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
5608
5609 for (i = 0; i < testsize; ++i) {
5610 const audio_usecase_t audio_usecase = testcases[i];
5611 int device_id;
5612 snd_device_t snd_device;
5613 struct pcm_params **pparams;
5614 struct stream_out out;
5615 struct stream_in in;
5616 struct audio_usecase uc_info;
5617 int retval;
5618
5619 pparams = &adev->use_case_table[audio_usecase];
5620 pcm_params_free(*pparams); /* can accept null input */
5621 *pparams = NULL;
5622
5623 /* find the device ID for the use case (signed, for error) */
5624 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
5625 if (device_id < 0)
5626 continue;
5627
5628 /* prepare structures for device probing */
5629 memset(&uc_info, 0, sizeof(uc_info));
5630 uc_info.id = audio_usecase;
5631 uc_info.type = usecase_type;
5632 if (dir) {
Andy Hung31aca912014-03-20 17:14:59 -07005633 memset(&in, 0, sizeof(in));
5634 in.device = audio_device;
5635 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
5636 uc_info.stream.in = &in;
Andy Hung31aca912014-03-20 17:14:59 -07005637 }
5638 memset(&out, 0, sizeof(out));
5639 out.devices = audio_device; /* only field needed in select_devices */
5640 uc_info.stream.out = &out;
5641 uc_info.devices = audio_device;
5642 uc_info.in_snd_device = SND_DEVICE_NONE;
5643 uc_info.out_snd_device = SND_DEVICE_NONE;
5644 list_add_tail(&adev->usecase_list, &uc_info.list);
5645
5646 /* select device - similar to start_(in/out)put_stream() */
5647 retval = select_devices(adev, audio_usecase);
5648 if (retval >= 0) {
5649 *pparams = pcm_params_get(card_id, device_id, flags_dir);
5650#if LOG_NDEBUG == 0
5651 if (*pparams) {
5652 ALOGV("%s: (%s) card %d device %d", __func__,
5653 dir ? "input" : "output", card_id, device_id);
5654 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07005655 } else {
5656 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
5657 }
5658#endif
5659 }
5660
5661 /* deselect device - similar to stop_(in/out)put_stream() */
5662 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07005663 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07005664 /* 2. Disable the rx device */
5665 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07005666 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07005667 list_remove(&uc_info.list);
5668 }
5669 }
Andy Hung31aca912014-03-20 17:14:59 -07005670 return 0;
5671}
5672
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005673static int adev_close(hw_device_t *device)
5674{
Andy Hung31aca912014-03-20 17:14:59 -07005675 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005676 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005677
5678 if (!adev)
5679 return 0;
5680
5681 pthread_mutex_lock(&adev_init_lock);
5682
5683 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005684 audio_extn_snd_mon_unregister_listener(adev);
5685 audio_extn_tfa_98xx_deinit();
jasmine cha270b7762018-03-30 15:41:33 +08005686 audio_extn_ma_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005687 audio_route_free(adev->audio_route);
5688 free(adev->snd_dev_ref_cnt);
5689 platform_deinit(adev->platform);
5690 audio_extn_extspk_deinit(adev->extspk);
5691 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005692 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005693 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
5694 pcm_params_free(adev->use_case_table[i]);
5695 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005696 if (adev->adm_deinit)
5697 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005698 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005699 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07005700 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07005701
5702 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005703
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005704 return 0;
5705}
5706
Glenn Kasten4f993392014-05-14 07:30:48 -07005707/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5708 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5709 * just that it _might_ work.
5710 */
5711static int period_size_is_plausible_for_low_latency(int period_size)
5712{
5713 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005714 case 48:
5715 case 96:
5716 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07005717 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005718 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07005719 case 240:
5720 case 320:
5721 case 480:
5722 return 1;
5723 default:
5724 return 0;
5725 }
5726}
5727
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005728static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
5729{
5730 int card;
5731 card_status_t status;
5732
5733 if (!parms)
5734 return;
5735
5736 if (parse_snd_card_status(parms, &card, &status) < 0)
5737 return;
5738
5739 pthread_mutex_lock(&adev->lock);
5740 bool valid_cb = (card == adev->snd_card);
5741 if (valid_cb) {
5742 if (adev->card_status != status) {
5743 adev->card_status = status;
5744 platform_snd_card_update(adev->platform, status);
5745 }
5746 }
5747 pthread_mutex_unlock(&adev->lock);
5748 return;
5749}
5750
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005751/* out and adev lock held */
5752static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
5753{
5754 struct audio_usecase *uc_info;
5755 float left_p;
5756 float right_p;
5757 audio_devices_t devices;
5758
5759 uc_info = get_usecase_from_list(adev, out->usecase);
5760 if (uc_info == NULL) {
5761 ALOGE("%s: Could not find the usecase (%d) in the list",
5762 __func__, out->usecase);
5763 return -EINVAL;
5764 }
5765
5766 ALOGD("%s: enter: usecase(%d: %s)", __func__,
5767 out->usecase, use_case_table[out->usecase]);
5768
5769 if (restore) {
5770 // restore A2DP device for active usecases and unmute if required
5771 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
5772 !is_a2dp_device(uc_info->out_snd_device)) {
5773 ALOGD("%s: restoring A2DP and unmuting stream", __func__);
5774 select_devices(adev, uc_info->id);
5775 pthread_mutex_lock(&out->compr_mute_lock);
5776 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5777 (out->a2dp_compress_mute)) {
5778 out->a2dp_compress_mute = false;
5779 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5780 }
5781 pthread_mutex_unlock(&out->compr_mute_lock);
5782 }
5783 } else {
5784 // mute compress stream if suspended
5785 pthread_mutex_lock(&out->compr_mute_lock);
5786 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5787 (!out->a2dp_compress_mute)) {
5788 if (!out->standby) {
5789 ALOGD("%s: selecting speaker and muting stream", __func__);
5790 devices = out->devices;
5791 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
5792 left_p = out->volume_l;
5793 right_p = out->volume_r;
5794 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5795 compress_pause(out->compr);
5796 set_compr_volume(&out->stream, 0.0f, 0.0f);
5797 out->a2dp_compress_mute = true;
5798 select_devices(adev, out->usecase);
5799 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5800 compress_resume(out->compr);
5801 out->devices = devices;
5802 out->volume_l = left_p;
5803 out->volume_r = right_p;
5804 }
5805 }
5806 pthread_mutex_unlock(&out->compr_mute_lock);
5807 }
5808 ALOGV("%s: exit", __func__);
5809 return 0;
5810}
5811
5812int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
5813{
5814 int ret = 0;
5815
5816 lock_output_stream(out);
5817 pthread_mutex_lock(&adev->lock);
5818
5819 ret = check_a2dp_restore_l(adev, out, restore);
5820
5821 pthread_mutex_unlock(&adev->lock);
5822 pthread_mutex_unlock(&out->lock);
5823 return ret;
5824}
5825
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005826static int adev_open(const hw_module_t *module, const char *name,
5827 hw_device_t **device)
5828{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005829 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005830
Eric Laurent2bafff12016-03-17 12:17:23 -07005831 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005832 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005833 pthread_mutex_lock(&adev_init_lock);
5834 if (audio_device_ref_count != 0) {
5835 *device = &adev->device.common;
5836 audio_device_ref_count++;
5837 ALOGV("%s: returning existing instance of adev", __func__);
5838 ALOGV("%s: exit", __func__);
5839 pthread_mutex_unlock(&adev_init_lock);
5840 return 0;
5841 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005842 adev = calloc(1, sizeof(struct audio_device));
5843
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005844 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5845
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005846 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5847 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5848 adev->device.common.module = (struct hw_module_t *)module;
5849 adev->device.common.close = adev_close;
5850
5851 adev->device.init_check = adev_init_check;
5852 adev->device.set_voice_volume = adev_set_voice_volume;
5853 adev->device.set_master_volume = adev_set_master_volume;
5854 adev->device.get_master_volume = adev_get_master_volume;
5855 adev->device.set_master_mute = adev_set_master_mute;
5856 adev->device.get_master_mute = adev_get_master_mute;
5857 adev->device.set_mode = adev_set_mode;
5858 adev->device.set_mic_mute = adev_set_mic_mute;
5859 adev->device.get_mic_mute = adev_get_mic_mute;
5860 adev->device.set_parameters = adev_set_parameters;
5861 adev->device.get_parameters = adev_get_parameters;
5862 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5863 adev->device.open_output_stream = adev_open_output_stream;
5864 adev->device.close_output_stream = adev_close_output_stream;
5865 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005866
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005867 adev->device.close_input_stream = adev_close_input_stream;
5868 adev->device.dump = adev_dump;
jiabin8962a4d2018-03-19 18:21:24 -07005869 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005870
5871 /* Set the default route before the PCM stream is opened */
5872 pthread_mutex_lock(&adev->lock);
5873 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005874 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005875 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005876 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005877 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005878 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005879 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005880 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005881 pthread_mutex_unlock(&adev->lock);
5882
5883 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005884 adev->platform = platform_init(adev);
5885 if (!adev->platform) {
5886 free(adev->snd_dev_ref_cnt);
5887 free(adev);
5888 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5889 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005890 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005891 return -EINVAL;
5892 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05005893 adev->extspk = audio_extn_extspk_init(adev);
5894
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005895 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5896 if (adev->visualizer_lib == NULL) {
5897 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5898 } else {
5899 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5900 adev->visualizer_start_output =
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07005901 (int (*)(audio_io_handle_t, int, int, int))dlsym(adev->visualizer_lib,
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005902 "visualizer_hal_start_output");
5903 adev->visualizer_stop_output =
5904 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5905 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07005906 }
5907
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005908 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5909 if (adev->offload_effects_lib == NULL) {
5910 ALOGW("%s: DLOPEN failed for %s", __func__,
5911 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5912 } else {
5913 ALOGV("%s: DLOPEN successful for %s", __func__,
5914 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5915 adev->offload_effects_start_output =
5916 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5917 "offload_effects_bundle_hal_start_output");
5918 adev->offload_effects_stop_output =
5919 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5920 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07005921 }
5922
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005923 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5924 if (adev->adm_lib == NULL) {
5925 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5926 } else {
5927 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5928 adev->adm_init = (adm_init_t)
5929 dlsym(adev->adm_lib, "adm_init");
5930 adev->adm_deinit = (adm_deinit_t)
5931 dlsym(adev->adm_lib, "adm_deinit");
5932 adev->adm_register_input_stream = (adm_register_input_stream_t)
5933 dlsym(adev->adm_lib, "adm_register_input_stream");
5934 adev->adm_register_output_stream = (adm_register_output_stream_t)
5935 dlsym(adev->adm_lib, "adm_register_output_stream");
5936 adev->adm_deregister_stream = (adm_deregister_stream_t)
5937 dlsym(adev->adm_lib, "adm_deregister_stream");
5938 adev->adm_request_focus = (adm_request_focus_t)
5939 dlsym(adev->adm_lib, "adm_request_focus");
5940 adev->adm_abandon_focus = (adm_abandon_focus_t)
5941 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08005942 adev->adm_set_config = (adm_set_config_t)
5943 dlsym(adev->adm_lib, "adm_set_config");
5944 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5945 dlsym(adev->adm_lib, "adm_request_focus_v2");
5946 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5947 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5948 adev->adm_on_routing_change = (adm_on_routing_change_t)
5949 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005950 }
5951
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005952 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005953 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005954
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005955 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005956
Andy Hung31aca912014-03-20 17:14:59 -07005957 if (k_enable_extended_precision)
5958 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005959
Glenn Kasten4f993392014-05-14 07:30:48 -07005960 char value[PROPERTY_VALUE_MAX];
5961 int trial;
5962 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5963 trial = atoi(value);
5964 if (period_size_is_plausible_for_low_latency(trial)) {
5965 pcm_config_low_latency.period_size = trial;
5966 pcm_config_low_latency.start_threshold = trial / 4;
5967 pcm_config_low_latency.avail_min = trial / 4;
5968 configured_low_latency_capture_period_size = trial;
5969 }
5970 }
5971 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5972 trial = atoi(value);
5973 if (period_size_is_plausible_for_low_latency(trial)) {
5974 configured_low_latency_capture_period_size = trial;
5975 }
5976 }
5977
Vignesh Kulothunganb6f0a9c2018-03-22 13:50:22 -07005978 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
5979
Eric Laurent5f4ca952018-10-19 17:33:43 -07005980 adev->camera_orientation = CAMERA_DEFAULT;
5981
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005982 // commented as full set of app type cfg is sent from platform
5983 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005984 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005985
5986 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5987 af_period_multiplier = atoi(value);
5988 if (af_period_multiplier < 0) {
5989 af_period_multiplier = 2;
5990 } else if (af_period_multiplier > 4) {
5991 af_period_multiplier = 4;
5992 }
5993 ALOGV("new period_multiplier = %d", af_period_multiplier);
5994 }
5995
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005996 audio_extn_tfa_98xx_init(adev);
jasmine cha270b7762018-03-30 15:41:33 +08005997 audio_extn_ma_init(adev->platform);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005998
vivek mehta1a9b7c02015-06-25 11:49:38 -07005999 pthread_mutex_unlock(&adev_init_lock);
6000
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006001 if (adev->adm_init)
6002 adev->adm_data = adev->adm_init();
6003
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07006004 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07006005 audio_extn_snd_mon_init();
6006 pthread_mutex_lock(&adev->lock);
6007 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
6008 adev->card_status = CARD_STATUS_ONLINE;
6009 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07006010 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07006011
Eric Laurent2bafff12016-03-17 12:17:23 -07006012 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006013 return 0;
6014}
6015
6016static struct hw_module_methods_t hal_module_methods = {
6017 .open = adev_open,
6018};
6019
6020struct audio_module HAL_MODULE_INFO_SYM = {
6021 .common = {
6022 .tag = HARDWARE_MODULE_TAG,
6023 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
6024 .hal_api_version = HARDWARE_HAL_API_VERSION,
6025 .id = AUDIO_HARDWARE_MODULE_ID,
6026 .name = "QCOM Audio HAL",
6027 .author = "Code Aurora Forum",
6028 .methods = &hal_module_methods,
6029 },
6030};