blob: a93d52a71894bc8566f1df7b649c0254aeef1be0 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
vivek mehtaa51fd402016-02-04 19:49:33 -08002 * Copyright (C) 2013-2016 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "audio_hw_primary"
Haynes Mathew George03c40102016-01-29 17:57:48 -080018#define ATRACE_TAG ATRACE_TAG_AUDIO
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080019/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070020/*#define VERY_VERY_VERBOSE_LOGGING*/
21#ifdef VERY_VERY_VERBOSE_LOGGING
22#define ALOGVV ALOGV
23#else
24#define ALOGVV(a...) do { } while(0)
25#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080026
27#include <errno.h>
28#include <pthread.h>
29#include <stdint.h>
30#include <sys/time.h>
31#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080032#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070033#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070034#include <sys/resource.h>
35#include <sys/prctl.h>
Kevin Rocardb5c28192017-05-02 15:30:20 -070036#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080037
Haynes Mathew Georgee6e2d442018-02-22 18:51:56 -080038#include <log/log.h>
Haynes Mathew George03c40102016-01-29 17:57:48 -080039#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040#include <cutils/str_parms.h>
41#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070042#include <cutils/atomic.h>
43#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080044
Eric Laurentb23d5282013-05-14 15:27:20 -070045#include <hardware/audio_effect.h>
Andy Hung31aca912014-03-20 17:14:59 -070046#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070047#include <system/thread_defs.h>
Phil Burkbc991042017-02-24 08:06:44 -080048#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070049#include <audio_effects/effect_aec.h>
50#include <audio_effects/effect_ns.h>
Andy Hungfc044e12017-03-20 09:24:22 -070051#include <audio_utils/clock.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052#include "audio_hw.h"
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -080053#include "audio_extn.h"
Wei Wangf4837d52017-11-21 14:51:20 -080054#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070055#include "platform_api.h"
56#include <platform.h>
Vineeta Srivastava4b89e372014-06-19 14:21:42 -070057#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080058
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070059#include "sound/compress_params.h"
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -080060#include "audio_extn/tfa_98xx.h"
jasmine cha270b7762018-03-30 15:41:33 +080061#include "audio_extn/maxxaudio.h"
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062
Eric Laurent397db572016-05-11 11:31:47 -070063/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
64 * COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
Marco Nelissen32093f52015-04-08 15:14:02 -070065#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070066// 2 buffers causes problems with high bitrate files
67#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070068/* ToDo: Check and update a proper value in msec */
69#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
vivek mehta4a824772017-06-08 19:05:49 -070070/* treat as unsigned Q1.13 */
71#define APP_TYPE_GAIN_DEFAULT 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070072#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
vivek mehta4a824772017-06-08 19:05:49 -070073
74/* treat as unsigned Q1.13 */
vivek mehtaa68fea62017-06-08 19:04:02 -070075#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076
Eric Laurent51f3c662018-04-10 18:21:34 -070077#define RECORD_GAIN_MIN 0.0f
78#define RECORD_GAIN_MAX 1.0f
79#define RECORD_VOLUME_CTL_MAX 0x2000
80
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070081#define PROXY_OPEN_RETRY_COUNT 100
82#define PROXY_OPEN_WAIT_TIME 20
83
vivek mehtadae44712015-07-27 14:13:18 -070084#define MIN_CHANNEL_COUNT 1
85#define DEFAULT_CHANNEL_COUNT 2
86
Jean-Michel Trivic0750692015-10-12 12:12:32 -070087#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
88#define MAX_CHANNEL_COUNT 1
89#else
vivek mehtadae44712015-07-27 14:13:18 -070090#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
91#define XSTR(x) STR(x)
92#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070093#endif
Eric Laurent74b55762017-07-09 17:04:53 -070094#define MAX_HIFI_CHANNEL_COUNT 8
vivek mehtadae44712015-07-27 14:13:18 -070095
Haynes Mathew George03c40102016-01-29 17:57:48 -080096#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
97
Glenn Kasten4f993392014-05-14 07:30:48 -070098static unsigned int configured_low_latency_capture_period_size =
99 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
100
Eric Laurent0e46adf2016-12-16 12:49:24 -0800101
102#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Phil Burkbc991042017-02-24 08:06:44 -0800103#define MMAP_PERIOD_COUNT_MIN 32
104#define MMAP_PERIOD_COUNT_MAX 512
105#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
Eric Laurent0e46adf2016-12-16 12:49:24 -0800106
Andy Hung31aca912014-03-20 17:14:59 -0700107/* This constant enables extended precision handling.
108 * TODO The flag is off until more testing is done.
109 */
110static const bool k_enable_extended_precision = false;
111
Eric Laurentb23d5282013-05-14 15:27:20 -0700112struct pcm_config pcm_config_deep_buffer = {
vivek mehtadae44712015-07-27 14:13:18 -0700113 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700114 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
115 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
116 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
117 .format = PCM_FORMAT_S16_LE,
118 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
119 .stop_threshold = INT_MAX,
120 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
121};
122
123struct pcm_config pcm_config_low_latency = {
vivek mehtadae44712015-07-27 14:13:18 -0700124 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700125 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
126 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
127 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
128 .format = PCM_FORMAT_S16_LE,
129 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
130 .stop_threshold = INT_MAX,
131 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
132};
133
Haynes Mathew George03c40102016-01-29 17:57:48 -0800134static int af_period_multiplier = 4;
135struct pcm_config pcm_config_rt = {
136 .channels = DEFAULT_CHANNEL_COUNT,
137 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
138 .period_size = ULL_PERIOD_SIZE, //1 ms
139 .period_count = 512, //=> buffer size is 512ms
140 .format = PCM_FORMAT_S16_LE,
141 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
142 .stop_threshold = INT_MAX,
143 .silence_threshold = 0,
144 .silence_size = 0,
145 .avail_min = ULL_PERIOD_SIZE, //1 ms
146};
147
Eric Laurentb23d5282013-05-14 15:27:20 -0700148struct pcm_config pcm_config_hdmi_multi = {
149 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
150 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
151 .period_size = HDMI_MULTI_PERIOD_SIZE,
152 .period_count = HDMI_MULTI_PERIOD_COUNT,
153 .format = PCM_FORMAT_S16_LE,
154 .start_threshold = 0,
155 .stop_threshold = INT_MAX,
156 .avail_min = 0,
157};
158
Eric Laurent0e46adf2016-12-16 12:49:24 -0800159struct pcm_config pcm_config_mmap_playback = {
160 .channels = DEFAULT_CHANNEL_COUNT,
161 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
162 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800163 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800164 .format = PCM_FORMAT_S16_LE,
165 .start_threshold = MMAP_PERIOD_SIZE*8,
166 .stop_threshold = INT32_MAX,
167 .silence_threshold = 0,
168 .silence_size = 0,
169 .avail_min = MMAP_PERIOD_SIZE, //1 ms
170};
171
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800172struct pcm_config pcm_config_hifi = {
173 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
174 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
175 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
176 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
177 .format = PCM_FORMAT_S24_3LE,
178 .start_threshold = 0,
179 .stop_threshold = INT_MAX,
180 .avail_min = 0,
181};
182
Eric Laurentb23d5282013-05-14 15:27:20 -0700183struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700184 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700185 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
186 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700187 .stop_threshold = INT_MAX,
188 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700189};
190
Haynes Mathew George03c40102016-01-29 17:57:48 -0800191struct pcm_config pcm_config_audio_capture_rt = {
192 .channels = DEFAULT_CHANNEL_COUNT,
193 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
194 .period_size = ULL_PERIOD_SIZE,
195 .period_count = 512,
196 .format = PCM_FORMAT_S16_LE,
197 .start_threshold = 0,
198 .stop_threshold = INT_MAX,
199 .silence_threshold = 0,
200 .silence_size = 0,
201 .avail_min = ULL_PERIOD_SIZE, //1 ms
202};
203
Eric Laurent0e46adf2016-12-16 12:49:24 -0800204struct pcm_config pcm_config_mmap_capture = {
205 .channels = DEFAULT_CHANNEL_COUNT,
206 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
207 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800208 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800209 .format = PCM_FORMAT_S16_LE,
210 .start_threshold = 0,
211 .stop_threshold = INT_MAX,
212 .silence_threshold = 0,
213 .silence_size = 0,
214 .avail_min = MMAP_PERIOD_SIZE, //1 ms
215};
216
vivek mehtaa68fea62017-06-08 19:04:02 -0700217struct pcm_config pcm_config_voip = {
218 .channels = 1,
219 .period_count = 2,
220 .format = PCM_FORMAT_S16_LE,
221 .stop_threshold = INT_MAX,
222 .avail_min = 0,
223};
224
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700225#define AFE_PROXY_CHANNEL_COUNT 2
226#define AFE_PROXY_SAMPLING_RATE 48000
227
228#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
229#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
230
231struct pcm_config pcm_config_afe_proxy_playback = {
232 .channels = AFE_PROXY_CHANNEL_COUNT,
233 .rate = AFE_PROXY_SAMPLING_RATE,
234 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
235 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
236 .format = PCM_FORMAT_S16_LE,
237 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
238 .stop_threshold = INT_MAX,
239 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
240};
241
242#define AFE_PROXY_RECORD_PERIOD_SIZE 768
243#define AFE_PROXY_RECORD_PERIOD_COUNT 4
244
245struct pcm_config pcm_config_afe_proxy_record = {
246 .channels = AFE_PROXY_CHANNEL_COUNT,
247 .rate = AFE_PROXY_SAMPLING_RATE,
248 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
249 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
250 .format = PCM_FORMAT_S16_LE,
251 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
jiabin5d0261e2018-05-25 09:43:59 -0700252 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700253 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
254};
255
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700256const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700257 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
258 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800259 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700260 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700261 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700262 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800263 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700264
Eric Laurentb23d5282013-05-14 15:27:20 -0700265 [USECASE_AUDIO_RECORD] = "audio-record",
266 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800267 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George569b7482017-05-08 14:44:27 -0700268 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700269
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800270 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
271 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700272
Eric Laurentb23d5282013-05-14 15:27:20 -0700273 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700274 [USECASE_VOICE2_CALL] = "voice2-call",
275 [USECASE_VOLTE_CALL] = "volte-call",
276 [USECASE_QCHAT_CALL] = "qchat-call",
277 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800278 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
279 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700280
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700281 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
282 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
283
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700284 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
285 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
vivek mehta781065c2017-04-04 12:55:01 -0700286
287 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
288 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
289 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
290
vivek mehtaa68fea62017-06-08 19:04:02 -0700291 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
292 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Nadav Bar3d72cfc2018-01-07 12:19:24 +0200293
294 [USECASE_INCALL_MUSIC_UPLINK] = "incall-music-uplink",
Aniket Kumar Lata99546312018-03-19 21:38:38 -0700295
296 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700297};
298
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800299
300#define STRING_TO_ENUM(string) { #string, string }
301
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800302struct string_to_enum {
303 const char *name;
304 uint32_t value;
305};
306
Haynes Mathew George569b7482017-05-08 14:44:27 -0700307static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800308 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
309 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
310 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Eric Laurent74b55762017-07-09 17:04:53 -0700311 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
Haynes Mathew George569b7482017-05-08 14:44:27 -0700312 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
Eric Laurent74b55762017-07-09 17:04:53 -0700313 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
314 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
315 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
316 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
317 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
318 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
319 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
320 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
321 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800322};
323
Haynes Mathew George5191a852013-09-11 14:19:36 -0700324static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700325static struct audio_device *adev = NULL;
Andy Hung9e737de2017-05-22 10:51:22 -0700326static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700327static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700328//cache last MBDRC cal step level
329static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700330
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800331static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
332static int set_compr_volume(struct audio_stream_out *stream, float left, float right);
333
Haynes Mathew George03c40102016-01-29 17:57:48 -0800334static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
335 int flags __unused)
336{
337 int dir = 0;
338 switch (uc_id) {
339 case USECASE_AUDIO_RECORD_LOW_LATENCY:
340 dir = 1;
341 case USECASE_AUDIO_PLAYBACK_ULL:
342 break;
343 default:
344 return false;
345 }
346
347 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
348 PCM_PLAYBACK : PCM_CAPTURE);
349 if (adev->adm_is_noirq_avail)
350 return adev->adm_is_noirq_avail(adev->adm_data,
351 adev->snd_card, dev_id, dir);
352 return false;
353}
354
355static void register_out_stream(struct stream_out *out)
356{
357 struct audio_device *adev = out->dev;
358 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
359 return;
360
361 if (!adev->adm_register_output_stream)
362 return;
363
364 adev->adm_register_output_stream(adev->adm_data,
365 out->handle,
366 out->flags);
367
368 if (!adev->adm_set_config)
369 return;
370
371 if (out->realtime) {
372 adev->adm_set_config(adev->adm_data,
373 out->handle,
374 out->pcm, &out->config);
375 }
376}
377
378static void register_in_stream(struct stream_in *in)
379{
380 struct audio_device *adev = in->dev;
381 if (!adev->adm_register_input_stream)
382 return;
383
384 adev->adm_register_input_stream(adev->adm_data,
385 in->capture_handle,
386 in->flags);
387
388 if (!adev->adm_set_config)
389 return;
390
391 if (in->realtime) {
392 adev->adm_set_config(adev->adm_data,
393 in->capture_handle,
394 in->pcm,
395 &in->config);
396 }
397}
398
399static void request_out_focus(struct stream_out *out, long ns)
400{
401 struct audio_device *adev = out->dev;
402
Haynes Mathew George03c40102016-01-29 17:57:48 -0800403 if (adev->adm_request_focus_v2) {
404 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
405 } else if (adev->adm_request_focus) {
406 adev->adm_request_focus(adev->adm_data, out->handle);
407 }
408}
409
410static void request_in_focus(struct stream_in *in, long ns)
411{
412 struct audio_device *adev = in->dev;
413
Haynes Mathew George03c40102016-01-29 17:57:48 -0800414 if (adev->adm_request_focus_v2) {
415 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
416 } else if (adev->adm_request_focus) {
417 adev->adm_request_focus(adev->adm_data, in->capture_handle);
418 }
419}
420
421static void release_out_focus(struct stream_out *out, long ns __unused)
422{
423 struct audio_device *adev = out->dev;
424
425 if (adev->adm_abandon_focus)
426 adev->adm_abandon_focus(adev->adm_data, out->handle);
427}
428
429static void release_in_focus(struct stream_in *in, long ns __unused)
430{
431 struct audio_device *adev = in->dev;
432 if (adev->adm_abandon_focus)
433 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
434}
435
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700436static int parse_snd_card_status(struct str_parms * parms, int * card,
437 card_status_t * status)
438{
439 char value[32]={0};
440 char state[32]={0};
441
442 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
443
444 if (ret < 0)
445 return -1;
446
447 // sscanf should be okay as value is of max length 32.
448 // same as sizeof state.
449 if (sscanf(value, "%d,%s", card, state) < 2)
450 return -1;
451
452 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
453 CARD_STATUS_OFFLINE;
454 return 0;
455}
456
vivek mehta40125092017-08-21 18:48:51 -0700457// always call with adev lock held
458void send_gain_dep_calibration_l() {
459 if (last_known_cal_step >= 0)
460 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
461}
462
vivek mehta1a9b7c02015-06-25 11:49:38 -0700463__attribute__ ((visibility ("default")))
464bool audio_hw_send_gain_dep_calibration(int level) {
465 bool ret_val = false;
466 ALOGV("%s: enter ... ", __func__);
467
468 pthread_mutex_lock(&adev_init_lock);
469
470 if (adev != NULL && adev->platform != NULL) {
471 pthread_mutex_lock(&adev->lock);
vivek mehta40125092017-08-21 18:48:51 -0700472 last_known_cal_step = level;
473 send_gain_dep_calibration_l();
vivek mehta1a9b7c02015-06-25 11:49:38 -0700474 pthread_mutex_unlock(&adev->lock);
475 } else {
476 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
477 }
478
479 pthread_mutex_unlock(&adev_init_lock);
480
481 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
482 return ret_val;
483}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700484
jasmine cha270b7762018-03-30 15:41:33 +0800485#ifdef MAXXAUDIO_QDSP_ENABLED
486bool audio_hw_send_ma_parameter(int stream_type, float vol, bool active)
487{
488 bool ret = false;
489 ALOGV("%s: enter ...", __func__);
490
491 pthread_mutex_lock(&adev_init_lock);
492
493 if (adev != NULL && adev->platform != NULL) {
494 pthread_mutex_lock(&adev->lock);
495 ret = audio_extn_ma_set_state(adev, stream_type, vol, active);
496 pthread_mutex_unlock(&adev->lock);
497 }
498
499 pthread_mutex_unlock(&adev_init_lock);
500
501 ALOGV("%s: exit with ret %d", __func__, ret);
502 return ret;
503}
504#else
505#define audio_hw_send_ma_parameter(stream_type, vol, active) (0)
506#endif
507
vivek mehtaa8d7c922016-05-25 14:40:44 -0700508__attribute__ ((visibility ("default")))
509int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
510 int table_size) {
511 int ret_val = 0;
512 ALOGV("%s: enter ... ", __func__);
513
514 pthread_mutex_lock(&adev_init_lock);
515 if (adev == NULL) {
516 ALOGW("%s: adev is NULL .... ", __func__);
517 goto done;
518 }
519
520 pthread_mutex_lock(&adev->lock);
521 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
522 pthread_mutex_unlock(&adev->lock);
523done:
524 pthread_mutex_unlock(&adev_init_lock);
525 ALOGV("%s: exit ... ", __func__);
526 return ret_val;
527}
528
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700529static bool is_supported_format(audio_format_t format)
530{
Eric Laurent8251ac82014-07-23 11:00:25 -0700531 switch (format) {
532 case AUDIO_FORMAT_MP3:
533 case AUDIO_FORMAT_AAC_LC:
534 case AUDIO_FORMAT_AAC_HE_V1:
535 case AUDIO_FORMAT_AAC_HE_V2:
536 return true;
537 default:
538 break;
539 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700540 return false;
541}
542
Haynes Mathew George03c40102016-01-29 17:57:48 -0800543static inline bool is_mmap_usecase(audio_usecase_t uc_id)
544{
545 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
546 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
547}
548
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700549static int get_snd_codec_id(audio_format_t format)
550{
551 int id = 0;
552
Eric Laurent8251ac82014-07-23 11:00:25 -0700553 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700554 case AUDIO_FORMAT_MP3:
555 id = SND_AUDIOCODEC_MP3;
556 break;
557 case AUDIO_FORMAT_AAC:
558 id = SND_AUDIOCODEC_AAC;
559 break;
560 default:
561 ALOGE("%s: Unsupported audio format", __func__);
562 }
563
564 return id;
565}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800566
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800567static int audio_ssr_status(struct audio_device *adev)
568{
569 int ret = 0;
570 struct mixer_ctl *ctl;
571 const char *mixer_ctl_name = "Audio SSR Status";
572
573 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
574 ret = mixer_ctl_get_value(ctl, 0);
575 ALOGD("%s: value: %d", __func__, ret);
576 return ret;
577}
578
vivek mehta4a824772017-06-08 19:05:49 -0700579static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
580{
581 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
582}
583
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800584static bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
585{
586 return out_snd_device == SND_DEVICE_OUT_BT_SCO ||
587 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
588 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
589 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
590 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
591 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC;
592
593}
594
595static bool is_a2dp_device(snd_device_t out_snd_device)
596{
597 return out_snd_device == SND_DEVICE_OUT_BT_A2DP;
598}
599
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800600int enable_audio_route(struct audio_device *adev,
601 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800602{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800603 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800604
605 if (usecase == NULL)
606 return -EINVAL;
607
608 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
609
Yamit Mehtae3b99562016-09-16 22:44:00 +0530610 audio_extn_utils_send_app_type_cfg(adev, usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800611 audio_extn_utils_send_audio_calibration(adev, usecase);
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000612 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
yixuanjiang6c5e87c2018-08-13 11:50:26 +0800613 strcpy(mixer_path, use_case_table[usecase->id]);
614
615 if (usecase->type == VOICE_CALL) {
616 platform_add_backend_name(adev->platform, mixer_path, usecase->in_snd_device);
617 if (!strstr(mixer_path, " "))
618 platform_add_backend_name(adev->platform, mixer_path, usecase->out_snd_device);
619 } else if (usecase->type == PCM_CAPTURE) {
620 platform_add_backend_name(adev->platform, mixer_path, usecase->in_snd_device);
621 } else {
622 platform_add_backend_name(adev->platform, mixer_path, usecase->out_snd_device);
623 }
624
Eric Laurent2e140aa2016-06-30 17:14:46 -0700625 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700626 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800627
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800628 ALOGV("%s: exit", __func__);
629 return 0;
630}
631
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800632int disable_audio_route(struct audio_device *adev,
633 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800634{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800635 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800636
637 if (usecase == NULL)
638 return -EINVAL;
639
640 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800641 strcpy(mixer_path, use_case_table[usecase->id]);
yixuanjiang6c5e87c2018-08-13 11:50:26 +0800642
643 if (usecase->type == VOICE_CALL) {
644 platform_add_backend_name(adev->platform, mixer_path, usecase->in_snd_device);
645 if (!strstr(mixer_path, " "))
646 platform_add_backend_name(adev->platform, mixer_path, usecase->out_snd_device);
647 } else if (usecase->type == PCM_CAPTURE) {
648 platform_add_backend_name(adev->platform, mixer_path, usecase->in_snd_device);
649 } else {
650 platform_add_backend_name(adev->platform, mixer_path, usecase->out_snd_device);
651 }
652
Eric Laurent2e140aa2016-06-30 17:14:46 -0700653 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700654 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000655 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800656
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800657 ALOGV("%s: exit", __func__);
658 return 0;
659}
660
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800661int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700662 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800663{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700664 int i, num_devices = 0;
665 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800666 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800667 if (snd_device < SND_DEVICE_MIN ||
668 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800669 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800670 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800671 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700672
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700673 platform_send_audio_calibration(adev->platform, snd_device);
674
vivek mehtade4849c2016-03-03 17:23:38 -0800675 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700676 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700677 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800678 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700679 }
680
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700681 /* due to the possibility of calibration overwrite between listen
682 and audio, notify sound trigger hal before audio calibration is sent */
683 audio_extn_sound_trigger_update_device_status(snd_device,
684 ST_EVENT_SND_DEVICE_BUSY);
685
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700686 if (audio_extn_spkr_prot_is_enabled())
687 audio_extn_spkr_prot_calib_cancel(adev);
688
zhaoyang yin4211fad2015-06-04 21:13:25 +0800689 audio_extn_dsm_feedback_enable(adev, snd_device, true);
690
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700691 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800692 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
juyuchen1d05ba32018-03-31 16:03:51 +0800693 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700694 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
695 audio_extn_spkr_prot_is_enabled()) {
Aniket Kumar Lata9d6679a2018-04-11 18:13:23 -0700696 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800697 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700698 }
699 if (audio_extn_spkr_prot_start_processing(snd_device)) {
700 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800701 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700702 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700703 } else if (platform_can_split_snd_device(snd_device,
704 &num_devices,
705 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700706 for (i = 0; i < num_devices; i++) {
707 enable_snd_device(adev, new_snd_devices[i]);
708 }
vivek mehtab6506412015-08-07 16:55:17 -0700709 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700710 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800711 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
712 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
713 ALOGE(" %s: Invalid sound device returned", __func__);
714 goto on_error;
715 }
Ed Tam70b5c142016-03-21 19:14:29 -0700716
Eric Laurent2e140aa2016-06-30 17:14:46 -0700717 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Aniket Kumar Lataa158e862018-05-11 17:28:40 -0700718
719 if (is_a2dp_device(snd_device) &&
720 (audio_extn_a2dp_start_playback() < 0)) {
721 ALOGE("%s: failed to configure A2DP control path", __func__);
722 goto on_error;
723 }
724
vivek mehtade4849c2016-03-03 17:23:38 -0800725 audio_route_apply_and_update_path(adev->audio_route, device_name);
726 }
727on_success:
728 adev->snd_dev_ref_cnt[snd_device]++;
729 ret_val = 0;
730on_error:
731 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800732}
733
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800734int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700735 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800736{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700737 int i, num_devices = 0;
738 snd_device_t new_snd_devices[2];
739
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800740 if (snd_device < SND_DEVICE_MIN ||
741 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800742 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800743 return -EINVAL;
744 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700745 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
746 ALOGE("%s: device ref cnt is already 0", __func__);
747 return -EINVAL;
748 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800749 audio_extn_tfa_98xx_disable_speaker(snd_device);
750
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700751 adev->snd_dev_ref_cnt[snd_device]--;
752 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800753 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800754
755 if (is_a2dp_device(snd_device))
756 audio_extn_a2dp_stop_playback();
757
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700758 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800759 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700760 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700761 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
762 audio_extn_spkr_prot_is_enabled()) {
763 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700764
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700765 // FIXME b/65363602: bullhead is the only Nexus with audio_extn_spkr_prot_is_enabled()
766 // and does not use speaker swap. As this code causes a problem with device enable ref
767 // counting we remove it for now.
vivek mehtae59cfb22017-06-16 15:57:11 -0700768 // when speaker device is disabled, reset swap.
769 // will be renabled on usecase start
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700770 // platform_set_swap_channels(adev, false);
vivek mehtae59cfb22017-06-16 15:57:11 -0700771
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700772 } else if (platform_can_split_snd_device(snd_device,
773 &num_devices,
774 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700775 for (i = 0; i < num_devices; i++) {
776 disable_snd_device(adev, new_snd_devices[i]);
777 }
vivek mehtab6506412015-08-07 16:55:17 -0700778 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700779 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800780 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
781 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
782 ALOGE(" %s: Invalid sound device returned", __func__);
783 return -EINVAL;
784 }
785
Eric Laurent2e140aa2016-06-30 17:14:46 -0700786 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800787 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700788 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700789 audio_extn_sound_trigger_update_device_status(snd_device,
790 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700791 }
vivek mehtab6506412015-08-07 16:55:17 -0700792
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800793 return 0;
794}
795
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700796/*
797 legend:
798 uc - existing usecase
799 new_uc - new usecase
800 d1, d11, d2 - SND_DEVICE enums
801 a1, a2 - corresponding ANDROID device enums
802 B, B1, B2 - backend strings
803
804case 1
805 uc->dev d1 (a1) B1
806 new_uc->dev d1 (a1), d2 (a2) B1, B2
807
808 resolution: disable and enable uc->dev on d1
809
810case 2
811 uc->dev d1 (a1) B1
812 new_uc->dev d11 (a1) B1
813
814 resolution: need to switch uc since d1 and d11 are related
815 (e.g. speaker and voice-speaker)
816 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
817
818case 3
819 uc->dev d1 (a1) B1
820 new_uc->dev d2 (a2) B2
821
822 resolution: no need to switch uc
823
824case 4
825 uc->dev d1 (a1) B
826 new_uc->dev d2 (a2) B
827
828 resolution: disable enable uc-dev on d2 since backends match
829 we cannot enable two streams on two different devices if they
830 share the same backend. e.g. if offload is on speaker device using
831 QUAD_MI2S backend and a low-latency stream is started on voice-handset
832 using the same backend, offload must also be switched to voice-handset.
833
834case 5
835 uc->dev d1 (a1) B
836 new_uc->dev d1 (a1), d2 (a2) B
837
838 resolution: disable enable uc-dev on d2 since backends match
839 we cannot enable two streams on two different devices if they
840 share the same backend.
841
842case 6
843 uc->dev d1 a1 B1
844 new_uc->dev d2 a1 B2
845
846 resolution: no need to switch
847
848case 7
849
850 uc->dev d1 (a1), d2 (a2) B1, B2
851 new_uc->dev d1 B1
852
853 resolution: no need to switch
854
855*/
856static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
857 struct audio_usecase *new_uc,
858 snd_device_t new_snd_device)
859{
860 audio_devices_t a1 = uc->stream.out->devices;
861 audio_devices_t a2 = new_uc->stream.out->devices;
862
863 snd_device_t d1 = uc->out_snd_device;
864 snd_device_t d2 = new_snd_device;
865
866 // Treat as a special case when a1 and a2 are not disjoint
867 if ((a1 != a2) && (a1 & a2)) {
868 snd_device_t d3[2];
869 int num_devices = 0;
870 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
871 &num_devices,
872 d3);
873 if (ret < 0) {
874 if (ret != -ENOSYS) {
875 ALOGW("%s failed to split snd_device %d",
876 __func__,
877 popcount(a1) > 1 ? d1 : d2);
878 }
879 goto end;
880 }
881
882 // NB: case 7 is hypothetical and isn't a practical usecase yet.
883 // But if it does happen, we need to give priority to d2 if
884 // the combo devices active on the existing usecase share a backend.
885 // This is because we cannot have a usecase active on a combo device
886 // and a new usecase requests one device in this combo pair.
887 if (platform_check_backends_match(d3[0], d3[1])) {
888 return d2; // case 5
889 } else {
890 return d1; // case 1
891 }
892 } else {
893 if (platform_check_backends_match(d1, d2)) {
894 return d2; // case 2, 4
895 } else {
896 return d1; // case 6, 3
897 }
898 }
899
900end:
901 return d2; // return whatever was calculated before.
902}
903
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700904static void check_and_route_playback_usecases(struct audio_device *adev,
905 struct audio_usecase *uc_info,
906 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700907{
908 struct listnode *node;
909 struct audio_usecase *usecase;
910 bool switch_device[AUDIO_USECASE_MAX];
911 int i, num_uc_to_switch = 0;
912
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700913 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
914 uc_info,
915 snd_device);
David Linee3fe402017-03-13 10:00:42 -0700916
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800917 /* For a2dp device reconfigure all active sessions
918 * with new AFE encoder format based on a2dp state
919 */
920 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Aniket Kumar Lata9723a962018-05-16 17:41:55 -0700921 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
922 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800923 audio_extn_a2dp_is_force_device_switch()) {
924 force_routing = true;
925 }
926
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700927 /*
928 * This function is to make sure that all the usecases that are active on
929 * the hardware codec backend are always routed to any one device that is
930 * handled by the hardware codec.
931 * For example, if low-latency and deep-buffer usecases are currently active
932 * on speaker and out_set_parameters(headset) is received on low-latency
933 * output, then we have to make sure deep-buffer is also switched to headset,
934 * because of the limitation that both the devices cannot be enabled
935 * at the same time as they share the same backend.
936 */
937 /* Disable all the usecases on the shared backend other than the
938 specified usecase */
939 for (i = 0; i < AUDIO_USECASE_MAX; i++)
940 switch_device[i] = false;
941
942 list_for_each(node, &adev->usecase_list) {
943 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700944 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
945 continue;
946
947 if (force_routing ||
948 (usecase->out_snd_device != snd_device &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -0700949 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
950 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700951 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700952 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
953 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700954 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700955 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700956 switch_device[usecase->id] = true;
957 num_uc_to_switch++;
958 }
959 }
960
961 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700962 list_for_each(node, &adev->usecase_list) {
963 usecase = node_to_item(node, struct audio_usecase, list);
964 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700965 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900966 }
967 }
968
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700969 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900970 list_for_each(node, &adev->usecase_list) {
971 usecase = node_to_item(node, struct audio_usecase, list);
972 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700973 d_device = derive_playback_snd_device(usecase, uc_info,
974 snd_device);
975 enable_snd_device(adev, d_device);
976 /* Update the out_snd_device before enabling the audio route */
977 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700978 }
979 }
980
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700981 /* Re-route all the usecases on the shared backend other than the
982 specified usecase to new snd devices */
983 list_for_each(node, &adev->usecase_list) {
984 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700985 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700986 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700987 }
988 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700989 }
990}
991
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700992static void check_and_route_capture_usecases(struct audio_device *adev,
993 struct audio_usecase *uc_info,
994 snd_device_t snd_device)
995{
996 struct listnode *node;
997 struct audio_usecase *usecase;
998 bool switch_device[AUDIO_USECASE_MAX];
999 int i, num_uc_to_switch = 0;
1000
vivek mehta4ed66e62016-04-15 23:33:34 -07001001 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
1002
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001003 /*
1004 * This function is to make sure that all the active capture usecases
1005 * are always routed to the same input sound device.
1006 * For example, if audio-record and voice-call usecases are currently
1007 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1008 * is received for voice call then we have to make sure that audio-record
1009 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1010 * because of the limitation that two devices cannot be enabled
1011 * at the same time if they share the same backend.
1012 */
1013 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1014 switch_device[i] = false;
1015
1016 list_for_each(node, &adev->usecase_list) {
1017 usecase = node_to_item(node, struct audio_usecase, list);
1018 if (usecase->type != PCM_PLAYBACK &&
1019 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -07001020 usecase->in_snd_device != snd_device &&
1021 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001022 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1023 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001024 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001025 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001026 switch_device[usecase->id] = true;
1027 num_uc_to_switch++;
1028 }
1029 }
1030
1031 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001032 list_for_each(node, &adev->usecase_list) {
1033 usecase = node_to_item(node, struct audio_usecase, list);
1034 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001035 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001036 }
1037 }
1038
1039 list_for_each(node, &adev->usecase_list) {
1040 usecase = node_to_item(node, struct audio_usecase, list);
1041 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001042 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001043 }
1044 }
1045
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001046 /* Re-route all the usecases on the shared backend other than the
1047 specified usecase to new snd devices */
1048 list_for_each(node, &adev->usecase_list) {
1049 usecase = node_to_item(node, struct audio_usecase, list);
1050 /* Update the in_snd_device only before enabling the audio route */
1051 if (switch_device[usecase->id] ) {
1052 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001053 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001054 }
1055 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001056 }
1057}
1058
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001059/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001060static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001061{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001062 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001063 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001064
1065 switch (channels) {
1066 /*
1067 * Do not handle stereo output in Multi-channel cases
1068 * Stereo case is handled in normal playback path
1069 */
1070 case 6:
1071 ALOGV("%s: HDMI supports 5.1", __func__);
1072 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1073 break;
1074 case 8:
1075 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
1076 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1077 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
1078 break;
1079 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001080 ALOGE("HDMI does not support multi channel playback");
1081 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001082 break;
1083 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001084 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001085}
1086
Andy Hung18859412017-08-09 11:47:21 -07001087static ssize_t read_usb_sup_sample_rates(bool is_playback,
1088 uint32_t *supported_sample_rates,
1089 uint32_t max_rates)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001090{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001091 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1092 supported_sample_rates,
1093 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001094#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001095 for (ssize_t i=0; i<count; i++) {
1096 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1097 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001098 }
1099#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001100 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001101}
1102
Haynes Mathew George569b7482017-05-08 14:44:27 -07001103static int read_usb_sup_channel_masks(bool is_playback,
1104 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001105 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001106{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001107 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001108 int channel_count;
1109 uint32_t num_masks = 0;
1110 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1111 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001112 }
Eric Laurent74b55762017-07-09 17:04:53 -07001113 if (is_playback) {
Andy Hung6c1afb12017-12-22 11:34:41 -08001114 // start from 2 channels as framework currently doesn't support mono.
1115 // TODO: consider only supporting channel index masks beyond stereo here.
1116 for (channel_count = FCC_2;
1117 channel_count <= channels && num_masks < max_masks;
1118 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001119 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1120 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001121 for (channel_count = FCC_2;
1122 channel_count <= channels && num_masks < max_masks;
1123 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001124 supported_channel_masks[num_masks++] =
1125 audio_channel_mask_for_index_assignment_from_count(channel_count);
1126 }
1127 } else {
1128 // For capture we report all supported channel masks from 1 channel up.
1129 channel_count = MIN_CHANNEL_COUNT;
1130 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1131 // indexed mask
1132 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1133 supported_channel_masks[num_masks++] =
1134 audio_channel_in_mask_from_count(channel_count);
1135 }
1136 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001137#ifdef NDEBUG
1138 for (size_t i = 0; i < num_masks; ++i) {
1139 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1140 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
1141 }
1142#endif
Eric Laurent74b55762017-07-09 17:04:53 -07001143 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001144}
1145
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001146static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001147 audio_format_t *supported_formats,
1148 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001149{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001150 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001151 switch (bitwidth) {
1152 case 24:
1153 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001154 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001155 break;
1156 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001157 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001158 break;
1159 case 16:
1160 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001161 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001162 break;
1163 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001164 ALOGV("%s: %s supported format %d", __func__,
1165 is_playback ? "P" : "C", bitwidth);
1166 return 1;
1167}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001168
Haynes Mathew George569b7482017-05-08 14:44:27 -07001169static int read_usb_sup_params_and_compare(bool is_playback,
1170 audio_format_t *format,
1171 audio_format_t *supported_formats,
1172 uint32_t max_formats,
1173 audio_channel_mask_t *mask,
1174 audio_channel_mask_t *supported_channel_masks,
1175 uint32_t max_masks,
1176 uint32_t *rate,
1177 uint32_t *supported_sample_rates,
1178 uint32_t max_rates) {
1179 int ret = 0;
1180 int num_formats;
1181 int num_masks;
1182 int num_rates;
1183 int i;
1184
1185 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1186 max_formats);
1187 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1188 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001189
Haynes Mathew George569b7482017-05-08 14:44:27 -07001190 num_rates = read_usb_sup_sample_rates(is_playback,
1191 supported_sample_rates, max_rates);
1192
1193#define LUT(table, len, what, dflt) \
1194 for (i=0; i<len && (table[i] != what); i++); \
1195 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1196
1197 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1198 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1199 LUT(supported_sample_rates, num_rates, *rate, 0);
1200
1201#undef LUT
1202 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001203}
1204
Andy Hungd9653bd2017-08-01 19:31:39 -07001205static bool is_usb_ready(struct audio_device *adev, bool is_playback)
1206{
1207 // Check if usb is ready.
1208 // The usb device may have been removed quickly after insertion and hence
1209 // no longer available. This will show up as empty channel masks, or rates.
1210
1211 pthread_mutex_lock(&adev->lock);
1212 uint32_t supported_sample_rate;
1213
1214 // we consider usb ready if we can fetch at least one sample rate.
1215 const bool ready = read_usb_sup_sample_rates(
1216 is_playback, &supported_sample_rate, 1 /* max_rates */) > 0;
1217 pthread_mutex_unlock(&adev->lock);
1218 return ready;
1219}
1220
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001221static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1222{
1223 struct audio_usecase *usecase;
1224 struct listnode *node;
1225
1226 list_for_each(node, &adev->usecase_list) {
1227 usecase = node_to_item(node, struct audio_usecase, list);
1228 if (usecase->type == VOICE_CALL) {
1229 ALOGV("%s: usecase id %d", __func__, usecase->id);
1230 return usecase->id;
1231 }
1232 }
1233 return USECASE_INVALID;
1234}
1235
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001236struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1237 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001238{
1239 struct audio_usecase *usecase;
1240 struct listnode *node;
1241
1242 list_for_each(node, &adev->usecase_list) {
1243 usecase = node_to_item(node, struct audio_usecase, list);
1244 if (usecase->id == uc_id)
1245 return usecase;
1246 }
1247 return NULL;
1248}
1249
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001250static bool force_device_switch(struct audio_usecase *usecase)
1251{
1252 if (usecase->stream.out == NULL) {
1253 ALOGE("%s: stream.out is NULL", __func__);
1254 return false;
1255 }
1256
1257 // Force all A2DP output devices to reconfigure for proper AFE encode format
1258 // Also handle a case where in earlier A2DP start failed as A2DP stream was
1259 // in suspended state, hence try to trigger a retry when we again get a routing request.
1260 if ((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
1261 audio_extn_a2dp_is_force_device_switch()) {
1262 ALOGD("%s: Force A2DP device switch to update new encoder config", __func__);
1263 return true;
1264 }
1265
1266 return false;
1267}
1268
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001269int select_devices(struct audio_device *adev,
1270 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001271{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001272 snd_device_t out_snd_device = SND_DEVICE_NONE;
1273 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001274 struct audio_usecase *usecase = NULL;
1275 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001276 struct audio_usecase *hfp_usecase = NULL;
1277 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001278 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001279 int status = 0;
Eric Laurentf4520b02017-09-20 18:31:58 -07001280 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1281 USECASE_AUDIO_PLAYBACK_VOIP);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001282
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001283 usecase = get_usecase_from_list(adev, uc_id);
1284 if (usecase == NULL) {
1285 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1286 return -EINVAL;
1287 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001288
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001289 if ((usecase->type == VOICE_CALL) ||
1290 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001291 out_snd_device = platform_get_output_snd_device(adev->platform,
1292 usecase->stream.out->devices);
1293 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001294 usecase->devices = usecase->stream.out->devices;
1295 } else {
1296 /*
1297 * If the voice call is active, use the sound devices of voice call usecase
1298 * so that it would not result any device switch. All the usecases will
1299 * be switched to new device when select_devices() is called for voice call
1300 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001301 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001302 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001303 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001304 vc_usecase = get_usecase_from_list(adev,
1305 get_voice_usecase_id_from_list(adev));
1306 if ((vc_usecase != NULL) &&
1307 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1308 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001309 in_snd_device = vc_usecase->in_snd_device;
1310 out_snd_device = vc_usecase->out_snd_device;
1311 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001312 } else if (audio_extn_hfp_is_active(adev)) {
1313 hfp_ucid = audio_extn_hfp_get_usecase();
1314 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1315 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1316 in_snd_device = hfp_usecase->in_snd_device;
1317 out_snd_device = hfp_usecase->out_snd_device;
1318 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001319 }
1320 if (usecase->type == PCM_PLAYBACK) {
1321 usecase->devices = usecase->stream.out->devices;
1322 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001323 if (out_snd_device == SND_DEVICE_NONE) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001324 struct stream_out *voip_out = adev->primary_output;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001325
Eric Laurentb23d5282013-05-14 15:27:20 -07001326 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001327 usecase->stream.out->devices);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001328
1329 if (voip_usecase)
1330 voip_out = voip_usecase->stream.out;
1331
1332 if (usecase->stream.out == voip_out &&
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001333 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001334 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001335 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001336 select_devices(adev, adev->active_input->usecase);
1337 }
1338 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001339 } else if (usecase->type == PCM_CAPTURE) {
1340 usecase->devices = usecase->stream.in->device;
1341 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001342 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001343 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001344 if (adev->active_input &&
1345 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1346 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001347
1348 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1349 USECASE_AUDIO_PLAYBACK_VOIP);
1350
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001351 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001352 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1353 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001354 } else if (voip_usecase) {
1355 out_device = voip_usecase->stream.out->devices;
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001356 } else if (adev->primary_output) {
1357 out_device = adev->primary_output->devices;
1358 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001359 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001360 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001361 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001362 }
1363 }
1364
1365 if (out_snd_device == usecase->out_snd_device &&
1366 in_snd_device == usecase->in_snd_device) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001367 if (!force_device_switch(usecase))
1368 return 0;
1369 }
1370
1371 if (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready()) {
1372 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1373 return 0;
1374 }
1375
Aniket Kumar Lata9723a962018-05-16 17:41:55 -07001376 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
1377 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001378 (!audio_extn_a2dp_is_ready())) {
1379 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
juyuchen9baad392018-06-05 19:02:10 +08001380 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
1381 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
1382 else
1383 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001384 }
1385
juyuchen66c4ecf2018-08-06 15:39:34 +08001386 if (usecase->id == USECASE_INCALL_MUSIC_UPLINK) {
1387 out_snd_device = SND_DEVICE_OUT_VOICE_MUSIC_TX;
1388 }
1389
Eric Laurent2bafff12016-03-17 12:17:23 -07001390 if (out_snd_device != SND_DEVICE_NONE &&
1391 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1392 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1393 __func__,
1394 use_case_table[uc_id],
1395 adev->last_logged_snd_device[uc_id][0],
1396 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1397 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1398 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1399 -1,
1400 out_snd_device,
1401 platform_get_snd_device_name(out_snd_device),
1402 platform_get_snd_device_acdb_id(out_snd_device));
1403 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1404 }
1405 if (in_snd_device != SND_DEVICE_NONE &&
1406 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1407 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1408 __func__,
1409 use_case_table[uc_id],
1410 adev->last_logged_snd_device[uc_id][1],
1411 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1412 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1413 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1414 -1,
1415 in_snd_device,
1416 platform_get_snd_device_name(in_snd_device),
1417 platform_get_snd_device_acdb_id(in_snd_device));
1418 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1419 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001420
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001421 /*
1422 * Limitation: While in call, to do a device switch we need to disable
1423 * and enable both RX and TX devices though one of them is same as current
1424 * device.
1425 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001426 if ((usecase->type == VOICE_CALL) &&
1427 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1428 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001429 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001430 /* Disable sidetone only if voice call already exists */
1431 if (voice_is_call_state_active(adev))
1432 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001433 }
1434
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001435 /* Disable current sound devices */
1436 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001437 disable_audio_route(adev, usecase);
1438 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001439 }
1440
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001441 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001442 disable_audio_route(adev, usecase);
1443 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001444 }
1445
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001446 /* Applicable only on the targets that has external modem.
1447 * New device information should be sent to modem before enabling
1448 * the devices to reduce in-call device switch time.
1449 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001450 if ((usecase->type == VOICE_CALL) &&
1451 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1452 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001453 status = platform_switch_voice_call_enable_device_config(adev->platform,
1454 out_snd_device,
1455 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001456 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001457
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001458 /* Enable new sound devices */
1459 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001460 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001461 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) ||
1462 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001463 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001464 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001465 }
1466
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001467 if (in_snd_device != SND_DEVICE_NONE) {
1468 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001469 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001470 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001471
Eric Laurentb23d5282013-05-14 15:27:20 -07001472 if (usecase->type == VOICE_CALL)
1473 status = platform_switch_voice_call_device_post(adev->platform,
1474 out_snd_device,
1475 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001476
sangwoo170731f2013-06-08 15:36:36 +09001477 usecase->in_snd_device = in_snd_device;
1478 usecase->out_snd_device = out_snd_device;
1479
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001480 audio_extn_tfa_98xx_set_mode();
1481
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001482 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001483
Jasmine Cha70771b62018-05-15 15:02:43 +08001484 audio_extn_ma_set_device(usecase);
jasmine cha270b7762018-03-30 15:41:33 +08001485
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001486 /* Applicable only on the targets that has external modem.
1487 * Enable device command should be sent to modem only after
1488 * enabling voice call mixer controls
1489 */
vivek mehta765eb642015-08-07 19:46:06 -07001490 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001491 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1492 out_snd_device,
1493 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001494 /* Enable sidetone only if voice call already exists */
1495 if (voice_is_call_state_active(adev))
1496 voice_set_sidetone(adev, out_snd_device, true);
1497 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001498
Eric Laurentf4520b02017-09-20 18:31:58 -07001499 if (usecase == voip_usecase) {
1500 struct stream_out *voip_out = voip_usecase->stream.out;
1501 audio_extn_utils_send_app_type_gain(adev,
1502 voip_out->app_type_cfg.app_type,
1503 &voip_out->app_type_cfg.gain[0]);
1504 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001505 return status;
1506}
1507
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001508static int stop_input_stream(struct stream_in *in)
1509{
1510 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001511 struct audio_usecase *uc_info;
1512 struct audio_device *adev = in->dev;
1513
Eric Laurent994a6932013-07-17 11:51:42 -07001514 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001515 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001516
1517 if (adev->active_input) {
1518 if (adev->active_input->usecase == in->usecase) {
1519 adev->active_input = NULL;
1520 } else {
1521 ALOGW("%s adev->active_input->usecase %s, v/s in->usecase %s",
1522 __func__,
1523 use_case_table[adev->active_input->usecase],
1524 use_case_table[in->usecase]);
1525 }
1526 }
1527
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001528 uc_info = get_usecase_from_list(adev, in->usecase);
1529 if (uc_info == NULL) {
1530 ALOGE("%s: Could not find the usecase (%d) in the list",
1531 __func__, in->usecase);
1532 return -EINVAL;
1533 }
1534
vivek mehta781065c2017-04-04 12:55:01 -07001535 /* Close in-call recording streams */
1536 voice_check_and_stop_incall_rec_usecase(adev, in);
1537
Eric Laurent150dbfe2013-02-27 14:31:02 -08001538 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001539 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001540
1541 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001542 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001543
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001544 list_remove(&uc_info->list);
1545 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001546
Eric Laurent994a6932013-07-17 11:51:42 -07001547 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001548 return ret;
1549}
1550
1551int start_input_stream(struct stream_in *in)
1552{
1553 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001554 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001555 struct audio_usecase *uc_info;
1556 struct audio_device *adev = in->dev;
1557
Eric Laurent994a6932013-07-17 11:51:42 -07001558 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001559
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001560 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1561 return -EIO;
1562
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001563 if (in->card_status == CARD_STATUS_OFFLINE ||
1564 adev->card_status == CARD_STATUS_OFFLINE) {
1565 ALOGW("in->card_status or adev->card_status offline, try again");
1566 ret = -EAGAIN;
1567 goto error_config;
1568 }
1569
vivek mehta781065c2017-04-04 12:55:01 -07001570 /* Check if source matches incall recording usecase criteria */
1571 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1572 if (ret)
1573 goto error_config;
1574 else
1575 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1576
Eric Laurentb23d5282013-05-14 15:27:20 -07001577 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001578 if (in->pcm_device_id < 0) {
1579 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1580 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001581 ret = -EINVAL;
1582 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001583 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001584
1585 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001586 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1587 uc_info->id = in->usecase;
1588 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001589 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001590 uc_info->devices = in->device;
1591 uc_info->in_snd_device = SND_DEVICE_NONE;
1592 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001593
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001594 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001595
Wei Wangf4837d52017-11-21 14:51:20 -08001596 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001597 audio_extn_perf_lock_acquire();
1598
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001599 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001600
Eric Laurent0e46adf2016-12-16 12:49:24 -08001601 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001602 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001603 ALOGE("%s: pcm stream not ready", __func__);
1604 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001605 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001606 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001607 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001608 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1609 goto error_open;
1610 }
1611 } else {
1612 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1613 unsigned int pcm_open_retry_count = 0;
1614
1615 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1616 flags |= PCM_MMAP | PCM_NOIRQ;
1617 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1618 } else if (in->realtime) {
1619 flags |= PCM_MMAP | PCM_NOIRQ;
1620 }
1621
1622 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1623 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1624
1625 while (1) {
1626 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1627 flags, &in->config);
1628 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1629 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1630 if (in->pcm != NULL) {
1631 pcm_close(in->pcm);
1632 in->pcm = NULL;
1633 }
1634 if (pcm_open_retry_count-- == 0) {
1635 ret = -EIO;
1636 goto error_open;
1637 }
1638 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1639 continue;
1640 }
1641 break;
1642 }
1643
1644 ALOGV("%s: pcm_prepare", __func__);
1645 ret = pcm_prepare(in->pcm);
1646 if (ret < 0) {
1647 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001648 pcm_close(in->pcm);
1649 in->pcm = NULL;
1650 goto error_open;
1651 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001652 if (in->realtime) {
1653 ret = pcm_start(in->pcm);
1654 if (ret < 0) {
1655 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1656 pcm_close(in->pcm);
1657 in->pcm = NULL;
1658 goto error_open;
1659 }
1660 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001661 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001662 register_in_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001663 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001664 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001665 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001666
Eric Laurent0e46adf2016-12-16 12:49:24 -08001667 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001668
1669error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001670 stop_input_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001671 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001672 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001673
1674error_config:
1675 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001676 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001677 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001678}
1679
Eric Laurenta1478072015-09-21 17:21:52 -07001680void lock_input_stream(struct stream_in *in)
1681{
1682 pthread_mutex_lock(&in->pre_lock);
1683 pthread_mutex_lock(&in->lock);
1684 pthread_mutex_unlock(&in->pre_lock);
1685}
1686
1687void lock_output_stream(struct stream_out *out)
1688{
1689 pthread_mutex_lock(&out->pre_lock);
1690 pthread_mutex_lock(&out->lock);
1691 pthread_mutex_unlock(&out->pre_lock);
1692}
1693
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001694/* must be called with out->lock locked */
1695static int send_offload_cmd_l(struct stream_out* out, int command)
1696{
1697 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1698
1699 ALOGVV("%s %d", __func__, command);
1700
1701 cmd->cmd = command;
1702 list_add_tail(&out->offload_cmd_list, &cmd->node);
1703 pthread_cond_signal(&out->offload_cond);
1704 return 0;
1705}
1706
1707/* must be called iwth out->lock locked */
1708static void stop_compressed_output_l(struct stream_out *out)
1709{
1710 out->offload_state = OFFLOAD_STATE_IDLE;
1711 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001712 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001713 if (out->compr != NULL) {
1714 compress_stop(out->compr);
1715 while (out->offload_thread_blocked) {
1716 pthread_cond_wait(&out->cond, &out->lock);
1717 }
1718 }
1719}
1720
1721static void *offload_thread_loop(void *context)
1722{
1723 struct stream_out *out = (struct stream_out *) context;
1724 struct listnode *item;
1725
1726 out->offload_state = OFFLOAD_STATE_IDLE;
1727 out->playback_started = 0;
1728
1729 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1730 set_sched_policy(0, SP_FOREGROUND);
1731 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1732
1733 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001734 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001735 for (;;) {
1736 struct offload_cmd *cmd = NULL;
1737 stream_callback_event_t event;
1738 bool send_callback = false;
1739
1740 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1741 __func__, list_empty(&out->offload_cmd_list),
1742 out->offload_state);
1743 if (list_empty(&out->offload_cmd_list)) {
1744 ALOGV("%s SLEEPING", __func__);
1745 pthread_cond_wait(&out->offload_cond, &out->lock);
1746 ALOGV("%s RUNNING", __func__);
1747 continue;
1748 }
1749
1750 item = list_head(&out->offload_cmd_list);
1751 cmd = node_to_item(item, struct offload_cmd, node);
1752 list_remove(item);
1753
1754 ALOGVV("%s STATE %d CMD %d out->compr %p",
1755 __func__, out->offload_state, cmd->cmd, out->compr);
1756
1757 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1758 free(cmd);
1759 break;
1760 }
1761
1762 if (out->compr == NULL) {
1763 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001764 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001765 pthread_cond_signal(&out->cond);
1766 continue;
1767 }
1768 out->offload_thread_blocked = true;
1769 pthread_mutex_unlock(&out->lock);
1770 send_callback = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001771 switch (cmd->cmd) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001772 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1773 compress_wait(out->compr, -1);
1774 send_callback = true;
1775 event = STREAM_CBK_EVENT_WRITE_READY;
1776 break;
1777 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001778 compress_next_track(out->compr);
1779 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001780 send_callback = true;
1781 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001782 /* Resend the metadata for next iteration */
1783 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001784 break;
1785 case OFFLOAD_CMD_DRAIN:
1786 compress_drain(out->compr);
1787 send_callback = true;
1788 event = STREAM_CBK_EVENT_DRAIN_READY;
1789 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001790 case OFFLOAD_CMD_ERROR:
1791 send_callback = true;
1792 event = STREAM_CBK_EVENT_ERROR;
1793 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001794 default:
1795 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1796 break;
1797 }
Eric Laurenta1478072015-09-21 17:21:52 -07001798 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001799 out->offload_thread_blocked = false;
1800 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001801 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001802 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001803 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001804 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001805 free(cmd);
1806 }
1807
1808 pthread_cond_signal(&out->cond);
1809 while (!list_empty(&out->offload_cmd_list)) {
1810 item = list_head(&out->offload_cmd_list);
1811 list_remove(item);
1812 free(node_to_item(item, struct offload_cmd, node));
1813 }
1814 pthread_mutex_unlock(&out->lock);
1815
1816 return NULL;
1817}
1818
1819static int create_offload_callback_thread(struct stream_out *out)
1820{
1821 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1822 list_init(&out->offload_cmd_list);
1823 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1824 offload_thread_loop, out);
1825 return 0;
1826}
1827
1828static int destroy_offload_callback_thread(struct stream_out *out)
1829{
Eric Laurenta1478072015-09-21 17:21:52 -07001830 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001831 stop_compressed_output_l(out);
1832 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1833
1834 pthread_mutex_unlock(&out->lock);
1835 pthread_join(out->offload_thread, (void **) NULL);
1836 pthread_cond_destroy(&out->offload_cond);
1837
1838 return 0;
1839}
1840
Eric Laurent07eeafd2013-10-06 12:52:49 -07001841static bool allow_hdmi_channel_config(struct audio_device *adev)
1842{
1843 struct listnode *node;
1844 struct audio_usecase *usecase;
1845 bool ret = true;
1846
1847 list_for_each(node, &adev->usecase_list) {
1848 usecase = node_to_item(node, struct audio_usecase, list);
1849 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1850 /*
1851 * If voice call is already existing, do not proceed further to avoid
1852 * disabling/enabling both RX and TX devices, CSD calls, etc.
1853 * Once the voice call done, the HDMI channels can be configured to
1854 * max channels of remaining use cases.
1855 */
1856 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001857 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001858 __func__);
1859 ret = false;
1860 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001861 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1862 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001863 "no change in HDMI channels", __func__);
1864 ret = false;
1865 break;
1866 }
1867 }
1868 }
1869 return ret;
1870}
1871
1872static int check_and_set_hdmi_channels(struct audio_device *adev,
1873 unsigned int channels)
1874{
1875 struct listnode *node;
1876 struct audio_usecase *usecase;
1877
1878 /* Check if change in HDMI channel config is allowed */
1879 if (!allow_hdmi_channel_config(adev))
1880 return 0;
1881
1882 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001883 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001884 return 0;
1885 }
1886
1887 platform_set_hdmi_channels(adev->platform, channels);
1888 adev->cur_hdmi_channels = channels;
1889
1890 /*
1891 * Deroute all the playback streams routed to HDMI so that
1892 * the back end is deactivated. Note that backend will not
1893 * be deactivated if any one stream is connected to it.
1894 */
1895 list_for_each(node, &adev->usecase_list) {
1896 usecase = node_to_item(node, struct audio_usecase, list);
1897 if (usecase->type == PCM_PLAYBACK &&
1898 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001899 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001900 }
1901 }
1902
1903 /*
1904 * Enable all the streams disabled above. Now the HDMI backend
1905 * will be activated with new channel configuration
1906 */
1907 list_for_each(node, &adev->usecase_list) {
1908 usecase = node_to_item(node, struct audio_usecase, list);
1909 if (usecase->type == PCM_PLAYBACK &&
1910 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001911 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001912 }
1913 }
1914
1915 return 0;
1916}
1917
Haynes Mathew George65f6b432018-02-27 17:44:55 -08001918static int check_and_set_usb_service_interval(struct audio_device *adev,
1919 struct audio_usecase *uc_info,
1920 bool min)
1921{
1922 struct listnode *node;
1923 struct audio_usecase *usecase;
1924 bool switch_usecases = false;
1925 bool reconfig = false;
1926
1927 if ((uc_info->id != USECASE_AUDIO_PLAYBACK_MMAP) &&
1928 (uc_info->id != USECASE_AUDIO_PLAYBACK_ULL))
1929 return -1;
1930
1931 /* set if the valid usecase do not already exist */
1932 list_for_each(node, &adev->usecase_list) {
1933 usecase = node_to_item(node, struct audio_usecase, list);
1934 if (usecase->type == PCM_PLAYBACK &&
1935 (audio_is_usb_out_device(usecase->devices & AUDIO_DEVICE_OUT_ALL_USB))) {
1936 switch (usecase->id) {
1937 case USECASE_AUDIO_PLAYBACK_MMAP:
1938 case USECASE_AUDIO_PLAYBACK_ULL:
1939 // cannot reconfig while mmap/ull is present.
1940 return -1;
1941 default:
1942 switch_usecases = true;
1943 break;
1944 }
1945 }
1946 if (switch_usecases)
1947 break;
1948 }
1949 /*
1950 * client can try to set service interval in start_output_stream
1951 * to min or to 0 (i.e reset) in stop_output_stream .
1952 */
1953 unsigned long service_interval =
1954 audio_extn_usb_find_service_interval(min, true /*playback*/);
1955 int ret = platform_set_usb_service_interval(adev->platform,
1956 true /*playback*/,
1957 service_interval,
1958 &reconfig);
1959 /* no change or not supported or no active usecases */
1960 if (ret || !reconfig || !switch_usecases)
1961 return -1;
1962 return 0;
1963#undef VALID_USECASE
1964}
1965
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001966static int stop_output_stream(struct stream_out *out)
1967{
1968 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001969 struct audio_usecase *uc_info;
1970 struct audio_device *adev = out->dev;
HW Lee88512e92018-06-12 15:26:09 +08001971 bool has_voip_usecase =
1972 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001973
Eric Laurent994a6932013-07-17 11:51:42 -07001974 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001975 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001976 uc_info = get_usecase_from_list(adev, out->usecase);
1977 if (uc_info == NULL) {
1978 ALOGE("%s: Could not find the usecase (%d) in the list",
1979 __func__, out->usecase);
1980 return -EINVAL;
1981 }
1982
Haynes Mathew George41f86652014-06-17 14:22:15 -07001983 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1984 if (adev->visualizer_stop_output != NULL)
1985 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1986 if (adev->offload_effects_stop_output != NULL)
1987 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08001988 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
1989 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
1990 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07001991 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001992
Eric Laurent150dbfe2013-02-27 14:31:02 -08001993 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001994 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001995
1996 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001997 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001998
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001999 list_remove(&uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002000
Eric Laurent0499d4f2014-08-25 22:39:29 -05002001 audio_extn_extspk_update(adev->extspk);
2002
Eric Laurent07eeafd2013-10-06 12:52:49 -07002003 /* Must be called after removing the usecase from list */
2004 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2005 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
HW Lee88512e92018-06-12 15:26:09 +08002006 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002007 ret = check_and_set_usb_service_interval(adev, uc_info, false /*min*/);
2008 if (ret == 0) {
2009 /* default service interval was successfully updated,
2010 reopen USB backend with new service interval */
2011 check_and_route_playback_usecases(adev, uc_info, uc_info->out_snd_device);
2012 }
2013 ret = 0;
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07002014 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002015
HW Lee88512e92018-06-12 15:26:09 +08002016 if (has_voip_usecase ||
2017 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
2018 struct listnode *node;
2019 struct audio_usecase *usecase;
2020 list_for_each(node, &adev->usecase_list) {
2021 usecase = node_to_item(node, struct audio_usecase, list);
2022 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
2023 continue;
2024
2025 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
2026 __func__, usecase->id, use_case_table[usecase->id],
2027 out->usecase, use_case_table[out->usecase]);
2028 select_devices(adev, usecase->id);
2029 }
2030 }
2031
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002032 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07002033 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002034 return ret;
2035}
2036
2037int start_output_stream(struct stream_out *out)
2038{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002039 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002040 struct audio_usecase *uc_info;
2041 struct audio_device *adev = out->dev;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002042 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002043
Eric Laurent994a6932013-07-17 11:51:42 -07002044 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002045 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002046
2047 if (out->card_status == CARD_STATUS_OFFLINE ||
2048 adev->card_status == CARD_STATUS_OFFLINE) {
2049 ALOGW("out->card_status or adev->card_status offline, try again");
2050 ret = -EAGAIN;
2051 goto error_config;
2052 }
2053
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002054 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2055 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002056 if (out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002057 a2dp_combo = true;
2058 } else {
2059 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2060 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2061 ret = -EAGAIN;
2062 goto error_config;
2063 }
2064 }
2065 }
2066 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002067 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002068 if (out->pcm_device_id < 0) {
2069 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2070 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002071 ret = -EINVAL;
2072 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002073 }
2074
2075 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
2076 uc_info->id = out->usecase;
2077 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002078 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002079 uc_info->devices = out->devices;
2080 uc_info->in_snd_device = SND_DEVICE_NONE;
2081 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002082
Eric Laurent07eeafd2013-10-06 12:52:49 -07002083 /* This must be called before adding this usecase to the list */
2084 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2085 check_and_set_hdmi_channels(adev, out->config.channels);
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002086 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
2087 check_and_set_usb_service_interval(adev, uc_info, true /*min*/);
2088 /* USB backend is not reopened immediately.
2089 This is eventually done as part of select_devices */
2090 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002091
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002092 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002093
Wei Wangf4837d52017-11-21 14:51:20 -08002094 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002095 audio_extn_perf_lock_acquire();
2096
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002097 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2098 (!audio_extn_a2dp_is_ready())) {
2099 if (!a2dp_combo) {
2100 check_a2dp_restore_l(adev, out, false);
2101 } else {
2102 audio_devices_t dev = out->devices;
juyuchen9baad392018-06-05 19:02:10 +08002103 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2104 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2105 else
2106 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002107 select_devices(adev, out->usecase);
2108 out->devices = dev;
2109 }
2110 } else {
2111 select_devices(adev, out->usecase);
2112 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002113
Eric Laurent0499d4f2014-08-25 22:39:29 -05002114 audio_extn_extspk_update(adev->extspk);
2115
Andy Hung31aca912014-03-20 17:14:59 -07002116 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002117 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002118 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2119 out->pcm = NULL;
2120 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
2121 COMPRESS_IN, &out->compr_config);
2122 if (out->compr && !is_compress_ready(out->compr)) {
2123 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2124 compress_close(out->compr);
2125 out->compr = NULL;
2126 ret = -EIO;
2127 goto error_open;
2128 }
2129 if (out->offload_callback)
2130 compress_nonblock(out->compr, out->non_blocking);
2131
Aniket Kumar Lata72a3cea2018-04-06 13:56:37 -07002132 if (adev->visualizer_start_output != NULL) {
2133 int capture_device_id =
2134 platform_get_pcm_device_id(USECASE_AUDIO_RECORD_AFE_PROXY,
2135 PCM_CAPTURE);
2136 adev->visualizer_start_output(out->handle, out->pcm_device_id,
2137 adev->snd_card, capture_device_id);
2138 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002139 if (adev->offload_effects_start_output != NULL)
2140 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
2141 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002142 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002143 ALOGE("%s: pcm stream not ready", __func__);
2144 goto error_open;
2145 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002146 ret = pcm_start(out->pcm);
2147 if (ret < 0) {
2148 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2149 goto error_open;
2150 }
2151 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07002152 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002153 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002154
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002155 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2156 flags |= PCM_MMAP | PCM_NOIRQ;
2157 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002158 } else if (out->realtime) {
2159 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07002160 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002161
2162 while (1) {
2163 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2164 flags, &out->config);
2165 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2166 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2167 if (out->pcm != NULL) {
2168 pcm_close(out->pcm);
2169 out->pcm = NULL;
2170 }
2171 if (pcm_open_retry_count-- == 0) {
2172 ret = -EIO;
2173 goto error_open;
2174 }
2175 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2176 continue;
2177 }
2178 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002179 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002180 ALOGV("%s: pcm_prepare", __func__);
2181 if (pcm_is_ready(out->pcm)) {
2182 ret = pcm_prepare(out->pcm);
2183 if (ret < 0) {
2184 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2185 pcm_close(out->pcm);
2186 out->pcm = NULL;
2187 goto error_open;
2188 }
2189 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002190 if (out->realtime) {
2191 ret = pcm_start(out->pcm);
2192 if (ret < 0) {
2193 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
2194 pcm_close(out->pcm);
2195 out->pcm = NULL;
2196 goto error_open;
2197 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002198 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002199 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002200 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08002201 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002202 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002203 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07002204
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002205 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2206 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2207 audio_low_latency_hint_start();
2208 }
2209
vivek mehtae59cfb22017-06-16 15:57:11 -07002210 // consider a scenario where on pause lower layers are tear down.
2211 // so on resume, swap mixer control need to be sent only when
2212 // backend is active, hence rather than sending from enable device
2213 // sending it from start of streamtream
2214
2215 platform_set_swap_channels(adev, true);
2216
Eric Laurent994a6932013-07-17 11:51:42 -07002217 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002218 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002219error_open:
Wei Wangf4837d52017-11-21 14:51:20 -08002220 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002221 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002222 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002223error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002224 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002225}
2226
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002227static int check_input_parameters(uint32_t sample_rate,
2228 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07002229 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002230{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002231 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2232 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002233 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2234 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002235 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2236 return -EINVAL;
2237 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002238
Eric Laurent74b55762017-07-09 17:04:53 -07002239 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2240 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002241 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002242 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002243 return -EINVAL;
2244 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002245
2246 switch (sample_rate) {
2247 case 8000:
2248 case 11025:
2249 case 12000:
2250 case 16000:
2251 case 22050:
2252 case 24000:
2253 case 32000:
2254 case 44100:
2255 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002256 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002257 break;
2258 default:
vivek mehtadae44712015-07-27 14:13:18 -07002259 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002260 return -EINVAL;
2261 }
2262
2263 return 0;
2264}
2265
Kevin Rocarda325aa22018-04-03 09:15:52 -07002266/** Add a value in a list if not already present.
2267 * @return true if value was successfully inserted or already present,
2268 * false if the list is full and does not contain the value.
2269 */
2270static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
2271 for (size_t i = 0; i < list_length; i++) {
2272 if (list[i] == value) return true; // value is already present
2273 if (list[i] == 0) { // no values in this slot
2274 list[i] = value;
2275 return true; // value inserted
2276 }
2277 }
2278 return false; // could not insert value
2279}
2280
2281/** Add channel_mask in supported_channel_masks if not already present.
2282 * @return true if channel_mask was successfully inserted or already present,
2283 * false if supported_channel_masks is full and does not contain channel_mask.
2284 */
2285static void register_channel_mask(audio_channel_mask_t channel_mask,
2286 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
2287 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
2288 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
2289}
2290
2291/** Add format in supported_formats if not already present.
2292 * @return true if format was successfully inserted or already present,
2293 * false if supported_formats is full and does not contain format.
2294 */
2295static void register_format(audio_format_t format,
2296 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
2297 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
2298 "%s: stream can not declare supporting its format %x", __func__, format);
2299}
2300/** Add sample_rate in supported_sample_rates if not already present.
2301 * @return true if sample_rate was successfully inserted or already present,
2302 * false if supported_sample_rates is full and does not contain sample_rate.
2303 */
2304static void register_sample_rate(uint32_t sample_rate,
2305 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
2306 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
2307 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
2308}
2309
vivek mehtaa68fea62017-06-08 19:04:02 -07002310static size_t get_stream_buffer_size(size_t duration_ms,
2311 uint32_t sample_rate,
2312 audio_format_t format,
2313 int channel_count,
2314 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002315{
2316 size_t size = 0;
2317
vivek mehtaa68fea62017-06-08 19:04:02 -07002318 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002319 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002320 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002321
2322 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002323
Glenn Kasten4f993392014-05-14 07:30:48 -07002324 /* make sure the size is multiple of 32 bytes
2325 * At 48 kHz mono 16-bit PCM:
2326 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2327 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2328 */
2329 size += 0x1f;
2330 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002331
2332 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002333}
2334
2335static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2336{
2337 struct stream_out *out = (struct stream_out *)stream;
2338
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002339 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002340}
2341
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002342static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002343{
2344 return -ENOSYS;
2345}
2346
2347static size_t out_get_buffer_size(const struct audio_stream *stream)
2348{
2349 struct stream_out *out = (struct stream_out *)stream;
2350
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002351 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2352 return out->compr_config.fragment_size;
2353 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002354 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002355 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002356}
2357
2358static uint32_t out_get_channels(const struct audio_stream *stream)
2359{
2360 struct stream_out *out = (struct stream_out *)stream;
2361
2362 return out->channel_mask;
2363}
2364
2365static audio_format_t out_get_format(const struct audio_stream *stream)
2366{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002367 struct stream_out *out = (struct stream_out *)stream;
2368
2369 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002370}
2371
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002372static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002373{
2374 return -ENOSYS;
2375}
2376
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002377/* must be called with out->lock locked */
2378static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002379{
2380 struct stream_out *out = (struct stream_out *)stream;
2381 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002382 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002383
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002384 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002385 if (adev->adm_deregister_stream)
2386 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002387 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002388 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002389 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2390 if (out->pcm) {
2391 pcm_close(out->pcm);
2392 out->pcm = NULL;
2393 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002394 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002395 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002396 out->playback_started = false;
2397 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002398 } else {
2399 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002400 out->gapless_mdata.encoder_delay = 0;
2401 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002402 if (out->compr != NULL) {
2403 compress_close(out->compr);
2404 out->compr = NULL;
2405 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002406 }
Phil Burkbc991042017-02-24 08:06:44 -08002407 if (do_stop) {
2408 stop_output_stream(out);
2409 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002410 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002411 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002412 return 0;
2413}
2414
2415static int out_standby(struct audio_stream *stream)
2416{
2417 struct stream_out *out = (struct stream_out *)stream;
2418
2419 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2420 out->usecase, use_case_table[out->usecase]);
2421
2422 lock_output_stream(out);
2423 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002424 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002425 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002426 return 0;
2427}
2428
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002429static int out_on_error(struct audio_stream *stream)
2430{
2431 struct stream_out *out = (struct stream_out *)stream;
2432 struct audio_device *adev = out->dev;
2433 bool do_standby = false;
2434
2435 lock_output_stream(out);
2436 if (!out->standby) {
2437 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2438 stop_compressed_output_l(out);
2439 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2440 } else
2441 do_standby = true;
2442 }
2443 pthread_mutex_unlock(&out->lock);
2444
2445 if (do_standby)
2446 return out_standby(&out->stream.common);
2447
2448 return 0;
2449}
2450
Andy Hung7401c7c2016-09-21 12:41:21 -07002451static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002452{
Andy Hung7401c7c2016-09-21 12:41:21 -07002453 struct stream_out *out = (struct stream_out *)stream;
2454
2455 // We try to get the lock for consistency,
2456 // but it isn't necessary for these variables.
2457 // If we're not in standby, we may be blocked on a write.
2458 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2459 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2460 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2461
2462 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002463 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002464 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002465
2466 // dump error info
2467 (void)error_log_dump(
2468 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002469
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002470 return 0;
2471}
2472
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002473static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2474{
2475 int ret = 0;
2476 char value[32];
2477 struct compr_gapless_mdata tmp_mdata;
2478
2479 if (!out || !parms) {
2480 return -EINVAL;
2481 }
2482
2483 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2484 if (ret >= 0) {
2485 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2486 } else {
2487 return -EINVAL;
2488 }
2489
2490 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2491 if (ret >= 0) {
2492 tmp_mdata.encoder_padding = atoi(value);
2493 } else {
2494 return -EINVAL;
2495 }
2496
2497 out->gapless_mdata = tmp_mdata;
2498 out->send_new_metadata = 1;
2499 ALOGV("%s new encoder delay %u and padding %u", __func__,
2500 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2501
2502 return 0;
2503}
2504
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002505static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2506{
2507 return out == adev->primary_output || out == adev->voice_tx_output;
2508}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002509
Kevin Rocard1e02c882017-08-09 15:26:07 -07002510static int get_alive_usb_card(struct str_parms* parms) {
2511 int card;
2512 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2513 !audio_extn_usb_alive(card)) {
2514 return card;
2515 }
2516 return -ENODEV;
2517}
2518
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002519static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2520{
2521 struct stream_out *out = (struct stream_out *)stream;
2522 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002523 struct audio_usecase *usecase;
2524 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002525 struct str_parms *parms;
2526 char value[32];
2527 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002528 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002529 int status = 0;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002530 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002531
Eric Laurent2e140aa2016-06-30 17:14:46 -07002532 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002533 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002534 parms = str_parms_create_str(kvpairs);
2535 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2536 if (ret >= 0) {
2537 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002538
Eric Laurenta1478072015-09-21 17:21:52 -07002539 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002540
2541 // The usb driver needs to be closed after usb device disconnection
2542 // otherwise audio is no longer played on the new usb devices.
2543 // By forcing the stream in standby, the usb stack refcount drops to 0
2544 // and the driver is closed.
2545 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD && val == AUDIO_DEVICE_NONE &&
2546 audio_is_usb_out_device(out->devices)) {
2547 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2548 out_standby_l(&out->stream.common);
2549 }
2550
Eric Laurent150dbfe2013-02-27 14:31:02 -08002551 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002552
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002553 /*
2554 * When HDMI cable is unplugged the music playback is paused and
2555 * the policy manager sends routing=0. But the audioflinger
2556 * continues to write data until standby time (3sec).
2557 * As the HDMI core is turned off, the write gets blocked.
2558 * Avoid this by routing audio to speaker until standby.
2559 */
2560 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2561 val == AUDIO_DEVICE_NONE) {
2562 val = AUDIO_DEVICE_OUT_SPEAKER;
2563 }
2564
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002565 /*
2566 * When A2DP is disconnected the
2567 * music playback is paused and the policy manager sends routing=0
2568 * But the audioflingercontinues to write data until standby time
2569 * (3sec). As BT is turned off, the write gets blocked.
2570 * Avoid this by routing audio to speaker until standby.
2571 */
2572 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2573 (val == AUDIO_DEVICE_NONE) &&
2574 !audio_extn_a2dp_is_ready()) {
2575 val = AUDIO_DEVICE_OUT_SPEAKER;
2576 }
2577
2578 /* To avoid a2dp to sco overlapping / BT device improper state
2579 * check with BT lib about a2dp streaming support before routing
2580 */
2581 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2582 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002583 if (val & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002584 //combo usecase just by pass a2dp
2585 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2586 bypass_a2dp = true;
2587 } else {
2588 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2589 /* update device to a2dp and don't route as BT returned error
2590 * However it is still possible a2dp routing called because
2591 * of current active device disconnection (like wired headset)
2592 */
2593 out->devices = val;
2594 pthread_mutex_unlock(&out->lock);
2595 pthread_mutex_unlock(&adev->lock);
2596 status = -ENOSYS;
2597 goto routing_fail;
2598 }
2599 }
2600 }
2601
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002602 audio_devices_t new_dev = val;
2603
2604 // Workaround: If routing to an non existing usb device, fail gracefully
2605 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002606 int card;
2607 if (audio_is_usb_out_device(new_dev) &&
2608 (card = get_alive_usb_card(parms)) >= 0) {
2609
2610 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002611 pthread_mutex_unlock(&adev->lock);
2612 pthread_mutex_unlock(&out->lock);
2613 status = -ENOSYS;
2614 goto routing_fail;
2615 }
2616
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002617 /*
2618 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002619 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002620 * the select_devices(). But how do we undo this?
2621 *
2622 * For example, music playback is active on headset (deep-buffer usecase)
2623 * and if we go to ringtones and select a ringtone, low-latency usecase
2624 * will be started on headset+speaker. As we can't enable headset+speaker
2625 * and headset devices at the same time, select_devices() switches the music
2626 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2627 * So when the ringtone playback is completed, how do we undo the same?
2628 *
2629 * We are relying on the out_set_parameters() call on deep-buffer output,
2630 * once the ringtone playback is ended.
2631 * NOTE: We should not check if the current devices are same as new devices.
2632 * Because select_devices() must be called to switch back the music
2633 * playback to headset.
2634 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002635 if (new_dev != AUDIO_DEVICE_NONE) {
2636 bool same_dev = out->devices == new_dev;
2637 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002638
Eric Laurenta7657192014-10-09 21:09:33 -07002639 if (output_drives_call(adev, out)) {
Vignesh Kulothungana5c9da12017-11-10 11:41:24 -08002640 if (!voice_is_call_state_active(adev)) {
Eric Laurenta7657192014-10-09 21:09:33 -07002641 if (adev->mode == AUDIO_MODE_IN_CALL) {
2642 adev->current_call_output = out;
2643 ret = voice_start_call(adev);
2644 }
2645 } else {
2646 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002647 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002648 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002649 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002650
2651 if (!out->standby) {
2652 if (!same_dev) {
2653 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002654 // inform adm before actual routing to prevent glitches.
2655 if (adev->adm_on_routing_change) {
2656 adev->adm_on_routing_change(adev->adm_data,
2657 out->handle);
2658 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002659 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002660 if (!bypass_a2dp) {
2661 select_devices(adev, out->usecase);
2662 } else {
juyuchen9baad392018-06-05 19:02:10 +08002663 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2664 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2665 else
2666 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002667 select_devices(adev, out->usecase);
2668 out->devices = new_dev;
2669 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002670 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002671
2672 // on device switch force swap, lower functions will make sure
2673 // to check if swap is allowed or not.
2674
2675 if (!same_dev)
2676 platform_set_swap_channels(adev, true);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002677
2678 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2679 out->a2dp_compress_mute &&
2680 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
2681 pthread_mutex_lock(&out->compr_mute_lock);
2682 out->a2dp_compress_mute = false;
2683 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
2684 pthread_mutex_unlock(&out->compr_mute_lock);
2685 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002686 }
2687
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002688 }
2689
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002690 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002691 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002692
2693 /*handles device and call state changes*/
2694 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002695 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002696 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002697
2698 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2699 parse_compress_metadata(out, parms);
2700 }
2701
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002702 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002703 ALOGV("%s: exit: code(%d)", __func__, status);
2704 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002705}
2706
Haynes Mathew George569b7482017-05-08 14:44:27 -07002707static bool stream_get_parameter_channels(struct str_parms *query,
2708 struct str_parms *reply,
2709 audio_channel_mask_t *supported_channel_masks) {
2710 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002711 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002712 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002713 size_t i, j;
2714
2715 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2716 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002717 value[0] = '\0';
2718 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002719 while (supported_channel_masks[i] != 0) {
2720 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2721 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002722 if (!first) {
2723 strcat(value, "|");
2724 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002725 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002726 first = false;
2727 break;
2728 }
2729 }
2730 i++;
2731 }
2732 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002733 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002734 return ret >= 0;
2735}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002736
Haynes Mathew George569b7482017-05-08 14:44:27 -07002737static bool stream_get_parameter_formats(struct str_parms *query,
2738 struct str_parms *reply,
2739 audio_format_t *supported_formats) {
2740 int ret = -1;
2741 char value[256];
2742 int i;
2743
2744 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2745 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002746 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002747 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002748 case AUDIO_FORMAT_PCM_16_BIT:
2749 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2750 break;
2751 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2752 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2753 break;
2754 case AUDIO_FORMAT_PCM_32_BIT:
2755 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2756 break;
2757 default:
2758 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002759 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002760 break;
2761 }
2762 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002763 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002764 return ret >= 0;
2765}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002766
Haynes Mathew George569b7482017-05-08 14:44:27 -07002767static bool stream_get_parameter_rates(struct str_parms *query,
2768 struct str_parms *reply,
2769 uint32_t *supported_sample_rates) {
2770
2771 int i;
2772 char value[256];
2773 int ret = -1;
2774 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2775 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002776 value[0] = '\0';
2777 i=0;
2778 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002779 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002780 int avail = sizeof(value) - cursor;
2781 ret = snprintf(value + cursor, avail, "%s%d",
2782 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002783 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002784 if (ret < 0 || ret >= avail) {
2785 // if cursor is at the last element of the array
2786 // overwrite with \0 is duplicate work as
2787 // snprintf already put a \0 in place.
2788 // else
2789 // we had space to write the '|' at value[cursor]
2790 // (which will be overwritten) or no space to fill
2791 // the first element (=> cursor == 0)
2792 value[cursor] = '\0';
2793 break;
2794 }
2795 cursor += ret;
2796 ++i;
2797 }
2798 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2799 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002800 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002801 return ret >= 0;
2802}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002803
Haynes Mathew George569b7482017-05-08 14:44:27 -07002804static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2805{
2806 struct stream_out *out = (struct stream_out *)stream;
2807 struct str_parms *query = str_parms_create_str(keys);
2808 char *str;
2809 struct str_parms *reply = str_parms_create();
2810 bool replied = false;
2811 ALOGV("%s: enter: keys - %s", __func__, keys);
2812
2813 replied |= stream_get_parameter_channels(query, reply,
2814 &out->supported_channel_masks[0]);
2815 replied |= stream_get_parameter_formats(query, reply,
2816 &out->supported_formats[0]);
2817 replied |= stream_get_parameter_rates(query, reply,
2818 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002819 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002820 str = str_parms_to_str(reply);
2821 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002822 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002823 }
2824 str_parms_destroy(query);
2825 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002826 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002827 return str;
2828}
2829
2830static uint32_t out_get_latency(const struct audio_stream_out *stream)
2831{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002832 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002833 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002834 uint32_t latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002835
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002836 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2837 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002838 else if ((out->realtime) ||
2839 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002840 // since the buffer won't be filled up faster than realtime,
2841 // return a smaller number
2842 period_ms = (out->af_period_multiplier * out->config.period_size *
2843 1000) / (out->config.rate);
2844 hw_delay = platform_render_latency(out->usecase)/1000;
2845 return period_ms + hw_delay;
2846 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002847
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002848 latency = (out->config.period_count * out->config.period_size * 1000) /
2849 (out->config.rate);
2850
2851 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
2852 latency += audio_extn_a2dp_get_encoder_latency();
2853
2854 return latency;
2855}
2856
2857static int set_compr_volume(struct audio_stream_out *stream, float left,
2858 float right)
2859{
2860 struct stream_out *out = (struct stream_out *)stream;
2861 int volume[2];
2862 char mixer_ctl_name[128];
2863 struct audio_device *adev = out->dev;
2864 struct mixer_ctl *ctl;
2865 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2866 PCM_PLAYBACK);
2867
2868 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2869 "Compress Playback %d Volume", pcm_device_id);
2870 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2871 if (!ctl) {
2872 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2873 __func__, mixer_ctl_name);
2874 return -EINVAL;
2875 }
2876 ALOGV("%s: ctl for mixer cmd - %s, left %f, right %f",
2877 __func__, mixer_ctl_name, left, right);
2878 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2879 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2880 mixer_ctl_set_array(ctl, volume, sizeof(volume) / sizeof(volume[0]));
2881
2882 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002883}
2884
2885static int out_set_volume(struct audio_stream_out *stream, float left,
2886 float right)
2887{
Eric Laurenta9024de2013-04-04 09:19:12 -07002888 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002889 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002890
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002891 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002892 /* only take left channel into account: the API is for stereo anyway */
2893 out->muted = (left == 0.0f);
2894 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002895 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002896 pthread_mutex_lock(&out->compr_mute_lock);
2897 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
2898 if (!out->a2dp_compress_mute)
2899 ret = set_compr_volume(stream, left, right);
2900 out->volume_l = left;
2901 out->volume_r = right;
2902 pthread_mutex_unlock(&out->compr_mute_lock);
2903 return ret;
vivek mehtaa68fea62017-06-08 19:04:02 -07002904 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002905 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2906 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2907 if (!out->standby) {
2908 // if in standby, cached volume will be sent after stream is opened
2909 audio_extn_utils_send_app_type_gain(out->dev,
2910 out->app_type_cfg.app_type,
2911 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002912 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002913 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002914 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002915
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002916 return -ENOSYS;
2917}
2918
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002919// note: this call is safe only if the stream_cb is
2920// removed first in close_output_stream (as is done now).
2921static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2922{
2923 if (!stream || !parms)
2924 return;
2925
2926 struct stream_out *out = (struct stream_out *)stream;
2927 struct audio_device *adev = out->dev;
2928
2929 card_status_t status;
2930 int card;
2931 if (parse_snd_card_status(parms, &card, &status) < 0)
2932 return;
2933
2934 pthread_mutex_lock(&adev->lock);
2935 bool valid_cb = (card == adev->snd_card);
2936 pthread_mutex_unlock(&adev->lock);
2937
2938 if (!valid_cb)
2939 return;
2940
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002941 lock_output_stream(out);
2942 if (out->card_status != status)
2943 out->card_status = status;
2944 pthread_mutex_unlock(&out->lock);
2945
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002946 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2947 use_case_table[out->usecase],
2948 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2949
2950 if (status == CARD_STATUS_OFFLINE)
2951 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002952
2953 return;
2954}
2955
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002956#ifdef NO_AUDIO_OUT
2957static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002958 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002959{
2960 struct stream_out *out = (struct stream_out *)stream;
2961
2962 /* No Output device supported other than BT for playback.
2963 * Sleep for the amount of buffer duration
2964 */
Eric Laurenta1478072015-09-21 17:21:52 -07002965 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002966 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2967 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002968 out_get_sample_rate(&out->stream.common));
2969 pthread_mutex_unlock(&out->lock);
2970 return bytes;
2971}
2972#endif
2973
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002974static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2975 size_t bytes)
2976{
2977 struct stream_out *out = (struct stream_out *)stream;
2978 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002979 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002980 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002981
Eric Laurenta1478072015-09-21 17:21:52 -07002982 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002983 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07002984 const size_t frame_size = audio_stream_out_frame_size(stream);
2985 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002986
Eric Laurent0e46adf2016-12-16 12:49:24 -08002987 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2988 error_code = ERROR_CODE_WRITE;
2989 goto exit;
2990 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002991
2992 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2993 (audio_extn_a2dp_is_suspended())) {
juyuchen9baad392018-06-05 19:02:10 +08002994 if (!(out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002995 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2996 ret = -EIO;
2997 goto exit;
2998 }
2999 }
3000 }
3001
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003002 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003003 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003004 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003005 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07003006
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003007 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003008 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003009 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07003010 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003011 goto exit;
3012 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07003013
vivek mehta40125092017-08-21 18:48:51 -07003014 // after standby always force set last known cal step
3015 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
3016 ALOGD("%s: retry previous failed cal level set", __func__);
3017 send_gain_dep_calibration_l();
3018 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003019 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003020
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003021 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003022 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003023 if (out->send_new_metadata) {
3024 ALOGVV("send new gapless metadata");
3025 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3026 out->send_new_metadata = 0;
3027 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003028 unsigned int avail;
3029 struct timespec tstamp;
3030 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
3031 /* Do not limit write size if the available frames count is unknown */
3032 if (ret != 0) {
3033 avail = bytes;
3034 }
3035 if (avail == 0) {
3036 ret = 0;
3037 } else {
3038 if (avail > bytes) {
3039 avail = bytes;
3040 }
3041 ret = compress_write(out->compr, buffer, avail);
3042 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
3043 __func__, avail, ret);
3044 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003045
Eric Laurent6e895242013-09-05 16:10:57 -07003046 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003047 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
3048 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003049 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003050 compress_start(out->compr);
3051 out->playback_started = 1;
3052 out->offload_state = OFFLOAD_STATE_PLAYING;
3053 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003054 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07003055 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07003056 } else {
3057 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07003058 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003059 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07003060 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003061 return ret;
3062 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07003063 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003064 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003065 size_t bytes_to_write = bytes;
3066
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003067 if (out->muted)
3068 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07003069 // FIXME: this can be removed once audio flinger mixer supports mono output
Nadav Bar3d72cfc2018-01-07 12:19:24 +02003070 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP || out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003071 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3072 int16_t *src = (int16_t *)buffer;
3073 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003074
Eric Laurentad2dde92017-09-20 18:27:31 -07003075 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
3076 out->format != AUDIO_FORMAT_PCM_16_BIT,
3077 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003078
Eric Laurentad2dde92017-09-20 18:27:31 -07003079 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
3080 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
3081 }
3082 bytes_to_write /= 2;
3083 }
3084 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes_to_write);
3085
Glenn Kasten5a59dff2018-02-22 08:05:35 -08003086 long ns = (frames * (int64_t) NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003087 request_out_focus(out, ns);
3088
3089 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3090 if (use_mmap)
Eric Laurentad2dde92017-09-20 18:27:31 -07003091 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003092 else
Eric Laurentad2dde92017-09-20 18:27:31 -07003093 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003094
Haynes Mathew George03c40102016-01-29 17:57:48 -08003095 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07003096 } else {
3097 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003098 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003099 }
3100
3101exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07003102 // For PCM we always consume the buffer and return #bytes regardless of ret.
3103 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003104 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07003105 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003106 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07003107
Andy Hung7401c7c2016-09-21 12:41:21 -07003108 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07003109 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07003110 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3111 ALOGE_IF(out->pcm != NULL,
3112 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07003113 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003114 // usleep not guaranteed for values over 1 second but we don't limit here.
3115 }
3116 }
Andy Hungda9b56b2016-09-16 20:06:35 -07003117
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003118 pthread_mutex_unlock(&out->lock);
3119
3120 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07003121 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003122 if (sleeptime_us != 0)
3123 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003124 }
3125 return bytes;
3126}
3127
3128static int out_get_render_position(const struct audio_stream_out *stream,
3129 uint32_t *dsp_frames)
3130{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003131 struct stream_out *out = (struct stream_out *)stream;
3132 *dsp_frames = 0;
3133 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07003134 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003135 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003136 unsigned long frames = 0;
3137 // TODO: check return value
3138 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
3139 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003140 ALOGVV("%s rendered frames %d sample_rate %d",
3141 __func__, *dsp_frames, out->sample_rate);
3142 }
3143 pthread_mutex_unlock(&out->lock);
3144 return 0;
3145 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003146 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003147}
3148
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003149static int out_add_audio_effect(const struct audio_stream *stream __unused,
3150 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003151{
3152 return 0;
3153}
3154
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003155static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3156 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003157{
3158 return 0;
3159}
3160
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003161static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3162 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003163{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003164 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003165}
3166
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003167static int out_get_presentation_position(const struct audio_stream_out *stream,
3168 uint64_t *frames, struct timespec *timestamp)
3169{
3170 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003171 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07003172 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003173
Eric Laurenta1478072015-09-21 17:21:52 -07003174 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003175
Eric Laurent949a0892013-09-20 09:20:13 -07003176 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3177 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003178 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07003179 compress_get_tstamp(out->compr, &dsp_frames,
3180 &out->sample_rate);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003181 // Adjustment accounts for A2DP encoder latency with offload usecases
3182 // Note: Encoder latency is returned in ms.
3183 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3184 unsigned long offset =
3185 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3186 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
3187 }
Eric Laurent949a0892013-09-20 09:20:13 -07003188 ALOGVV("%s rendered frames %ld sample_rate %d",
3189 __func__, dsp_frames, out->sample_rate);
3190 *frames = dsp_frames;
3191 ret = 0;
3192 /* this is the best we can do */
3193 clock_gettime(CLOCK_MONOTONIC, timestamp);
3194 }
3195 } else {
3196 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07003197 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003198 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3199 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003200 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003201 // This adjustment accounts for buffering after app processor.
3202 // It is based on estimated DSP latency per use case, rather than exact.
3203 signed_frames -=
3204 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3205
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003206 // Adjustment accounts for A2DP encoder latency with non-offload usecases
3207 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3208 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3209 signed_frames -=
3210 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3211 }
3212
Eric Laurent949a0892013-09-20 09:20:13 -07003213 // It would be unusual for this value to be negative, but check just in case ...
3214 if (signed_frames >= 0) {
3215 *frames = signed_frames;
3216 ret = 0;
3217 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003218 }
3219 }
3220 }
3221
3222 pthread_mutex_unlock(&out->lock);
3223
3224 return ret;
3225}
3226
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003227static int out_set_callback(struct audio_stream_out *stream,
3228 stream_callback_t callback, void *cookie)
3229{
3230 struct stream_out *out = (struct stream_out *)stream;
3231
3232 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003233 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003234 out->offload_callback = callback;
3235 out->offload_cookie = cookie;
3236 pthread_mutex_unlock(&out->lock);
3237 return 0;
3238}
3239
3240static int out_pause(struct audio_stream_out* stream)
3241{
3242 struct stream_out *out = (struct stream_out *)stream;
3243 int status = -ENOSYS;
3244 ALOGV("%s", __func__);
3245 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003246 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003247 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
3248 status = compress_pause(out->compr);
3249 out->offload_state = OFFLOAD_STATE_PAUSED;
3250 }
3251 pthread_mutex_unlock(&out->lock);
3252 }
3253 return status;
3254}
3255
3256static int out_resume(struct audio_stream_out* stream)
3257{
3258 struct stream_out *out = (struct stream_out *)stream;
3259 int status = -ENOSYS;
3260 ALOGV("%s", __func__);
3261 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3262 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07003263 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003264 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
3265 status = compress_resume(out->compr);
3266 out->offload_state = OFFLOAD_STATE_PLAYING;
3267 }
3268 pthread_mutex_unlock(&out->lock);
3269 }
3270 return status;
3271}
3272
3273static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3274{
3275 struct stream_out *out = (struct stream_out *)stream;
3276 int status = -ENOSYS;
3277 ALOGV("%s", __func__);
3278 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003279 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003280 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3281 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3282 else
3283 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3284 pthread_mutex_unlock(&out->lock);
3285 }
3286 return status;
3287}
3288
3289static int out_flush(struct audio_stream_out* stream)
3290{
3291 struct stream_out *out = (struct stream_out *)stream;
3292 ALOGV("%s", __func__);
3293 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003294 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003295 stop_compressed_output_l(out);
3296 pthread_mutex_unlock(&out->lock);
3297 return 0;
3298 }
3299 return -ENOSYS;
3300}
3301
Eric Laurent0e46adf2016-12-16 12:49:24 -08003302static int out_stop(const struct audio_stream_out* stream)
3303{
3304 struct stream_out *out = (struct stream_out *)stream;
3305 struct audio_device *adev = out->dev;
3306 int ret = -ENOSYS;
3307
3308 ALOGV("%s", __func__);
3309 pthread_mutex_lock(&adev->lock);
3310 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3311 out->playback_started && out->pcm != NULL) {
3312 pcm_stop(out->pcm);
3313 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08003314 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003315 }
3316 pthread_mutex_unlock(&adev->lock);
3317 return ret;
3318}
3319
3320static int out_start(const struct audio_stream_out* stream)
3321{
3322 struct stream_out *out = (struct stream_out *)stream;
3323 struct audio_device *adev = out->dev;
3324 int ret = -ENOSYS;
3325
3326 ALOGV("%s", __func__);
3327 pthread_mutex_lock(&adev->lock);
3328 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3329 !out->playback_started && out->pcm != NULL) {
3330 ret = start_output_stream(out);
3331 if (ret == 0) {
3332 out->playback_started = true;
3333 }
3334 }
3335 pthread_mutex_unlock(&adev->lock);
3336 return ret;
3337}
3338
Phil Burkbc991042017-02-24 08:06:44 -08003339/*
3340 * Modify config->period_count based on min_size_frames
3341 */
3342static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
3343{
3344 int periodCountRequested = (min_size_frames + config->period_size - 1)
3345 / config->period_size;
3346 int periodCount = MMAP_PERIOD_COUNT_MIN;
3347
3348 ALOGV("%s original config.period_size = %d config.period_count = %d",
3349 __func__, config->period_size, config->period_count);
3350
3351 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
3352 periodCount *= 2;
3353 }
3354 config->period_count = periodCount;
3355
3356 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
3357}
3358
Eric Laurent0e46adf2016-12-16 12:49:24 -08003359static int out_create_mmap_buffer(const struct audio_stream_out *stream,
3360 int32_t min_size_frames,
3361 struct audio_mmap_buffer_info *info)
3362{
3363 struct stream_out *out = (struct stream_out *)stream;
3364 struct audio_device *adev = out->dev;
3365 int ret = 0;
3366 unsigned int offset1;
3367 unsigned int frames1;
3368 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003369 uint32_t mmap_size;
3370 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003371
3372 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003373 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003374 pthread_mutex_lock(&adev->lock);
3375
3376 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003377 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003378 ret = -EINVAL;
3379 goto exit;
3380 }
3381 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003382 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003383 ret = -ENOSYS;
3384 goto exit;
3385 }
3386 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3387 if (out->pcm_device_id < 0) {
3388 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3389 __func__, out->pcm_device_id, out->usecase);
3390 ret = -EINVAL;
3391 goto exit;
3392 }
Phil Burkbc991042017-02-24 08:06:44 -08003393
3394 adjust_mmap_period_count(&out->config, min_size_frames);
3395
Eric Laurent0e46adf2016-12-16 12:49:24 -08003396 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3397 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3398 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3399 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3400 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3401 step = "open";
3402 ret = -ENODEV;
3403 goto exit;
3404 }
3405 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3406 if (ret < 0) {
3407 step = "begin";
3408 goto exit;
3409 }
3410 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003411 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003412 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003413 ret = platform_get_mmap_data_fd(adev->platform,
3414 out->pcm_device_id, 0 /*playback*/,
3415 &info->shared_memory_fd,
3416 &mmap_size);
3417 if (ret < 0) {
3418 // Fall back to non exclusive mode
3419 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3420 } else {
3421 if (mmap_size < buffer_size) {
3422 step = "mmap";
3423 goto exit;
3424 }
3425 // FIXME: indicate exclusive mode support by returning a negative buffer size
3426 info->buffer_size_frames *= -1;
3427 }
3428 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003429
3430 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3431 if (ret < 0) {
3432 step = "commit";
3433 goto exit;
3434 }
Phil Burkbc991042017-02-24 08:06:44 -08003435
3436 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003437 ret = 0;
3438
3439 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3440 __func__, info->shared_memory_address, info->buffer_size_frames);
3441
3442exit:
3443 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003444 if (out->pcm == NULL) {
3445 ALOGE("%s: %s - %d", __func__, step, ret);
3446 } else {
3447 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003448 pcm_close(out->pcm);
3449 out->pcm = NULL;
3450 }
3451 }
3452 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003453 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003454 return ret;
3455}
3456
3457static int out_get_mmap_position(const struct audio_stream_out *stream,
3458 struct audio_mmap_position *position)
3459{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003460 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003461 struct stream_out *out = (struct stream_out *)stream;
3462 ALOGVV("%s", __func__);
3463 if (position == NULL) {
3464 return -EINVAL;
3465 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003466 lock_output_stream(out);
3467 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3468 out->pcm == NULL) {
3469 ret = -ENOSYS;
3470 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003471 }
3472
3473 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003474 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003475 if (ret < 0) {
3476 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003477 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003478 }
Andy Hungfc044e12017-03-20 09:24:22 -07003479 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003480exit:
3481 pthread_mutex_unlock(&out->lock);
3482 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003483}
3484
3485
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003486/** audio_stream_in implementation **/
3487static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3488{
3489 struct stream_in *in = (struct stream_in *)stream;
3490
3491 return in->config.rate;
3492}
3493
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003494static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003495{
3496 return -ENOSYS;
3497}
3498
3499static size_t in_get_buffer_size(const struct audio_stream *stream)
3500{
3501 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003502 return in->config.period_size * in->af_period_multiplier *
3503 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003504}
3505
3506static uint32_t in_get_channels(const struct audio_stream *stream)
3507{
3508 struct stream_in *in = (struct stream_in *)stream;
3509
3510 return in->channel_mask;
3511}
3512
vivek mehta4ed66e62016-04-15 23:33:34 -07003513static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003514{
vivek mehta4ed66e62016-04-15 23:33:34 -07003515 struct stream_in *in = (struct stream_in *)stream;
3516 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003517}
3518
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003519static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003520{
3521 return -ENOSYS;
3522}
3523
3524static int in_standby(struct audio_stream *stream)
3525{
3526 struct stream_in *in = (struct stream_in *)stream;
3527 struct audio_device *adev = in->dev;
3528 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003529 bool do_stop = true;
3530
Eric Laurent994a6932013-07-17 11:51:42 -07003531 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003532
3533 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003534
3535 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003536 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003537 audio_extn_sound_trigger_stop_lab(in);
3538 in->standby = true;
3539 }
3540
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003541 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003542 if (adev->adm_deregister_stream)
3543 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3544
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003545 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003546 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003547 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003548 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003549 in->capture_started = false;
3550 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003551 if (in->pcm) {
3552 pcm_close(in->pcm);
3553 in->pcm = NULL;
3554 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003555 adev->enable_voicerx = false;
3556 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003557 if (do_stop) {
3558 status = stop_input_stream(in);
3559 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003560 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003561 }
3562 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003563 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003564 return status;
3565}
3566
Andy Hungd13f0d32017-06-12 13:58:37 -07003567static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003568{
Andy Hungd13f0d32017-06-12 13:58:37 -07003569 struct stream_in *in = (struct stream_in *)stream;
3570
3571 // We try to get the lock for consistency,
3572 // but it isn't necessary for these variables.
3573 // If we're not in standby, we may be blocked on a read.
3574 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3575 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3576 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3577 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3578
3579 if (locked) {
3580 pthread_mutex_unlock(&in->lock);
3581 }
3582
3583 // dump error info
3584 (void)error_log_dump(
3585 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003586 return 0;
3587}
3588
3589static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3590{
3591 struct stream_in *in = (struct stream_in *)stream;
3592 struct audio_device *adev = in->dev;
3593 struct str_parms *parms;
3594 char *str;
3595 char value[32];
3596 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003597 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003598
Eric Laurent994a6932013-07-17 11:51:42 -07003599 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003600 parms = str_parms_create_str(kvpairs);
3601
3602 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3603
Eric Laurenta1478072015-09-21 17:21:52 -07003604 lock_input_stream(in);
3605
Eric Laurent150dbfe2013-02-27 14:31:02 -08003606 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003607 if (ret >= 0) {
3608 val = atoi(value);
3609 /* no audio source uses val == 0 */
3610 if ((in->source != val) && (val != 0)) {
3611 in->source = val;
3612 }
3613 }
3614
3615 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003616
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003617 if (ret >= 0) {
3618 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003619 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003620
3621 // Workaround: If routing to an non existing usb device, fail gracefully
3622 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003623 int card;
3624 if (audio_is_usb_in_device(val) &&
3625 (card = get_alive_usb_card(parms)) >= 0) {
3626
3627 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003628 status = -ENOSYS;
3629 } else {
3630
3631 in->device = val;
3632 /* If recording is in progress, change the tx device to new device */
3633 if (!in->standby) {
3634 ALOGV("update input routing change");
3635 // inform adm before actual routing to prevent glitches.
3636 if (adev->adm_on_routing_change) {
3637 adev->adm_on_routing_change(adev->adm_data,
3638 in->capture_handle);
3639 }
3640 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003641 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003642 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003643 }
3644 }
3645
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003646 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003647 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003648
3649 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003650 ALOGV("%s: exit: status(%d)", __func__, status);
3651 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003652}
3653
Haynes Mathew George569b7482017-05-08 14:44:27 -07003654static char* in_get_parameters(const struct audio_stream *stream,
3655 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003656{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003657 struct stream_in *in = (struct stream_in *)stream;
3658 struct str_parms *query = str_parms_create_str(keys);
3659 char *str;
3660 struct str_parms *reply = str_parms_create();
3661 bool replied = false;
3662
3663 ALOGV("%s: enter: keys - %s", __func__, keys);
3664 replied |= stream_get_parameter_channels(query, reply,
3665 &in->supported_channel_masks[0]);
3666 replied |= stream_get_parameter_formats(query, reply,
3667 &in->supported_formats[0]);
3668 replied |= stream_get_parameter_rates(query, reply,
3669 &in->supported_sample_rates[0]);
3670 if (replied) {
3671 str = str_parms_to_str(reply);
3672 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003673 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003674 }
3675 str_parms_destroy(query);
3676 str_parms_destroy(reply);
3677 ALOGV("%s: exit: returns - %s", __func__, str);
3678 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003679}
3680
Eric Laurent51f3c662018-04-10 18:21:34 -07003681static int in_set_gain(struct audio_stream_in *stream, float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003682{
Eric Laurent51f3c662018-04-10 18:21:34 -07003683 struct stream_in *in = (struct stream_in *)stream;
3684 char mixer_ctl_name[128];
3685 struct mixer_ctl *ctl;
3686 int ctl_value;
3687
3688 ALOGV("%s: gain %f", __func__, gain);
3689
3690 if (stream == NULL)
3691 return -EINVAL;
3692
3693 /* in_set_gain() only used to silence MMAP capture for now */
3694 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
3695 return -ENOSYS;
3696
3697 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
3698
3699 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
3700 if (!ctl) {
3701 ALOGW("%s: Could not get ctl for mixer cmd - %s",
3702 __func__, mixer_ctl_name);
3703 return -ENOSYS;
3704 }
3705
3706 if (gain < RECORD_GAIN_MIN)
3707 gain = RECORD_GAIN_MIN;
3708 else if (gain > RECORD_GAIN_MAX)
3709 gain = RECORD_GAIN_MAX;
3710 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
3711
3712 mixer_ctl_set_value(ctl, 0, ctl_value);
3713 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003714}
3715
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003716static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3717{
3718 if (!stream || !parms)
3719 return;
3720
3721 struct stream_in *in = (struct stream_in *)stream;
3722 struct audio_device *adev = in->dev;
3723
3724 card_status_t status;
3725 int card;
3726 if (parse_snd_card_status(parms, &card, &status) < 0)
3727 return;
3728
3729 pthread_mutex_lock(&adev->lock);
3730 bool valid_cb = (card == adev->snd_card);
3731 pthread_mutex_unlock(&adev->lock);
3732
3733 if (!valid_cb)
3734 return;
3735
3736 lock_input_stream(in);
3737 if (in->card_status != status)
3738 in->card_status = status;
3739 pthread_mutex_unlock(&in->lock);
3740
3741 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3742 use_case_table[in->usecase],
3743 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3744
3745 // a better solution would be to report error back to AF and let
3746 // it put the stream to standby
3747 if (status == CARD_STATUS_OFFLINE)
3748 in_standby(&in->stream.common);
3749
3750 return;
3751}
3752
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003753static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3754 size_t bytes)
3755{
3756 struct stream_in *in = (struct stream_in *)stream;
3757 struct audio_device *adev = in->dev;
3758 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003759 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003760 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003761
Eric Laurenta1478072015-09-21 17:21:52 -07003762 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003763 const size_t frame_size = audio_stream_in_frame_size(stream);
3764 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003765
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003766 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003767 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003768 /* Read from sound trigger HAL */
3769 audio_extn_sound_trigger_read(in, buffer, bytes);
3770 pthread_mutex_unlock(&in->lock);
3771 return bytes;
3772 }
3773
Eric Laurent0e46adf2016-12-16 12:49:24 -08003774 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3775 ret = -ENOSYS;
3776 goto exit;
3777 }
3778
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003779 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003780 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003781 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003782 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003783 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003784 goto exit;
3785 }
3786 in->standby = 0;
3787 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003788
Andy Hungd13f0d32017-06-12 13:58:37 -07003789 // errors that occur here are read errors.
3790 error_code = ERROR_CODE_READ;
3791
Haynes Mathew George03c40102016-01-29 17:57:48 -08003792 //what's the duration requested by the client?
3793 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3794 in->config.rate;
3795 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003796
Haynes Mathew George03c40102016-01-29 17:57:48 -08003797 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003798 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003799 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003800 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003801 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003802 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003803 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003804 if (ret < 0) {
3805 ALOGE("Failed to read w/err %s", strerror(errno));
3806 ret = -errno;
3807 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003808 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3809 if (bytes % 4 == 0) {
3810 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3811 int_buf_stream = buffer;
3812 for (size_t itt=0; itt < bytes/4 ; itt++) {
3813 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003814 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003815 } else {
3816 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3817 ret = -EINVAL;
3818 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003819 }
3820 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003821 }
3822
Haynes Mathew George03c40102016-01-29 17:57:48 -08003823 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003824
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003825 /*
3826 * Instead of writing zeroes here, we could trust the hardware
3827 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003828 * 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 -08003829 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08003830 if (ret == 0 && adev->mic_muted &&
3831 !voice_is_in_call_rec_stream(in) &&
3832 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003833 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07003834 in->frames_muted += frames;
3835 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003836
3837exit:
3838 pthread_mutex_unlock(&in->lock);
3839
3840 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07003841 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003842 in_standby(&in->stream.common);
3843 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003844 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003845 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07003846 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08003847 }
3848 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003849 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003850 }
3851 return bytes;
3852}
3853
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003854static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003855{
3856 return 0;
3857}
3858
Andy Hung6ebe5962016-01-15 17:46:57 -08003859static int in_get_capture_position(const struct audio_stream_in *stream,
3860 int64_t *frames, int64_t *time)
3861{
3862 if (stream == NULL || frames == NULL || time == NULL) {
3863 return -EINVAL;
3864 }
3865 struct stream_in *in = (struct stream_in *)stream;
3866 int ret = -ENOSYS;
3867
3868 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003869 // note: ST sessions do not close the alsa pcm driver synchronously
3870 // on standby. Therefore, we may return an error even though the
3871 // pcm stream is still opened.
3872 if (in->standby) {
3873 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
3874 "%s stream in standby but pcm not NULL for non ST session", __func__);
3875 goto exit;
3876 }
Andy Hung6ebe5962016-01-15 17:46:57 -08003877 if (in->pcm) {
3878 struct timespec timestamp;
3879 unsigned int avail;
3880 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3881 *frames = in->frames_read + avail;
3882 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3883 ret = 0;
3884 }
3885 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003886exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08003887 pthread_mutex_unlock(&in->lock);
3888 return ret;
3889}
3890
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003891static int add_remove_audio_effect(const struct audio_stream *stream,
3892 effect_handle_t effect,
3893 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003894{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003895 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003896 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003897 int status = 0;
3898 effect_descriptor_t desc;
3899
3900 status = (*effect)->get_descriptor(effect, &desc);
3901 if (status != 0)
3902 return status;
3903
Eric Laurenta1478072015-09-21 17:21:52 -07003904 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003905 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003906 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003907 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003908 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003909 in->enable_aec != enable &&
3910 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3911 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003912 if (!enable)
3913 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003914 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3915 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3916 adev->enable_voicerx = enable;
3917 struct audio_usecase *usecase;
3918 struct listnode *node;
3919 list_for_each(node, &adev->usecase_list) {
3920 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07003921 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07003922 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05003923 }
3924 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003925 if (!in->standby)
3926 select_devices(in->dev, in->usecase);
3927 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003928 if (in->enable_ns != enable &&
3929 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3930 in->enable_ns = enable;
3931 if (!in->standby)
3932 select_devices(in->dev, in->usecase);
3933 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003934 pthread_mutex_unlock(&in->dev->lock);
3935 pthread_mutex_unlock(&in->lock);
3936
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003937 return 0;
3938}
3939
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003940static int in_add_audio_effect(const struct audio_stream *stream,
3941 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003942{
Eric Laurent994a6932013-07-17 11:51:42 -07003943 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003944 return add_remove_audio_effect(stream, effect, true);
3945}
3946
3947static int in_remove_audio_effect(const struct audio_stream *stream,
3948 effect_handle_t effect)
3949{
Eric Laurent994a6932013-07-17 11:51:42 -07003950 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003951 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003952}
3953
Eric Laurent0e46adf2016-12-16 12:49:24 -08003954static int in_stop(const struct audio_stream_in* stream)
3955{
3956 struct stream_in *in = (struct stream_in *)stream;
3957 struct audio_device *adev = in->dev;
3958
3959 int ret = -ENOSYS;
3960 ALOGV("%s", __func__);
3961 pthread_mutex_lock(&adev->lock);
3962 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3963 in->capture_started && in->pcm != NULL) {
3964 pcm_stop(in->pcm);
3965 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003966 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003967 }
3968 pthread_mutex_unlock(&adev->lock);
3969 return ret;
3970}
3971
3972static int in_start(const struct audio_stream_in* stream)
3973{
3974 struct stream_in *in = (struct stream_in *)stream;
3975 struct audio_device *adev = in->dev;
3976 int ret = -ENOSYS;
3977
3978 ALOGV("%s in %p", __func__, in);
3979 pthread_mutex_lock(&adev->lock);
3980 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3981 !in->capture_started && in->pcm != NULL) {
3982 if (!in->capture_started) {
3983 ret = start_input_stream(in);
3984 if (ret == 0) {
3985 in->capture_started = true;
3986 }
3987 }
3988 }
3989 pthread_mutex_unlock(&adev->lock);
3990 return ret;
3991}
3992
3993static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3994 int32_t min_size_frames,
3995 struct audio_mmap_buffer_info *info)
3996{
3997 struct stream_in *in = (struct stream_in *)stream;
3998 struct audio_device *adev = in->dev;
3999 int ret = 0;
4000 unsigned int offset1;
4001 unsigned int frames1;
4002 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07004003 uint32_t mmap_size;
4004 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004005
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004006 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004007 pthread_mutex_lock(&adev->lock);
4008 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08004009
Eric Laurent0e46adf2016-12-16 12:49:24 -08004010 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004011 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004012 ret = -EINVAL;
4013 goto exit;
4014 }
4015 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08004016 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004017 ALOGV("%s in %p", __func__, in);
4018 ret = -ENOSYS;
4019 goto exit;
4020 }
4021 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
4022 if (in->pcm_device_id < 0) {
4023 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4024 __func__, in->pcm_device_id, in->usecase);
4025 ret = -EINVAL;
4026 goto exit;
4027 }
Phil Burkbc991042017-02-24 08:06:44 -08004028
4029 adjust_mmap_period_count(&in->config, min_size_frames);
4030
Eric Laurent0e46adf2016-12-16 12:49:24 -08004031 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4032 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
4033 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
4034 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
4035 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
4036 step = "open";
4037 ret = -ENODEV;
4038 goto exit;
4039 }
4040
4041 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
4042 if (ret < 0) {
4043 step = "begin";
4044 goto exit;
4045 }
4046 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07004047 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004048 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07004049 ret = platform_get_mmap_data_fd(adev->platform,
4050 in->pcm_device_id, 1 /*capture*/,
4051 &info->shared_memory_fd,
4052 &mmap_size);
4053 if (ret < 0) {
4054 // Fall back to non exclusive mode
4055 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
4056 } else {
4057 if (mmap_size < buffer_size) {
4058 step = "mmap";
4059 goto exit;
4060 }
4061 // FIXME: indicate exclusive mode support by returning a negative buffer size
4062 info->buffer_size_frames *= -1;
4063 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08004064
Haynes Mathew George96483a22017-03-28 14:52:47 -07004065 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004066
4067 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4068 if (ret < 0) {
4069 step = "commit";
4070 goto exit;
4071 }
4072
Phil Burkbc991042017-02-24 08:06:44 -08004073 in->standby = false;
4074 ret = 0;
4075
Eric Laurent0e46adf2016-12-16 12:49:24 -08004076 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4077 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004078
4079exit:
4080 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004081 if (in->pcm == NULL) {
4082 ALOGE("%s: %s - %d", __func__, step, ret);
4083 } else {
4084 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08004085 pcm_close(in->pcm);
4086 in->pcm = NULL;
4087 }
4088 }
4089 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004090 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004091 return ret;
4092}
4093
4094static int in_get_mmap_position(const struct audio_stream_in *stream,
4095 struct audio_mmap_position *position)
4096{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004097 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004098 struct stream_in *in = (struct stream_in *)stream;
4099 ALOGVV("%s", __func__);
4100 if (position == NULL) {
4101 return -EINVAL;
4102 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004103 lock_input_stream(in);
4104 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
4105 in->pcm == NULL) {
4106 ret = -ENOSYS;
4107 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004108 }
4109 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004110 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004111 if (ret < 0) {
4112 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004113 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004114 }
Andy Hungfc044e12017-03-20 09:24:22 -07004115 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004116exit:
4117 pthread_mutex_unlock(&in->lock);
4118 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004119}
4120
jiabin8962a4d2018-03-19 18:21:24 -07004121static int in_get_active_microphones(const struct audio_stream_in *stream,
4122 struct audio_microphone_characteristic_t *mic_array,
4123 size_t *mic_count) {
4124 struct stream_in *in = (struct stream_in *)stream;
4125 struct audio_device *adev = in->dev;
4126 ALOGVV("%s", __func__);
4127
4128 lock_input_stream(in);
4129 pthread_mutex_lock(&adev->lock);
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004130 int ret = platform_get_active_microphones(adev->platform,
jiabin8962a4d2018-03-19 18:21:24 -07004131 audio_channel_count_from_in_mask(in->channel_mask),
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004132 in->usecase, mic_array, mic_count);
jiabin8962a4d2018-03-19 18:21:24 -07004133 pthread_mutex_unlock(&adev->lock);
4134 pthread_mutex_unlock(&in->lock);
4135
4136 return ret;
4137}
4138
4139static int adev_get_microphones(const struct audio_hw_device *dev,
4140 struct audio_microphone_characteristic_t *mic_array,
4141 size_t *mic_count) {
4142 struct audio_device *adev = (struct audio_device *)dev;
4143 ALOGVV("%s", __func__);
4144
4145 pthread_mutex_lock(&adev->lock);
4146 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
4147 pthread_mutex_unlock(&adev->lock);
4148
4149 return ret;
4150}
Eric Laurent0e46adf2016-12-16 12:49:24 -08004151
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004152static int adev_open_output_stream(struct audio_hw_device *dev,
4153 audio_io_handle_t handle,
4154 audio_devices_t devices,
4155 audio_output_flags_t flags,
4156 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07004157 struct audio_stream_out **stream_out,
4158 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004159{
4160 struct audio_device *adev = (struct audio_device *)dev;
4161 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004162 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004163 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
4164 bool is_usb_dev = audio_is_usb_out_device(devices) &&
4165 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004166
Andy Hungd9653bd2017-08-01 19:31:39 -07004167 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
4168 return -ENOSYS;
4169 }
4170
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004171 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
4172 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004173 *stream_out = NULL;
4174 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4175
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004176 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
4177
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004178 if (devices == AUDIO_DEVICE_NONE)
4179 devices = AUDIO_DEVICE_OUT_SPEAKER;
4180
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004181 out->flags = flags;
4182 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004183 out->dev = adev;
Eric Laurentc4aef752013-09-12 17:45:53 -07004184 out->handle = handle;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004185 out->a2dp_compress_mute = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004186
4187 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004188 if ((is_hdmi || is_usb_dev) &&
4189 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
4190 (flags == AUDIO_OUTPUT_FLAG_NONE ||
4191 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Eric Laurentab805ee2018-03-30 12:20:38 -07004192 audio_format_t req_format = config->format;
4193 audio_channel_mask_t req_channel_mask = config->channel_mask;
4194 uint32_t req_sample_rate = config->sample_rate;
4195
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004196 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004197 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004198 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004199 if (config->sample_rate == 0)
4200 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Eric Laurentab805ee2018-03-30 12:20:38 -07004201 if (config->channel_mask == AUDIO_CHANNEL_NONE)
Haynes Mathew George569b7482017-05-08 14:44:27 -07004202 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
4203 if (config->format == AUDIO_FORMAT_DEFAULT)
4204 config->format = AUDIO_FORMAT_PCM_16_BIT;
4205 } else if (is_usb_dev) {
4206 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
4207 &config->format,
4208 &out->supported_formats[0],
4209 MAX_SUPPORTED_FORMATS,
4210 &config->channel_mask,
4211 &out->supported_channel_masks[0],
4212 MAX_SUPPORTED_CHANNEL_MASKS,
4213 &config->sample_rate,
4214 &out->supported_sample_rates[0],
4215 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004216 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004217 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004218 pthread_mutex_unlock(&adev->lock);
Eric Laurentab805ee2018-03-30 12:20:38 -07004219 if (ret != 0) {
4220 // For MMAP NO IRQ, allow conversions in ADSP
4221 if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
4222 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004223
Eric Laurentab805ee2018-03-30 12:20:38 -07004224 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
4225 config->sample_rate = req_sample_rate;
4226 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
4227 config->channel_mask = req_channel_mask;
4228 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
4229 config->format = req_format;
4230 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004231
Haynes Mathew George569b7482017-05-08 14:44:27 -07004232 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004233 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004234 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004235 if (is_hdmi) {
4236 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4237 out->config = pcm_config_hdmi_multi;
4238 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
4239 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4240 out->config = pcm_config_mmap_playback;
4241 out->stream.start = out_start;
4242 out->stream.stop = out_stop;
4243 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4244 out->stream.get_mmap_position = out_get_mmap_position;
4245 } else {
4246 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4247 out->config = pcm_config_hifi;
4248 }
4249
4250 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004251 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004252 if (is_hdmi) {
4253 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
4254 audio_bytes_per_sample(out->format));
4255 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004256 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004257 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07004258 pthread_mutex_lock(&adev->lock);
4259 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4260 pthread_mutex_unlock(&adev->lock);
4261
4262 // reject offload during card offline to allow
4263 // fallback to s/w paths
4264 if (offline) {
4265 ret = -ENODEV;
4266 goto error_open;
4267 }
4268
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004269 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4270 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4271 ALOGE("%s: Unsupported Offload information", __func__);
4272 ret = -EINVAL;
4273 goto error_open;
4274 }
4275 if (!is_supported_format(config->offload_info.format)) {
4276 ALOGE("%s: Unsupported audio format", __func__);
4277 ret = -EINVAL;
4278 goto error_open;
4279 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004280 out->sample_rate = config->offload_info.sample_rate;
4281 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
4282 out->channel_mask = config->offload_info.channel_mask;
4283 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
4284 out->channel_mask = config->channel_mask;
4285 else
4286 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4287
4288 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004289
4290 out->compr_config.codec = (struct snd_codec *)
4291 calloc(1, sizeof(struct snd_codec));
4292
4293 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004294
4295 out->stream.set_callback = out_set_callback;
4296 out->stream.pause = out_pause;
4297 out->stream.resume = out_resume;
4298 out->stream.drain = out_drain;
4299 out->stream.flush = out_flush;
4300
4301 out->compr_config.codec->id =
4302 get_snd_codec_id(config->offload_info.format);
4303 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
4304 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004305 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004306 out->compr_config.codec->bit_rate =
4307 config->offload_info.bit_rate;
4308 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004309 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004310 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
4311
4312 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4313 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004314
4315 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004316 create_offload_callback_thread(out);
4317 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4318 __func__, config->offload_info.version,
4319 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02004320 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4321 switch (config->sample_rate) {
4322 case 0:
4323 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4324 break;
4325 case 8000:
4326 case 16000:
4327 case 48000:
4328 out->sample_rate = config->sample_rate;
4329 break;
4330 default:
4331 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
4332 config->sample_rate);
4333 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4334 ret = -EINVAL;
4335 goto error_open;
4336 }
4337 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4338 switch (config->channel_mask) {
4339 case AUDIO_CHANNEL_NONE:
4340 case AUDIO_CHANNEL_OUT_STEREO:
4341 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4342 break;
4343 default:
4344 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
4345 config->channel_mask);
4346 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4347 ret = -EINVAL;
4348 goto error_open;
4349 }
4350 switch (config->format) {
4351 case AUDIO_FORMAT_DEFAULT:
4352 case AUDIO_FORMAT_PCM_16_BIT:
4353 out->format = AUDIO_FORMAT_PCM_16_BIT;
4354 break;
4355 default:
4356 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
4357 config->format);
4358 config->format = AUDIO_FORMAT_PCM_16_BIT;
4359 ret = -EINVAL;
4360 goto error_open;
4361 }
4362
4363 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004364 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004365 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004366 case 0:
4367 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
4368 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07004369 case 8000:
4370 case 16000:
4371 case 48000:
4372 out->sample_rate = config->sample_rate;
4373 break;
4374 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004375 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
4376 config->sample_rate);
4377 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4378 ret = -EINVAL;
4379 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004380 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004381 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4382 switch (config->channel_mask) {
4383 case AUDIO_CHANNEL_NONE:
4384 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4385 break;
4386 case AUDIO_CHANNEL_OUT_STEREO:
4387 out->channel_mask = config->channel_mask;
4388 break;
4389 default:
4390 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
4391 config->channel_mask);
4392 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4393 ret = -EINVAL;
4394 break;
4395 }
4396 switch (config->format) {
4397 case AUDIO_FORMAT_DEFAULT:
4398 out->format = AUDIO_FORMAT_PCM_16_BIT;
4399 break;
4400 case AUDIO_FORMAT_PCM_16_BIT:
4401 out->format = config->format;
4402 break;
4403 default:
4404 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
4405 config->format);
4406 config->format = AUDIO_FORMAT_PCM_16_BIT;
4407 ret = -EINVAL;
4408 break;
4409 }
4410 if (ret != 0)
4411 goto error_open;
4412
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004413 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4414 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004415 out->config.rate = out->sample_rate;
4416 out->config.channels =
4417 audio_channel_count_from_out_mask(out->channel_mask);
4418 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004419 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004420 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
4421 switch (config->sample_rate) {
4422 case 0:
4423 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4424 break;
4425 case 8000:
4426 case 16000:
4427 case 32000:
4428 case 48000:
4429 out->sample_rate = config->sample_rate;
4430 break;
4431 default:
4432 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
4433 config->sample_rate);
4434 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4435 ret = -EINVAL;
4436 break;
4437 }
Eric Laurentad2dde92017-09-20 18:27:31 -07004438 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004439 switch (config->channel_mask) {
4440 case AUDIO_CHANNEL_NONE:
4441 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4442 break;
4443 case AUDIO_CHANNEL_OUT_STEREO:
4444 out->channel_mask = config->channel_mask;
4445 break;
4446 default:
4447 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
4448 config->channel_mask);
4449 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4450 ret = -EINVAL;
4451 break;
4452 }
4453 switch (config->format) {
4454 case AUDIO_FORMAT_DEFAULT:
4455 out->format = AUDIO_FORMAT_PCM_16_BIT;
4456 break;
4457 case AUDIO_FORMAT_PCM_16_BIT:
4458 out->format = config->format;
4459 break;
4460 default:
4461 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
4462 config->format);
4463 config->format = AUDIO_FORMAT_PCM_16_BIT;
4464 ret = -EINVAL;
4465 break;
4466 }
4467 if (ret != 0)
4468 goto error_open;
4469
vivek mehtaa68fea62017-06-08 19:04:02 -07004470 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07004471 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4472 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004473 out->config.rate = out->sample_rate;
4474 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07004475 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004476 out->sample_rate,
4477 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07004478 out->config.channels,
4479 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004480 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07004481 out->config.period_size = buffer_size / frame_size;
4482 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
4483 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004484 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004485 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07004486 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4487 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004488 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07004489 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
4490 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004491 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07004492 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004493 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004494 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004495 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004496 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4497 out->config = pcm_config_mmap_playback;
4498 out->stream.start = out_start;
4499 out->stream.stop = out_stop;
4500 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4501 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004502 } else {
4503 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4504 out->config = pcm_config_low_latency;
4505 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004506
4507 if (config->sample_rate == 0) {
4508 out->sample_rate = out->config.rate;
4509 } else {
4510 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004511 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004512 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
4513 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
4514 } else {
4515 out->channel_mask = config->channel_mask;
4516 }
4517 if (config->format == AUDIO_FORMAT_DEFAULT)
4518 out->format = audio_format_from_pcm_format(out->config.format);
4519 else if (!audio_is_linear_pcm(config->format)) {
4520 config->format = AUDIO_FORMAT_PCM_16_BIT;
4521 ret = -EINVAL;
4522 goto error_open;
4523 } else {
4524 out->format = config->format;
4525 }
4526
4527 out->config.rate = out->sample_rate;
4528 out->config.channels =
4529 audio_channel_count_from_out_mask(out->channel_mask);
4530 if (out->format != audio_format_from_pcm_format(out->config.format)) {
4531 out->config.format = pcm_format_from_audio_format(out->format);
4532 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004533 }
Kevin Rocard50eff892017-05-02 16:52:05 -07004534
4535 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
4536 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004537 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004538 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
4539 __func__, config->sample_rate, config->format, config->channel_mask);
4540 config->sample_rate = out->sample_rate;
4541 config->format = out->format;
4542 config->channel_mask = out->channel_mask;
4543 ret = -EINVAL;
4544 goto error_open;
4545 }
4546
Andy Hung6fcba9c2014-03-18 11:53:32 -07004547 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
4548 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004549
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004550 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004551 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004552 adev->primary_output = out;
4553 else {
4554 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004555 ret = -EEXIST;
4556 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004557 }
4558 }
4559
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004560 /* Check if this usecase is already existing */
4561 pthread_mutex_lock(&adev->lock);
4562 if (get_usecase_from_list(adev, out->usecase) != NULL) {
4563 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004564 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004565 ret = -EEXIST;
4566 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004567 }
4568 pthread_mutex_unlock(&adev->lock);
4569
4570 out->stream.common.get_sample_rate = out_get_sample_rate;
4571 out->stream.common.set_sample_rate = out_set_sample_rate;
4572 out->stream.common.get_buffer_size = out_get_buffer_size;
4573 out->stream.common.get_channels = out_get_channels;
4574 out->stream.common.get_format = out_get_format;
4575 out->stream.common.set_format = out_set_format;
4576 out->stream.common.standby = out_standby;
4577 out->stream.common.dump = out_dump;
4578 out->stream.common.set_parameters = out_set_parameters;
4579 out->stream.common.get_parameters = out_get_parameters;
4580 out->stream.common.add_audio_effect = out_add_audio_effect;
4581 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4582 out->stream.get_latency = out_get_latency;
4583 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004584#ifdef NO_AUDIO_OUT
4585 out->stream.write = out_write_for_no_output;
4586#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004587 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004588#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004589 out->stream.get_render_position = out_get_render_position;
4590 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004591 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004592
Eric Laurent0e46adf2016-12-16 12:49:24 -08004593 if (out->realtime)
4594 out->af_period_multiplier = af_period_multiplier;
4595 else
4596 out->af_period_multiplier = 1;
4597
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004598 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004599 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004600 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004601
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004602 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004603 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004604 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4605
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004606 config->format = out->stream.common.get_format(&out->stream.common);
4607 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4608 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4609
Kevin Rocarda325aa22018-04-03 09:15:52 -07004610 register_format(out->format, out->supported_formats);
4611 register_channel_mask(out->channel_mask, out->supported_channel_masks);
4612 register_sample_rate(out->sample_rate, out->supported_sample_rates);
4613
Andy Hunga452b0a2017-03-15 14:51:15 -07004614 out->error_log = error_log_create(
4615 ERROR_LOG_ENTRIES,
4616 1000000000 /* aggregate consecutive identical errors within one second in ns */);
4617
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004618 /*
4619 By locking output stream before registering, we allow the callback
4620 to update stream's state only after stream's initial state is set to
4621 adev state.
4622 */
4623 lock_output_stream(out);
4624 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4625 pthread_mutex_lock(&adev->lock);
4626 out->card_status = adev->card_status;
4627 pthread_mutex_unlock(&adev->lock);
4628 pthread_mutex_unlock(&out->lock);
4629
vivek mehta4a824772017-06-08 19:05:49 -07004630 stream_app_type_cfg_init(&out->app_type_cfg);
4631
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004632 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004633
Eric Laurent994a6932013-07-17 11:51:42 -07004634 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004635 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004636
4637error_open:
4638 free(out);
4639 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07004640 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004641 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004642}
4643
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004644static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004645 struct audio_stream_out *stream)
4646{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004647 struct stream_out *out = (struct stream_out *)stream;
4648 struct audio_device *adev = out->dev;
4649
Eric Laurent994a6932013-07-17 11:51:42 -07004650 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004651
4652 // must deregister from sndmonitor first to prevent races
4653 // between the callback and close_stream
4654 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004655 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004656 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
4657 destroy_offload_callback_thread(out);
4658
4659 if (out->compr_config.codec != NULL)
4660 free(out->compr_config.codec);
4661 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004662
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004663 out->a2dp_compress_mute = false;
4664
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004665 if (adev->voice_tx_output == out)
4666 adev->voice_tx_output = NULL;
4667
Andy Hunga452b0a2017-03-15 14:51:15 -07004668 error_log_destroy(out->error_log);
4669 out->error_log = NULL;
4670
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004671 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004672 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004673 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004674 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004675 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004676}
4677
4678static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4679{
4680 struct audio_device *adev = (struct audio_device *)dev;
4681 struct str_parms *parms;
4682 char *str;
4683 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004684 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004685 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07004686 int status = 0;
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004687 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004688
Joe Onorato188b6222016-03-01 11:02:27 -08004689 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004690
4691 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004692
4693 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004694 status = voice_set_parameters(adev, parms);
4695 if (status != 0) {
4696 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004697 }
4698
4699 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4700 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07004701 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004702 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4703 adev->bluetooth_nrec = true;
4704 else
4705 adev->bluetooth_nrec = false;
4706 }
4707
4708 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4709 if (ret >= 0) {
4710 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4711 adev->screen_off = false;
4712 else
4713 adev->screen_off = true;
4714 }
4715
jasmine cha270b7762018-03-30 15:41:33 +08004716#ifndef MAXXAUDIO_QDSP_ENABLED
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004717 ret = str_parms_get_int(parms, "rotation", &val);
4718 if (ret >= 0) {
4719 bool reverse_speakers = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004720 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004721 // FIXME: note that the code below assumes that the speakers are in the correct placement
4722 // relative to the user when the device is rotated 90deg from its default rotation. This
4723 // assumption is device-specific, not platform-specific like this code.
4724 case 270:
4725 reverse_speakers = true;
4726 break;
4727 case 0:
4728 case 90:
4729 case 180:
4730 break;
4731 default:
4732 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07004733 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004734 }
Eric Laurent03f09432014-03-25 18:09:11 -07004735 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004736 // check and set swap
4737 // - check if orientation changed and speaker active
4738 // - set rotation and cache the rotation value
4739 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004740 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004741 }
jasmine cha270b7762018-03-30 15:41:33 +08004742#endif
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004743
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004744 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4745 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004746 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004747 }
4748
David Linee3fe402017-03-13 10:00:42 -07004749 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4750 if (ret >= 0) {
4751 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004752 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004753 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4754 if (ret >= 0) {
4755 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004756 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004757 }
Eric Laurent99dab492017-06-17 15:19:08 -07004758 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004759 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4760 if (ret >= 0) {
4761 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004762 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004763 }
4764 }
4765 }
4766
4767 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4768 if (ret >= 0) {
4769 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004770 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004771 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4772 if (ret >= 0) {
4773 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004774 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004775 }
Eric Laurent99dab492017-06-17 15:19:08 -07004776 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004777 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4778 if (ret >= 0) {
4779 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004780 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004781 }
4782 }
4783 }
4784
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004785 audio_extn_hfp_set_parameters(adev, parms);
jasmine cha270b7762018-03-30 15:41:33 +08004786 audio_extn_ma_set_parameters(adev, parms);
4787
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004788 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
4789 if (status >= 0 && a2dp_reconfig) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004790 struct audio_usecase *usecase;
4791 struct listnode *node;
4792 list_for_each(node, &adev->usecase_list) {
4793 usecase = node_to_item(node, struct audio_usecase, list);
4794 if ((usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004795 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004796 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
4797
4798 pthread_mutex_unlock(&adev->lock);
4799 lock_output_stream(usecase->stream.out);
4800 pthread_mutex_lock(&adev->lock);
4801 audio_extn_a2dp_set_handoff_mode(true);
4802 // force device switch to reconfigure encoder
4803 select_devices(adev, usecase->id);
4804 audio_extn_a2dp_set_handoff_mode(false);
4805 pthread_mutex_unlock(&usecase->stream.out->lock);
4806 break;
4807 }
4808 }
4809 }
4810
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004811done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004812 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004813 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004814 ALOGV("%s: exit with code(%d)", __func__, status);
4815 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004816}
4817
4818static char* adev_get_parameters(const struct audio_hw_device *dev,
4819 const char *keys)
4820{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004821 struct audio_device *adev = (struct audio_device *)dev;
4822 struct str_parms *reply = str_parms_create();
4823 struct str_parms *query = str_parms_create_str(keys);
4824 char *str;
4825
4826 pthread_mutex_lock(&adev->lock);
4827
4828 voice_get_parameters(adev, query, reply);
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004829 audio_extn_a2dp_get_parameters(query, reply);
4830
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004831 str = str_parms_to_str(reply);
4832 str_parms_destroy(query);
4833 str_parms_destroy(reply);
4834
4835 pthread_mutex_unlock(&adev->lock);
4836 ALOGV("%s: exit: returns - %s", __func__, str);
4837 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004838}
4839
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004840static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004841{
4842 return 0;
4843}
4844
Haynes Mathew George5191a852013-09-11 14:19:36 -07004845static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4846{
4847 int ret;
4848 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004849
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004850 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4851
Haynes Mathew George5191a852013-09-11 14:19:36 -07004852 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004853 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004854 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004855
Haynes Mathew George5191a852013-09-11 14:19:36 -07004856 return ret;
4857}
4858
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004859static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004860{
4861 return -ENOSYS;
4862}
4863
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004864static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4865 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004866{
4867 return -ENOSYS;
4868}
4869
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004870static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004871{
4872 return -ENOSYS;
4873}
4874
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004875static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004876{
4877 return -ENOSYS;
4878}
4879
4880static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4881{
4882 struct audio_device *adev = (struct audio_device *)dev;
4883
4884 pthread_mutex_lock(&adev->lock);
4885 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004886 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004887 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004888 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4889 voice_is_in_call(adev)) {
4890 voice_stop_call(adev);
4891 adev->current_call_output = NULL;
4892 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004893 }
4894 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004895
4896 audio_extn_extspk_set_mode(adev->extspk, mode);
4897
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004898 return 0;
4899}
4900
4901static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4902{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004903 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004904 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004905
Eric Laurent2bafff12016-03-17 12:17:23 -07004906 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004907 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004908 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4909 ret = audio_extn_hfp_set_mic_mute(adev, state);
4910 } else {
4911 ret = voice_set_mic_mute(adev, state);
4912 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004913 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004914 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004915
4916 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004917}
4918
4919static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4920{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004921 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004922 return 0;
4923}
4924
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004925static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004926 const struct audio_config *config)
4927{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004928 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004929
Eric Laurent74b55762017-07-09 17:04:53 -07004930 /* Don't know if USB HIFI in this context so use true to be conservative */
4931 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4932 true /*is_usb_hifi */) != 0)
4933 return 0;
4934
vivek mehtaa68fea62017-06-08 19:04:02 -07004935 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4936 config->sample_rate, config->format,
4937 channel_count,
4938 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004939}
4940
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004941static bool adev_input_allow_hifi_record(struct audio_device *adev,
4942 audio_devices_t devices,
4943 audio_input_flags_t flags,
4944 audio_source_t source) {
4945 const bool allowed = true;
4946
4947 if (!audio_is_usb_in_device(devices))
4948 return !allowed;
4949
4950 switch (flags) {
4951 case AUDIO_INPUT_FLAG_NONE:
4952 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4953 break;
4954 default:
4955 return !allowed;
4956 }
4957
4958 switch (source) {
4959 case AUDIO_SOURCE_DEFAULT:
4960 case AUDIO_SOURCE_MIC:
4961 case AUDIO_SOURCE_UNPROCESSED:
4962 break;
4963 default:
4964 return !allowed;
4965 }
4966
4967 switch (adev->mode) {
4968 case 0:
4969 break;
4970 default:
4971 return !allowed;
4972 }
4973
4974 return allowed;
4975}
4976
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004977static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004978 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004979 audio_devices_t devices,
4980 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004981 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004982 audio_input_flags_t flags,
4983 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004984 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004985{
4986 struct audio_device *adev = (struct audio_device *)dev;
4987 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004988 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004989 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004990 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004991 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004992 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4993 devices,
4994 flags,
4995 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004996 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004997 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004998
Andy Hungd9653bd2017-08-01 19:31:39 -07004999 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
5000 return -ENOSYS;
5001 }
5002
Eric Laurent74b55762017-07-09 17:04:53 -07005003 if (!(is_usb_dev && may_use_hifi_record)) {
5004 if (config->sample_rate == 0)
5005 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
5006 if (config->channel_mask == AUDIO_CHANNEL_NONE)
5007 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5008 if (config->format == AUDIO_FORMAT_DEFAULT)
5009 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005010
Eric Laurent74b55762017-07-09 17:04:53 -07005011 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
5012
5013 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
5014 return -EINVAL;
5015 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005016
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005017 if (audio_extn_tfa_98xx_is_supported() &&
5018 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005019 return -EINVAL;
5020
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005021 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
5022
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005023 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005024 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005025
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005026 in->stream.common.get_sample_rate = in_get_sample_rate;
5027 in->stream.common.set_sample_rate = in_set_sample_rate;
5028 in->stream.common.get_buffer_size = in_get_buffer_size;
5029 in->stream.common.get_channels = in_get_channels;
5030 in->stream.common.get_format = in_get_format;
5031 in->stream.common.set_format = in_set_format;
5032 in->stream.common.standby = in_standby;
5033 in->stream.common.dump = in_dump;
5034 in->stream.common.set_parameters = in_set_parameters;
5035 in->stream.common.get_parameters = in_get_parameters;
5036 in->stream.common.add_audio_effect = in_add_audio_effect;
5037 in->stream.common.remove_audio_effect = in_remove_audio_effect;
5038 in->stream.set_gain = in_set_gain;
5039 in->stream.read = in_read;
5040 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08005041 in->stream.get_capture_position = in_get_capture_position;
jiabin8962a4d2018-03-19 18:21:24 -07005042 in->stream.get_active_microphones = in_get_active_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005043
5044 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005045 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005046 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005047 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005048 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005049 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005050
Arun Mirpuriba2749a2018-04-17 14:32:24 -07005051 ALOGV("%s: source = %d, config->channel_mask = %d", __func__, source, config->channel_mask);
5052 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
5053 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
5054 /* Force channel config requested to mono if incall
5055 record is being requested for only uplink/downlink */
5056 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
5057 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5058 ret = -EINVAL;
5059 goto err_open;
5060 }
5061 }
5062
Haynes Mathew George569b7482017-05-08 14:44:27 -07005063 if (is_usb_dev && may_use_hifi_record) {
5064 /* HiFi record selects an appropriate format, channel, rate combo
5065 depending on sink capabilities*/
5066 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
5067 &config->format,
5068 &in->supported_formats[0],
5069 MAX_SUPPORTED_FORMATS,
5070 &config->channel_mask,
5071 &in->supported_channel_masks[0],
5072 MAX_SUPPORTED_CHANNEL_MASKS,
5073 &config->sample_rate,
5074 &in->supported_sample_rates[0],
5075 MAX_SUPPORTED_SAMPLE_RATES);
5076 if (ret != 0) {
5077 ret = -EINVAL;
5078 goto err_open;
5079 }
Eric Laurent74b55762017-07-09 17:04:53 -07005080 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005081 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07005082 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07005083 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
5084 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
5085 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5086 bool ret_error = false;
5087 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5088 from HAL is 8_24
5089 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5090 8_24 return error indicating supported format is 8_24
5091 *> In case of any other source requesting 24 bit or float return error
5092 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07005093
vivek mehta57ff9b52016-04-28 14:13:08 -07005094 on error flinger will retry with supported format passed
5095 */
5096 if (source != AUDIO_SOURCE_UNPROCESSED) {
5097 config->format = AUDIO_FORMAT_PCM_16_BIT;
5098 ret_error = true;
5099 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
5100 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
5101 ret_error = true;
5102 }
5103
5104 if (ret_error) {
5105 ret = -EINVAL;
5106 goto err_open;
5107 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005108 }
5109
vivek mehta57ff9b52016-04-28 14:13:08 -07005110 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07005111 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07005112
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005113 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005114 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
5115 if (config->sample_rate == 0)
5116 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5117 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5118 config->sample_rate != 8000) {
5119 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5120 ret = -EINVAL;
5121 goto err_open;
5122 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005123
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005124 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5125 config->format = AUDIO_FORMAT_PCM_16_BIT;
5126 ret = -EINVAL;
5127 goto err_open;
5128 }
5129
5130 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5131 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07005132 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005133 } else if (is_usb_dev && may_use_hifi_record) {
5134 in->usecase = USECASE_AUDIO_RECORD_HIFI;
5135 in->config = pcm_config_audio_capture;
5136 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005137 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5138 config->sample_rate,
5139 config->format,
5140 channel_count,
5141 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005142 in->config.period_size = buffer_size / frame_size;
5143 in->config.rate = config->sample_rate;
5144 in->af_period_multiplier = 1;
5145 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005146 } else {
5147 in->usecase = USECASE_AUDIO_RECORD;
5148 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08005149 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005150 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07005151#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005152 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07005153#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08005154 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005155 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08005156 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005157 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005158 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5159 config->sample_rate,
5160 config->format,
5161 channel_count,
5162 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005163 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005164 in->config.rate = config->sample_rate;
5165 in->af_period_multiplier = 1;
5166 } else {
5167 // period size is left untouched for rt mode playback
5168 in->config = pcm_config_audio_capture_rt;
5169 in->af_period_multiplier = af_period_multiplier;
5170 }
5171 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
5172 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005173 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08005174 in->usecase = USECASE_AUDIO_RECORD_MMAP;
5175 in->config = pcm_config_mmap_capture;
5176 in->stream.start = in_start;
5177 in->stream.stop = in_stop;
5178 in->stream.create_mmap_buffer = in_create_mmap_buffer;
5179 in->stream.get_mmap_position = in_get_mmap_position;
5180 in->af_period_multiplier = 1;
5181 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07005182 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07005183 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07005184 (config->sample_rate == 8000 ||
5185 config->sample_rate == 16000 ||
5186 config->sample_rate == 32000 ||
5187 config->sample_rate == 48000) &&
5188 channel_count == 1) {
5189 in->usecase = USECASE_AUDIO_RECORD_VOIP;
5190 in->config = pcm_config_audio_capture;
5191 frame_size = audio_stream_in_frame_size(&in->stream);
5192 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
5193 config->sample_rate,
5194 config->format,
5195 channel_count, false /*is_low_latency*/);
5196 in->config.period_size = buffer_size / frame_size;
5197 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
5198 in->config.rate = config->sample_rate;
5199 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005200 } else {
5201 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005202 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005203 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5204 config->sample_rate,
5205 config->format,
5206 channel_count,
5207 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005208 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005209 in->config.rate = config->sample_rate;
5210 in->af_period_multiplier = 1;
5211 }
5212 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
5213 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005214 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08005215
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005216 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07005217 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005218
Kevin Rocarda325aa22018-04-03 09:15:52 -07005219
5220 register_format(in->format, in->supported_formats);
5221 register_channel_mask(in->channel_mask, in->supported_channel_masks);
5222 register_sample_rate(in->sample_rate, in->supported_sample_rates);
5223
Andy Hungd13f0d32017-06-12 13:58:37 -07005224 in->error_log = error_log_create(
5225 ERROR_LOG_ENTRIES,
5226 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
5227
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005228 /* This stream could be for sound trigger lab,
5229 get sound trigger pcm if present */
5230 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005231
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005232 lock_input_stream(in);
5233 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5234 pthread_mutex_lock(&adev->lock);
5235 in->card_status = adev->card_status;
5236 pthread_mutex_unlock(&adev->lock);
5237 pthread_mutex_unlock(&in->lock);
5238
vivek mehta4a824772017-06-08 19:05:49 -07005239 stream_app_type_cfg_init(&in->app_type_cfg);
5240
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005241 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005242 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005243 return 0;
5244
5245err_open:
5246 free(in);
5247 *stream_in = NULL;
5248 return ret;
5249}
5250
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005251static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005252 struct audio_stream_in *stream)
5253{
Andy Hungd13f0d32017-06-12 13:58:37 -07005254 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005255 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005256
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005257 // must deregister from sndmonitor first to prevent races
5258 // between the callback and close_stream
5259 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005260 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07005261
5262 error_log_destroy(in->error_log);
5263 in->error_log = NULL;
5264
Andy Hung0dbb52b2017-08-09 13:51:38 -07005265 pthread_mutex_destroy(&in->pre_lock);
5266 pthread_mutex_destroy(&in->lock);
5267
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005268 free(stream);
5269
5270 return;
5271}
5272
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005273static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005274{
5275 return 0;
5276}
5277
Andy Hung31aca912014-03-20 17:14:59 -07005278/* verifies input and output devices and their capabilities.
5279 *
5280 * This verification is required when enabling extended bit-depth or
5281 * sampling rates, as not all qcom products support it.
5282 *
5283 * Suitable for calling only on initialization such as adev_open().
5284 * It fills the audio_device use_case_table[] array.
5285 *
5286 * Has a side-effect that it needs to configure audio routing / devices
5287 * in order to power up the devices and read the device parameters.
5288 * It does not acquire any hw device lock. Should restore the devices
5289 * back to "normal state" upon completion.
5290 */
5291static int adev_verify_devices(struct audio_device *adev)
5292{
5293 /* enumeration is a bit difficult because one really wants to pull
5294 * the use_case, device id, etc from the hidden pcm_device_table[].
5295 * In this case there are the following use cases and device ids.
5296 *
5297 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
5298 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005299 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07005300 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
5301 * [USECASE_AUDIO_RECORD] = {0, 0},
5302 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
5303 * [USECASE_VOICE_CALL] = {2, 2},
5304 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005305 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07005306 * USECASE_VOICE_CALL omitted, but possible for either input or output.
5307 */
5308
5309 /* should be the usecases enabled in adev_open_input_stream() */
5310 static const int test_in_usecases[] = {
5311 USECASE_AUDIO_RECORD,
5312 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
5313 };
5314 /* should be the usecases enabled in adev_open_output_stream()*/
5315 static const int test_out_usecases[] = {
5316 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
5317 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
5318 };
5319 static const usecase_type_t usecase_type_by_dir[] = {
5320 PCM_PLAYBACK,
5321 PCM_CAPTURE,
5322 };
5323 static const unsigned flags_by_dir[] = {
5324 PCM_OUT,
5325 PCM_IN,
5326 };
5327
5328 size_t i;
5329 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005330 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07005331 char info[512]; /* for possible debug info */
5332
5333 for (dir = 0; dir < 2; ++dir) {
5334 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
5335 const unsigned flags_dir = flags_by_dir[dir];
5336 const size_t testsize =
5337 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
5338 const int *testcases =
5339 dir ? test_in_usecases : test_out_usecases;
5340 const audio_devices_t audio_device =
5341 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
5342
5343 for (i = 0; i < testsize; ++i) {
5344 const audio_usecase_t audio_usecase = testcases[i];
5345 int device_id;
5346 snd_device_t snd_device;
5347 struct pcm_params **pparams;
5348 struct stream_out out;
5349 struct stream_in in;
5350 struct audio_usecase uc_info;
5351 int retval;
5352
5353 pparams = &adev->use_case_table[audio_usecase];
5354 pcm_params_free(*pparams); /* can accept null input */
5355 *pparams = NULL;
5356
5357 /* find the device ID for the use case (signed, for error) */
5358 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
5359 if (device_id < 0)
5360 continue;
5361
5362 /* prepare structures for device probing */
5363 memset(&uc_info, 0, sizeof(uc_info));
5364 uc_info.id = audio_usecase;
5365 uc_info.type = usecase_type;
5366 if (dir) {
5367 adev->active_input = &in;
5368 memset(&in, 0, sizeof(in));
5369 in.device = audio_device;
5370 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
5371 uc_info.stream.in = &in;
5372 } else {
5373 adev->active_input = NULL;
5374 }
5375 memset(&out, 0, sizeof(out));
5376 out.devices = audio_device; /* only field needed in select_devices */
5377 uc_info.stream.out = &out;
5378 uc_info.devices = audio_device;
5379 uc_info.in_snd_device = SND_DEVICE_NONE;
5380 uc_info.out_snd_device = SND_DEVICE_NONE;
5381 list_add_tail(&adev->usecase_list, &uc_info.list);
5382
5383 /* select device - similar to start_(in/out)put_stream() */
5384 retval = select_devices(adev, audio_usecase);
5385 if (retval >= 0) {
5386 *pparams = pcm_params_get(card_id, device_id, flags_dir);
5387#if LOG_NDEBUG == 0
5388 if (*pparams) {
5389 ALOGV("%s: (%s) card %d device %d", __func__,
5390 dir ? "input" : "output", card_id, device_id);
5391 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07005392 } else {
5393 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
5394 }
5395#endif
5396 }
5397
5398 /* deselect device - similar to stop_(in/out)put_stream() */
5399 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07005400 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07005401 /* 2. Disable the rx device */
5402 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07005403 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07005404 list_remove(&uc_info.list);
5405 }
5406 }
5407 adev->active_input = NULL; /* restore adev state */
5408 return 0;
5409}
5410
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005411static int adev_close(hw_device_t *device)
5412{
Andy Hung31aca912014-03-20 17:14:59 -07005413 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005414 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005415
5416 if (!adev)
5417 return 0;
5418
5419 pthread_mutex_lock(&adev_init_lock);
5420
5421 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005422 audio_extn_snd_mon_unregister_listener(adev);
5423 audio_extn_tfa_98xx_deinit();
jasmine cha270b7762018-03-30 15:41:33 +08005424 audio_extn_ma_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005425 audio_route_free(adev->audio_route);
5426 free(adev->snd_dev_ref_cnt);
5427 platform_deinit(adev->platform);
5428 audio_extn_extspk_deinit(adev->extspk);
5429 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005430 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005431 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
5432 pcm_params_free(adev->use_case_table[i]);
5433 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005434 if (adev->adm_deinit)
5435 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005436 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005437 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07005438 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07005439
5440 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005441
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005442 return 0;
5443}
5444
Glenn Kasten4f993392014-05-14 07:30:48 -07005445/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5446 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5447 * just that it _might_ work.
5448 */
5449static int period_size_is_plausible_for_low_latency(int period_size)
5450{
5451 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005452 case 48:
5453 case 96:
5454 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07005455 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005456 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07005457 case 240:
5458 case 320:
5459 case 480:
5460 return 1;
5461 default:
5462 return 0;
5463 }
5464}
5465
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005466static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
5467{
5468 int card;
5469 card_status_t status;
5470
5471 if (!parms)
5472 return;
5473
5474 if (parse_snd_card_status(parms, &card, &status) < 0)
5475 return;
5476
5477 pthread_mutex_lock(&adev->lock);
5478 bool valid_cb = (card == adev->snd_card);
5479 if (valid_cb) {
5480 if (adev->card_status != status) {
5481 adev->card_status = status;
5482 platform_snd_card_update(adev->platform, status);
5483 }
5484 }
5485 pthread_mutex_unlock(&adev->lock);
5486 return;
5487}
5488
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005489/* out and adev lock held */
5490static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
5491{
5492 struct audio_usecase *uc_info;
5493 float left_p;
5494 float right_p;
5495 audio_devices_t devices;
5496
5497 uc_info = get_usecase_from_list(adev, out->usecase);
5498 if (uc_info == NULL) {
5499 ALOGE("%s: Could not find the usecase (%d) in the list",
5500 __func__, out->usecase);
5501 return -EINVAL;
5502 }
5503
5504 ALOGD("%s: enter: usecase(%d: %s)", __func__,
5505 out->usecase, use_case_table[out->usecase]);
5506
5507 if (restore) {
5508 // restore A2DP device for active usecases and unmute if required
5509 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
5510 !is_a2dp_device(uc_info->out_snd_device)) {
5511 ALOGD("%s: restoring A2DP and unmuting stream", __func__);
5512 select_devices(adev, uc_info->id);
5513 pthread_mutex_lock(&out->compr_mute_lock);
5514 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5515 (out->a2dp_compress_mute)) {
5516 out->a2dp_compress_mute = false;
5517 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5518 }
5519 pthread_mutex_unlock(&out->compr_mute_lock);
5520 }
5521 } else {
5522 // mute compress stream if suspended
5523 pthread_mutex_lock(&out->compr_mute_lock);
5524 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5525 (!out->a2dp_compress_mute)) {
5526 if (!out->standby) {
5527 ALOGD("%s: selecting speaker and muting stream", __func__);
5528 devices = out->devices;
5529 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
5530 left_p = out->volume_l;
5531 right_p = out->volume_r;
5532 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5533 compress_pause(out->compr);
5534 set_compr_volume(&out->stream, 0.0f, 0.0f);
5535 out->a2dp_compress_mute = true;
5536 select_devices(adev, out->usecase);
5537 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5538 compress_resume(out->compr);
5539 out->devices = devices;
5540 out->volume_l = left_p;
5541 out->volume_r = right_p;
5542 }
5543 }
5544 pthread_mutex_unlock(&out->compr_mute_lock);
5545 }
5546 ALOGV("%s: exit", __func__);
5547 return 0;
5548}
5549
5550int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
5551{
5552 int ret = 0;
5553
5554 lock_output_stream(out);
5555 pthread_mutex_lock(&adev->lock);
5556
5557 ret = check_a2dp_restore_l(adev, out, restore);
5558
5559 pthread_mutex_unlock(&adev->lock);
5560 pthread_mutex_unlock(&out->lock);
5561 return ret;
5562}
5563
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005564static int adev_open(const hw_module_t *module, const char *name,
5565 hw_device_t **device)
5566{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005567 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005568
Eric Laurent2bafff12016-03-17 12:17:23 -07005569 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005570 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005571 pthread_mutex_lock(&adev_init_lock);
5572 if (audio_device_ref_count != 0) {
5573 *device = &adev->device.common;
5574 audio_device_ref_count++;
5575 ALOGV("%s: returning existing instance of adev", __func__);
5576 ALOGV("%s: exit", __func__);
5577 pthread_mutex_unlock(&adev_init_lock);
5578 return 0;
5579 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005580 adev = calloc(1, sizeof(struct audio_device));
5581
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005582 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5583
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005584 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5585 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5586 adev->device.common.module = (struct hw_module_t *)module;
5587 adev->device.common.close = adev_close;
5588
5589 adev->device.init_check = adev_init_check;
5590 adev->device.set_voice_volume = adev_set_voice_volume;
5591 adev->device.set_master_volume = adev_set_master_volume;
5592 adev->device.get_master_volume = adev_get_master_volume;
5593 adev->device.set_master_mute = adev_set_master_mute;
5594 adev->device.get_master_mute = adev_get_master_mute;
5595 adev->device.set_mode = adev_set_mode;
5596 adev->device.set_mic_mute = adev_set_mic_mute;
5597 adev->device.get_mic_mute = adev_get_mic_mute;
5598 adev->device.set_parameters = adev_set_parameters;
5599 adev->device.get_parameters = adev_get_parameters;
5600 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5601 adev->device.open_output_stream = adev_open_output_stream;
5602 adev->device.close_output_stream = adev_close_output_stream;
5603 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005604
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005605 adev->device.close_input_stream = adev_close_input_stream;
5606 adev->device.dump = adev_dump;
jiabin8962a4d2018-03-19 18:21:24 -07005607 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005608
5609 /* Set the default route before the PCM stream is opened */
5610 pthread_mutex_lock(&adev->lock);
5611 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005612 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005613 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005614 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005615 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005616 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005617 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005618 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005619 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005620 pthread_mutex_unlock(&adev->lock);
5621
5622 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005623 adev->platform = platform_init(adev);
5624 if (!adev->platform) {
5625 free(adev->snd_dev_ref_cnt);
5626 free(adev);
5627 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5628 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005629 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005630 return -EINVAL;
5631 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05005632 adev->extspk = audio_extn_extspk_init(adev);
5633
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005634 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5635 if (adev->visualizer_lib == NULL) {
5636 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5637 } else {
5638 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5639 adev->visualizer_start_output =
Aniket Kumar Lata72a3cea2018-04-06 13:56:37 -07005640 (int (*)(audio_io_handle_t, int, int, int))dlsym(adev->visualizer_lib,
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005641 "visualizer_hal_start_output");
5642 adev->visualizer_stop_output =
5643 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5644 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07005645 }
5646
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005647 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5648 if (adev->offload_effects_lib == NULL) {
5649 ALOGW("%s: DLOPEN failed for %s", __func__,
5650 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5651 } else {
5652 ALOGV("%s: DLOPEN successful for %s", __func__,
5653 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5654 adev->offload_effects_start_output =
5655 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5656 "offload_effects_bundle_hal_start_output");
5657 adev->offload_effects_stop_output =
5658 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5659 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07005660 }
5661
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005662 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5663 if (adev->adm_lib == NULL) {
5664 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5665 } else {
5666 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5667 adev->adm_init = (adm_init_t)
5668 dlsym(adev->adm_lib, "adm_init");
5669 adev->adm_deinit = (adm_deinit_t)
5670 dlsym(adev->adm_lib, "adm_deinit");
5671 adev->adm_register_input_stream = (adm_register_input_stream_t)
5672 dlsym(adev->adm_lib, "adm_register_input_stream");
5673 adev->adm_register_output_stream = (adm_register_output_stream_t)
5674 dlsym(adev->adm_lib, "adm_register_output_stream");
5675 adev->adm_deregister_stream = (adm_deregister_stream_t)
5676 dlsym(adev->adm_lib, "adm_deregister_stream");
5677 adev->adm_request_focus = (adm_request_focus_t)
5678 dlsym(adev->adm_lib, "adm_request_focus");
5679 adev->adm_abandon_focus = (adm_abandon_focus_t)
5680 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08005681 adev->adm_set_config = (adm_set_config_t)
5682 dlsym(adev->adm_lib, "adm_set_config");
5683 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5684 dlsym(adev->adm_lib, "adm_request_focus_v2");
5685 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5686 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5687 adev->adm_on_routing_change = (adm_on_routing_change_t)
5688 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005689 }
5690
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005691 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005692 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005693
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005694 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005695
Andy Hung31aca912014-03-20 17:14:59 -07005696 if (k_enable_extended_precision)
5697 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005698
Glenn Kasten4f993392014-05-14 07:30:48 -07005699 char value[PROPERTY_VALUE_MAX];
5700 int trial;
5701 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5702 trial = atoi(value);
5703 if (period_size_is_plausible_for_low_latency(trial)) {
5704 pcm_config_low_latency.period_size = trial;
5705 pcm_config_low_latency.start_threshold = trial / 4;
5706 pcm_config_low_latency.avail_min = trial / 4;
5707 configured_low_latency_capture_period_size = trial;
5708 }
5709 }
5710 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5711 trial = atoi(value);
5712 if (period_size_is_plausible_for_low_latency(trial)) {
5713 configured_low_latency_capture_period_size = trial;
5714 }
5715 }
5716
Vignesh Kulothunganb6f0a9c2018-03-22 13:50:22 -07005717 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
5718
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005719 // commented as full set of app type cfg is sent from platform
5720 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005721 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005722
5723 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5724 af_period_multiplier = atoi(value);
5725 if (af_period_multiplier < 0) {
5726 af_period_multiplier = 2;
5727 } else if (af_period_multiplier > 4) {
5728 af_period_multiplier = 4;
5729 }
5730 ALOGV("new period_multiplier = %d", af_period_multiplier);
5731 }
5732
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005733 audio_extn_tfa_98xx_init(adev);
jasmine cha270b7762018-03-30 15:41:33 +08005734 audio_extn_ma_init(adev->platform);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005735
vivek mehta1a9b7c02015-06-25 11:49:38 -07005736 pthread_mutex_unlock(&adev_init_lock);
5737
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005738 if (adev->adm_init)
5739 adev->adm_data = adev->adm_init();
5740
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005741 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005742 audio_extn_snd_mon_init();
5743 pthread_mutex_lock(&adev->lock);
5744 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
5745 adev->card_status = CARD_STATUS_ONLINE;
5746 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005747 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005748
Eric Laurent2bafff12016-03-17 12:17:23 -07005749 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005750 return 0;
5751}
5752
5753static struct hw_module_methods_t hal_module_methods = {
5754 .open = adev_open,
5755};
5756
5757struct audio_module HAL_MODULE_INFO_SYM = {
5758 .common = {
5759 .tag = HARDWARE_MODULE_TAG,
5760 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5761 .hal_api_version = HARDWARE_HAL_API_VERSION,
5762 .id = AUDIO_HARDWARE_MODULE_ID,
5763 .name = "QCOM Audio HAL",
5764 .author = "Code Aurora Forum",
5765 .methods = &hal_module_methods,
5766 },
5767};