blob: 7037b567d047a05345bd8c79dd4bb295ee6b254c [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
38#include <cutils/log.h>
Haynes Mathew George03c40102016-01-29 17:57:48 -080039#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040#include <cutils/str_parms.h>
41#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070042#include <cutils/atomic.h>
43#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080044
Eric Laurentb23d5282013-05-14 15:27:20 -070045#include <hardware/audio_effect.h>
Andy Hung31aca912014-03-20 17:14:59 -070046#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070047#include <system/thread_defs.h>
Phil Burkbc991042017-02-24 08:06:44 -080048#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070049#include <audio_effects/effect_aec.h>
50#include <audio_effects/effect_ns.h>
Andy Hungfc044e12017-03-20 09:24:22 -070051#include <audio_utils/clock.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052#include "audio_hw.h"
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -080053#include "audio_extn.h"
Wei Wangf4837d52017-11-21 14:51:20 -080054#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070055#include "platform_api.h"
56#include <platform.h>
Vineeta Srivastava4b89e372014-06-19 14:21:42 -070057#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080058
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070059#include "sound/compress_params.h"
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -080060#include "audio_extn/tfa_98xx.h"
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070061
Eric Laurent397db572016-05-11 11:31:47 -070062/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
63 * COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
Marco Nelissen32093f52015-04-08 15:14:02 -070064#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070065// 2 buffers causes problems with high bitrate files
66#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070067/* ToDo: Check and update a proper value in msec */
68#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
vivek mehta4a824772017-06-08 19:05:49 -070069/* treat as unsigned Q1.13 */
70#define APP_TYPE_GAIN_DEFAULT 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070071#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
vivek mehta4a824772017-06-08 19:05:49 -070072
73/* treat as unsigned Q1.13 */
vivek mehtaa68fea62017-06-08 19:04:02 -070074#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070075
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070076#define PROXY_OPEN_RETRY_COUNT 100
77#define PROXY_OPEN_WAIT_TIME 20
78
vivek mehtadae44712015-07-27 14:13:18 -070079#define MIN_CHANNEL_COUNT 1
80#define DEFAULT_CHANNEL_COUNT 2
81
Jean-Michel Trivic0750692015-10-12 12:12:32 -070082#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
83#define MAX_CHANNEL_COUNT 1
84#else
vivek mehtadae44712015-07-27 14:13:18 -070085#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
86#define XSTR(x) STR(x)
87#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070088#endif
Eric Laurent74b55762017-07-09 17:04:53 -070089#define MAX_HIFI_CHANNEL_COUNT 8
vivek mehtadae44712015-07-27 14:13:18 -070090
Haynes Mathew George03c40102016-01-29 17:57:48 -080091#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
92
Glenn Kasten4f993392014-05-14 07:30:48 -070093static unsigned int configured_low_latency_capture_period_size =
94 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
95
Eric Laurent0e46adf2016-12-16 12:49:24 -080096
97#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Phil Burkbc991042017-02-24 08:06:44 -080098#define MMAP_PERIOD_COUNT_MIN 32
99#define MMAP_PERIOD_COUNT_MAX 512
100#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
Eric Laurent0e46adf2016-12-16 12:49:24 -0800101
Andy Hungd13f0d32017-06-12 13:58:37 -0700102static const int64_t NANOS_PER_SECOND = 1000000000;
Eric Laurent0e46adf2016-12-16 12:49:24 -0800103
Andy Hung31aca912014-03-20 17:14:59 -0700104/* This constant enables extended precision handling.
105 * TODO The flag is off until more testing is done.
106 */
107static const bool k_enable_extended_precision = false;
108
Eric Laurentb23d5282013-05-14 15:27:20 -0700109struct pcm_config pcm_config_deep_buffer = {
vivek mehtadae44712015-07-27 14:13:18 -0700110 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700111 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
112 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
113 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
114 .format = PCM_FORMAT_S16_LE,
115 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
116 .stop_threshold = INT_MAX,
117 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
118};
119
120struct pcm_config pcm_config_low_latency = {
vivek mehtadae44712015-07-27 14:13:18 -0700121 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700122 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
123 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
124 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
125 .format = PCM_FORMAT_S16_LE,
126 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
127 .stop_threshold = INT_MAX,
128 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
129};
130
Haynes Mathew George03c40102016-01-29 17:57:48 -0800131static int af_period_multiplier = 4;
132struct pcm_config pcm_config_rt = {
133 .channels = DEFAULT_CHANNEL_COUNT,
134 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
135 .period_size = ULL_PERIOD_SIZE, //1 ms
136 .period_count = 512, //=> buffer size is 512ms
137 .format = PCM_FORMAT_S16_LE,
138 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
139 .stop_threshold = INT_MAX,
140 .silence_threshold = 0,
141 .silence_size = 0,
142 .avail_min = ULL_PERIOD_SIZE, //1 ms
143};
144
Eric Laurentb23d5282013-05-14 15:27:20 -0700145struct pcm_config pcm_config_hdmi_multi = {
146 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
147 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
148 .period_size = HDMI_MULTI_PERIOD_SIZE,
149 .period_count = HDMI_MULTI_PERIOD_COUNT,
150 .format = PCM_FORMAT_S16_LE,
151 .start_threshold = 0,
152 .stop_threshold = INT_MAX,
153 .avail_min = 0,
154};
155
Eric Laurent0e46adf2016-12-16 12:49:24 -0800156struct pcm_config pcm_config_mmap_playback = {
157 .channels = DEFAULT_CHANNEL_COUNT,
158 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
159 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800160 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800161 .format = PCM_FORMAT_S16_LE,
162 .start_threshold = MMAP_PERIOD_SIZE*8,
163 .stop_threshold = INT32_MAX,
164 .silence_threshold = 0,
165 .silence_size = 0,
166 .avail_min = MMAP_PERIOD_SIZE, //1 ms
167};
168
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800169struct pcm_config pcm_config_hifi = {
170 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
171 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
172 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
173 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
174 .format = PCM_FORMAT_S24_3LE,
175 .start_threshold = 0,
176 .stop_threshold = INT_MAX,
177 .avail_min = 0,
178};
179
Eric Laurentb23d5282013-05-14 15:27:20 -0700180struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700181 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700182 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
183 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700184 .stop_threshold = INT_MAX,
185 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700186};
187
Haynes Mathew George03c40102016-01-29 17:57:48 -0800188struct pcm_config pcm_config_audio_capture_rt = {
189 .channels = DEFAULT_CHANNEL_COUNT,
190 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
191 .period_size = ULL_PERIOD_SIZE,
192 .period_count = 512,
193 .format = PCM_FORMAT_S16_LE,
194 .start_threshold = 0,
195 .stop_threshold = INT_MAX,
196 .silence_threshold = 0,
197 .silence_size = 0,
198 .avail_min = ULL_PERIOD_SIZE, //1 ms
199};
200
Eric Laurent0e46adf2016-12-16 12:49:24 -0800201struct pcm_config pcm_config_mmap_capture = {
202 .channels = DEFAULT_CHANNEL_COUNT,
203 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
204 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800205 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800206 .format = PCM_FORMAT_S16_LE,
207 .start_threshold = 0,
208 .stop_threshold = INT_MAX,
209 .silence_threshold = 0,
210 .silence_size = 0,
211 .avail_min = MMAP_PERIOD_SIZE, //1 ms
212};
213
vivek mehtaa68fea62017-06-08 19:04:02 -0700214struct pcm_config pcm_config_voip = {
215 .channels = 1,
216 .period_count = 2,
217 .format = PCM_FORMAT_S16_LE,
218 .stop_threshold = INT_MAX,
219 .avail_min = 0,
220};
221
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700222#define AFE_PROXY_CHANNEL_COUNT 2
223#define AFE_PROXY_SAMPLING_RATE 48000
224
225#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
226#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
227
228struct pcm_config pcm_config_afe_proxy_playback = {
229 .channels = AFE_PROXY_CHANNEL_COUNT,
230 .rate = AFE_PROXY_SAMPLING_RATE,
231 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
232 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
233 .format = PCM_FORMAT_S16_LE,
234 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
235 .stop_threshold = INT_MAX,
236 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
237};
238
239#define AFE_PROXY_RECORD_PERIOD_SIZE 768
240#define AFE_PROXY_RECORD_PERIOD_COUNT 4
241
242struct pcm_config pcm_config_afe_proxy_record = {
243 .channels = AFE_PROXY_CHANNEL_COUNT,
244 .rate = AFE_PROXY_SAMPLING_RATE,
245 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
246 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
247 .format = PCM_FORMAT_S16_LE,
248 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
249 .stop_threshold = INT_MAX,
250 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
251};
252
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700253const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700254 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
255 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800256 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700257 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700258 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700259 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800260 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700261
Eric Laurentb23d5282013-05-14 15:27:20 -0700262 [USECASE_AUDIO_RECORD] = "audio-record",
263 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800264 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George569b7482017-05-08 14:44:27 -0700265 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700266
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800267 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
268 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700269
Eric Laurentb23d5282013-05-14 15:27:20 -0700270 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700271 [USECASE_VOICE2_CALL] = "voice2-call",
272 [USECASE_VOLTE_CALL] = "volte-call",
273 [USECASE_QCHAT_CALL] = "qchat-call",
274 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800275 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
276 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700277
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700278 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
279 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
280
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700281 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
282 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
vivek mehta781065c2017-04-04 12:55:01 -0700283
284 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
285 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
286 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
287
vivek mehtaa68fea62017-06-08 19:04:02 -0700288 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
289 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Nadav Bar3d72cfc2018-01-07 12:19:24 +0200290
291 [USECASE_INCALL_MUSIC_UPLINK] = "incall-music-uplink",
Eric Laurentb23d5282013-05-14 15:27:20 -0700292};
293
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800294
295#define STRING_TO_ENUM(string) { #string, string }
296
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800297struct string_to_enum {
298 const char *name;
299 uint32_t value;
300};
301
Haynes Mathew George569b7482017-05-08 14:44:27 -0700302static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800303 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
304 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
305 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Eric Laurent74b55762017-07-09 17:04:53 -0700306 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
Haynes Mathew George569b7482017-05-08 14:44:27 -0700307 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
Eric Laurent74b55762017-07-09 17:04:53 -0700308 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
309 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
310 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
311 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
312 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
313 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
314 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
315 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
316 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800317};
318
Haynes Mathew George5191a852013-09-11 14:19:36 -0700319static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700320static struct audio_device *adev = NULL;
Andy Hung9e737de2017-05-22 10:51:22 -0700321static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700322static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700323//cache last MBDRC cal step level
324static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700325
Haynes Mathew George03c40102016-01-29 17:57:48 -0800326static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
327 int flags __unused)
328{
329 int dir = 0;
330 switch (uc_id) {
331 case USECASE_AUDIO_RECORD_LOW_LATENCY:
332 dir = 1;
333 case USECASE_AUDIO_PLAYBACK_ULL:
334 break;
335 default:
336 return false;
337 }
338
339 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
340 PCM_PLAYBACK : PCM_CAPTURE);
341 if (adev->adm_is_noirq_avail)
342 return adev->adm_is_noirq_avail(adev->adm_data,
343 adev->snd_card, dev_id, dir);
344 return false;
345}
346
347static void register_out_stream(struct stream_out *out)
348{
349 struct audio_device *adev = out->dev;
350 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
351 return;
352
353 if (!adev->adm_register_output_stream)
354 return;
355
356 adev->adm_register_output_stream(adev->adm_data,
357 out->handle,
358 out->flags);
359
360 if (!adev->adm_set_config)
361 return;
362
363 if (out->realtime) {
364 adev->adm_set_config(adev->adm_data,
365 out->handle,
366 out->pcm, &out->config);
367 }
368}
369
370static void register_in_stream(struct stream_in *in)
371{
372 struct audio_device *adev = in->dev;
373 if (!adev->adm_register_input_stream)
374 return;
375
376 adev->adm_register_input_stream(adev->adm_data,
377 in->capture_handle,
378 in->flags);
379
380 if (!adev->adm_set_config)
381 return;
382
383 if (in->realtime) {
384 adev->adm_set_config(adev->adm_data,
385 in->capture_handle,
386 in->pcm,
387 &in->config);
388 }
389}
390
391static void request_out_focus(struct stream_out *out, long ns)
392{
393 struct audio_device *adev = out->dev;
394
Haynes Mathew George03c40102016-01-29 17:57:48 -0800395 if (adev->adm_request_focus_v2) {
396 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
397 } else if (adev->adm_request_focus) {
398 adev->adm_request_focus(adev->adm_data, out->handle);
399 }
400}
401
402static void request_in_focus(struct stream_in *in, long ns)
403{
404 struct audio_device *adev = in->dev;
405
Haynes Mathew George03c40102016-01-29 17:57:48 -0800406 if (adev->adm_request_focus_v2) {
407 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
408 } else if (adev->adm_request_focus) {
409 adev->adm_request_focus(adev->adm_data, in->capture_handle);
410 }
411}
412
413static void release_out_focus(struct stream_out *out, long ns __unused)
414{
415 struct audio_device *adev = out->dev;
416
417 if (adev->adm_abandon_focus)
418 adev->adm_abandon_focus(adev->adm_data, out->handle);
419}
420
421static void release_in_focus(struct stream_in *in, long ns __unused)
422{
423 struct audio_device *adev = in->dev;
424 if (adev->adm_abandon_focus)
425 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
426}
427
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700428static int parse_snd_card_status(struct str_parms * parms, int * card,
429 card_status_t * status)
430{
431 char value[32]={0};
432 char state[32]={0};
433
434 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
435
436 if (ret < 0)
437 return -1;
438
439 // sscanf should be okay as value is of max length 32.
440 // same as sizeof state.
441 if (sscanf(value, "%d,%s", card, state) < 2)
442 return -1;
443
444 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
445 CARD_STATUS_OFFLINE;
446 return 0;
447}
448
vivek mehta40125092017-08-21 18:48:51 -0700449// always call with adev lock held
450void send_gain_dep_calibration_l() {
451 if (last_known_cal_step >= 0)
452 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
453}
454
vivek mehta1a9b7c02015-06-25 11:49:38 -0700455__attribute__ ((visibility ("default")))
456bool audio_hw_send_gain_dep_calibration(int level) {
457 bool ret_val = false;
458 ALOGV("%s: enter ... ", __func__);
459
460 pthread_mutex_lock(&adev_init_lock);
461
462 if (adev != NULL && adev->platform != NULL) {
463 pthread_mutex_lock(&adev->lock);
vivek mehta40125092017-08-21 18:48:51 -0700464 last_known_cal_step = level;
465 send_gain_dep_calibration_l();
vivek mehta1a9b7c02015-06-25 11:49:38 -0700466 pthread_mutex_unlock(&adev->lock);
467 } else {
468 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
469 }
470
471 pthread_mutex_unlock(&adev_init_lock);
472
473 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
474 return ret_val;
475}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700476
vivek mehtaa8d7c922016-05-25 14:40:44 -0700477__attribute__ ((visibility ("default")))
478int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
479 int table_size) {
480 int ret_val = 0;
481 ALOGV("%s: enter ... ", __func__);
482
483 pthread_mutex_lock(&adev_init_lock);
484 if (adev == NULL) {
485 ALOGW("%s: adev is NULL .... ", __func__);
486 goto done;
487 }
488
489 pthread_mutex_lock(&adev->lock);
490 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
491 pthread_mutex_unlock(&adev->lock);
492done:
493 pthread_mutex_unlock(&adev_init_lock);
494 ALOGV("%s: exit ... ", __func__);
495 return ret_val;
496}
497
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700498static bool is_supported_format(audio_format_t format)
499{
Eric Laurent8251ac82014-07-23 11:00:25 -0700500 switch (format) {
501 case AUDIO_FORMAT_MP3:
502 case AUDIO_FORMAT_AAC_LC:
503 case AUDIO_FORMAT_AAC_HE_V1:
504 case AUDIO_FORMAT_AAC_HE_V2:
505 return true;
506 default:
507 break;
508 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700509 return false;
510}
511
Haynes Mathew George03c40102016-01-29 17:57:48 -0800512static inline bool is_mmap_usecase(audio_usecase_t uc_id)
513{
514 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
515 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
516}
517
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700518static int get_snd_codec_id(audio_format_t format)
519{
520 int id = 0;
521
Eric Laurent8251ac82014-07-23 11:00:25 -0700522 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700523 case AUDIO_FORMAT_MP3:
524 id = SND_AUDIOCODEC_MP3;
525 break;
526 case AUDIO_FORMAT_AAC:
527 id = SND_AUDIOCODEC_AAC;
528 break;
529 default:
530 ALOGE("%s: Unsupported audio format", __func__);
531 }
532
533 return id;
534}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800535
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800536static int audio_ssr_status(struct audio_device *adev)
537{
538 int ret = 0;
539 struct mixer_ctl *ctl;
540 const char *mixer_ctl_name = "Audio SSR Status";
541
542 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
543 ret = mixer_ctl_get_value(ctl, 0);
544 ALOGD("%s: value: %d", __func__, ret);
545 return ret;
546}
547
vivek mehta4a824772017-06-08 19:05:49 -0700548static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
549{
550 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
551}
552
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800553int enable_audio_route(struct audio_device *adev,
554 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800555{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700556 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800557 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800558
559 if (usecase == NULL)
560 return -EINVAL;
561
562 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
563
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800564 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700565 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800566 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700567 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800568
Yamit Mehtae3b99562016-09-16 22:44:00 +0530569 audio_extn_utils_send_app_type_cfg(adev, usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800570 audio_extn_utils_send_audio_calibration(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800571 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500572 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700573 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700574 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800575
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800576 ALOGV("%s: exit", __func__);
577 return 0;
578}
579
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800580int disable_audio_route(struct audio_device *adev,
581 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800582{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700583 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800584 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800585
586 if (usecase == NULL)
587 return -EINVAL;
588
589 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700590 if (usecase->type == PCM_CAPTURE)
591 snd_device = usecase->in_snd_device;
592 else
593 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800594 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500595 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700596 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700597 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800598
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800599 ALOGV("%s: exit", __func__);
600 return 0;
601}
602
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800603int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700604 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800605{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700606 int i, num_devices = 0;
607 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800608 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800609 if (snd_device < SND_DEVICE_MIN ||
610 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800611 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800612 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800613 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700614
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700615 platform_send_audio_calibration(adev->platform, snd_device);
616
vivek mehtade4849c2016-03-03 17:23:38 -0800617 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700618 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700619 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800620 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700621 }
622
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700623 /* due to the possibility of calibration overwrite between listen
624 and audio, notify sound trigger hal before audio calibration is sent */
625 audio_extn_sound_trigger_update_device_status(snd_device,
626 ST_EVENT_SND_DEVICE_BUSY);
627
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700628 if (audio_extn_spkr_prot_is_enabled())
629 audio_extn_spkr_prot_calib_cancel(adev);
630
zhaoyang yin4211fad2015-06-04 21:13:25 +0800631 audio_extn_dsm_feedback_enable(adev, snd_device, true);
632
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700633 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800634 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700635 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
636 audio_extn_spkr_prot_is_enabled()) {
637 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800638 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700639 }
640 if (audio_extn_spkr_prot_start_processing(snd_device)) {
641 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800642 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700643 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700644 } else if (platform_can_split_snd_device(snd_device,
645 &num_devices,
646 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700647 for (i = 0; i < num_devices; i++) {
648 enable_snd_device(adev, new_snd_devices[i]);
649 }
vivek mehtab6506412015-08-07 16:55:17 -0700650 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700651 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800652 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
653 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
654 ALOGE(" %s: Invalid sound device returned", __func__);
655 goto on_error;
656 }
Ed Tam70b5c142016-03-21 19:14:29 -0700657
Eric Laurent2e140aa2016-06-30 17:14:46 -0700658 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800659 audio_route_apply_and_update_path(adev->audio_route, device_name);
660 }
661on_success:
662 adev->snd_dev_ref_cnt[snd_device]++;
663 ret_val = 0;
664on_error:
665 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800666}
667
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800668int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700669 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800670{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700671 int i, num_devices = 0;
672 snd_device_t new_snd_devices[2];
673
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800674 if (snd_device < SND_DEVICE_MIN ||
675 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800676 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800677 return -EINVAL;
678 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700679 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
680 ALOGE("%s: device ref cnt is already 0", __func__);
681 return -EINVAL;
682 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800683 audio_extn_tfa_98xx_disable_speaker(snd_device);
684
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700685 adev->snd_dev_ref_cnt[snd_device]--;
686 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800687 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700688 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800689 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700690 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700691 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
692 audio_extn_spkr_prot_is_enabled()) {
693 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700694
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700695 // FIXME b/65363602: bullhead is the only Nexus with audio_extn_spkr_prot_is_enabled()
696 // and does not use speaker swap. As this code causes a problem with device enable ref
697 // counting we remove it for now.
vivek mehtae59cfb22017-06-16 15:57:11 -0700698 // when speaker device is disabled, reset swap.
699 // will be renabled on usecase start
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700700 // platform_set_swap_channels(adev, false);
vivek mehtae59cfb22017-06-16 15:57:11 -0700701
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700702 } else if (platform_can_split_snd_device(snd_device,
703 &num_devices,
704 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700705 for (i = 0; i < num_devices; i++) {
706 disable_snd_device(adev, new_snd_devices[i]);
707 }
vivek mehtab6506412015-08-07 16:55:17 -0700708 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700709 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800710 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
711 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
712 ALOGE(" %s: Invalid sound device returned", __func__);
713 return -EINVAL;
714 }
715
Eric Laurent2e140aa2016-06-30 17:14:46 -0700716 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800717 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700718 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700719 audio_extn_sound_trigger_update_device_status(snd_device,
720 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700721 }
vivek mehtab6506412015-08-07 16:55:17 -0700722
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800723 return 0;
724}
725
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700726/*
727 legend:
728 uc - existing usecase
729 new_uc - new usecase
730 d1, d11, d2 - SND_DEVICE enums
731 a1, a2 - corresponding ANDROID device enums
732 B, B1, B2 - backend strings
733
734case 1
735 uc->dev d1 (a1) B1
736 new_uc->dev d1 (a1), d2 (a2) B1, B2
737
738 resolution: disable and enable uc->dev on d1
739
740case 2
741 uc->dev d1 (a1) B1
742 new_uc->dev d11 (a1) B1
743
744 resolution: need to switch uc since d1 and d11 are related
745 (e.g. speaker and voice-speaker)
746 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
747
748case 3
749 uc->dev d1 (a1) B1
750 new_uc->dev d2 (a2) B2
751
752 resolution: no need to switch uc
753
754case 4
755 uc->dev d1 (a1) B
756 new_uc->dev d2 (a2) B
757
758 resolution: disable enable uc-dev on d2 since backends match
759 we cannot enable two streams on two different devices if they
760 share the same backend. e.g. if offload is on speaker device using
761 QUAD_MI2S backend and a low-latency stream is started on voice-handset
762 using the same backend, offload must also be switched to voice-handset.
763
764case 5
765 uc->dev d1 (a1) B
766 new_uc->dev d1 (a1), d2 (a2) B
767
768 resolution: disable enable uc-dev on d2 since backends match
769 we cannot enable two streams on two different devices if they
770 share the same backend.
771
772case 6
773 uc->dev d1 a1 B1
774 new_uc->dev d2 a1 B2
775
776 resolution: no need to switch
777
778case 7
779
780 uc->dev d1 (a1), d2 (a2) B1, B2
781 new_uc->dev d1 B1
782
783 resolution: no need to switch
784
785*/
786static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
787 struct audio_usecase *new_uc,
788 snd_device_t new_snd_device)
789{
790 audio_devices_t a1 = uc->stream.out->devices;
791 audio_devices_t a2 = new_uc->stream.out->devices;
792
793 snd_device_t d1 = uc->out_snd_device;
794 snd_device_t d2 = new_snd_device;
795
796 // Treat as a special case when a1 and a2 are not disjoint
797 if ((a1 != a2) && (a1 & a2)) {
798 snd_device_t d3[2];
799 int num_devices = 0;
800 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
801 &num_devices,
802 d3);
803 if (ret < 0) {
804 if (ret != -ENOSYS) {
805 ALOGW("%s failed to split snd_device %d",
806 __func__,
807 popcount(a1) > 1 ? d1 : d2);
808 }
809 goto end;
810 }
811
812 // NB: case 7 is hypothetical and isn't a practical usecase yet.
813 // But if it does happen, we need to give priority to d2 if
814 // the combo devices active on the existing usecase share a backend.
815 // This is because we cannot have a usecase active on a combo device
816 // and a new usecase requests one device in this combo pair.
817 if (platform_check_backends_match(d3[0], d3[1])) {
818 return d2; // case 5
819 } else {
820 return d1; // case 1
821 }
822 } else {
823 if (platform_check_backends_match(d1, d2)) {
824 return d2; // case 2, 4
825 } else {
826 return d1; // case 6, 3
827 }
828 }
829
830end:
831 return d2; // return whatever was calculated before.
832}
833
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700834static void check_and_route_playback_usecases(struct audio_device *adev,
835 struct audio_usecase *uc_info,
836 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700837{
838 struct listnode *node;
839 struct audio_usecase *usecase;
840 bool switch_device[AUDIO_USECASE_MAX];
841 int i, num_uc_to_switch = 0;
842
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700843 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
844 uc_info,
845 snd_device);
David Linee3fe402017-03-13 10:00:42 -0700846
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700847 /*
848 * This function is to make sure that all the usecases that are active on
849 * the hardware codec backend are always routed to any one device that is
850 * handled by the hardware codec.
851 * For example, if low-latency and deep-buffer usecases are currently active
852 * on speaker and out_set_parameters(headset) is received on low-latency
853 * output, then we have to make sure deep-buffer is also switched to headset,
854 * because of the limitation that both the devices cannot be enabled
855 * at the same time as they share the same backend.
856 */
857 /* Disable all the usecases on the shared backend other than the
858 specified usecase */
859 for (i = 0; i < AUDIO_USECASE_MAX; i++)
860 switch_device[i] = false;
861
862 list_for_each(node, &adev->usecase_list) {
863 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700864 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
865 continue;
866
867 if (force_routing ||
868 (usecase->out_snd_device != snd_device &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -0700869 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
870 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700871 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700872 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
873 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700874 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700875 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700876 switch_device[usecase->id] = true;
877 num_uc_to_switch++;
878 }
879 }
880
881 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700882 list_for_each(node, &adev->usecase_list) {
883 usecase = node_to_item(node, struct audio_usecase, list);
884 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700885 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900886 }
887 }
888
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700889 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900890 list_for_each(node, &adev->usecase_list) {
891 usecase = node_to_item(node, struct audio_usecase, list);
892 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700893 d_device = derive_playback_snd_device(usecase, uc_info,
894 snd_device);
895 enable_snd_device(adev, d_device);
896 /* Update the out_snd_device before enabling the audio route */
897 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700898 }
899 }
900
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700901 /* Re-route all the usecases on the shared backend other than the
902 specified usecase to new snd devices */
903 list_for_each(node, &adev->usecase_list) {
904 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700905 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700906 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700907 }
908 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700909 }
910}
911
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700912static void check_and_route_capture_usecases(struct audio_device *adev,
913 struct audio_usecase *uc_info,
914 snd_device_t snd_device)
915{
916 struct listnode *node;
917 struct audio_usecase *usecase;
918 bool switch_device[AUDIO_USECASE_MAX];
919 int i, num_uc_to_switch = 0;
920
vivek mehta4ed66e62016-04-15 23:33:34 -0700921 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
922
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700923 /*
924 * This function is to make sure that all the active capture usecases
925 * are always routed to the same input sound device.
926 * For example, if audio-record and voice-call usecases are currently
927 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
928 * is received for voice call then we have to make sure that audio-record
929 * usecase is also switched to earpiece i.e. voice-dmic-ef,
930 * because of the limitation that two devices cannot be enabled
931 * at the same time if they share the same backend.
932 */
933 for (i = 0; i < AUDIO_USECASE_MAX; i++)
934 switch_device[i] = false;
935
936 list_for_each(node, &adev->usecase_list) {
937 usecase = node_to_item(node, struct audio_usecase, list);
938 if (usecase->type != PCM_PLAYBACK &&
939 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700940 usecase->in_snd_device != snd_device &&
941 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700942 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
943 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700944 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700945 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700946 switch_device[usecase->id] = true;
947 num_uc_to_switch++;
948 }
949 }
950
951 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700952 list_for_each(node, &adev->usecase_list) {
953 usecase = node_to_item(node, struct audio_usecase, list);
954 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700955 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700956 }
957 }
958
959 list_for_each(node, &adev->usecase_list) {
960 usecase = node_to_item(node, struct audio_usecase, list);
961 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700962 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700963 }
964 }
965
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700966 /* Re-route all the usecases on the shared backend other than the
967 specified usecase to new snd devices */
968 list_for_each(node, &adev->usecase_list) {
969 usecase = node_to_item(node, struct audio_usecase, list);
970 /* Update the in_snd_device only before enabling the audio route */
971 if (switch_device[usecase->id] ) {
972 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700973 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700974 }
975 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700976 }
977}
978
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800979/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700980static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800981{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700982 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700983 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800984
985 switch (channels) {
986 /*
987 * Do not handle stereo output in Multi-channel cases
988 * Stereo case is handled in normal playback path
989 */
990 case 6:
991 ALOGV("%s: HDMI supports 5.1", __func__);
992 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
993 break;
994 case 8:
995 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
996 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
997 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
998 break;
999 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001000 ALOGE("HDMI does not support multi channel playback");
1001 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001002 break;
1003 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001004 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001005}
1006
Andy Hung18859412017-08-09 11:47:21 -07001007static ssize_t read_usb_sup_sample_rates(bool is_playback,
1008 uint32_t *supported_sample_rates,
1009 uint32_t max_rates)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001010{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001011 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1012 supported_sample_rates,
1013 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001014#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001015 for (ssize_t i=0; i<count; i++) {
1016 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1017 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001018 }
1019#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001020 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001021}
1022
Haynes Mathew George569b7482017-05-08 14:44:27 -07001023static int read_usb_sup_channel_masks(bool is_playback,
1024 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001025 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001026{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001027 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001028 int channel_count;
1029 uint32_t num_masks = 0;
1030 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1031 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001032 }
Eric Laurent74b55762017-07-09 17:04:53 -07001033 if (is_playback) {
Andy Hung6c1afb12017-12-22 11:34:41 -08001034 // start from 2 channels as framework currently doesn't support mono.
1035 // TODO: consider only supporting channel index masks beyond stereo here.
1036 for (channel_count = FCC_2;
1037 channel_count <= channels && num_masks < max_masks;
1038 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001039 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1040 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001041 for (channel_count = FCC_2;
1042 channel_count <= channels && num_masks < max_masks;
1043 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001044 supported_channel_masks[num_masks++] =
1045 audio_channel_mask_for_index_assignment_from_count(channel_count);
1046 }
1047 } else {
1048 // For capture we report all supported channel masks from 1 channel up.
1049 channel_count = MIN_CHANNEL_COUNT;
1050 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1051 // indexed mask
1052 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1053 supported_channel_masks[num_masks++] =
1054 audio_channel_in_mask_from_count(channel_count);
1055 }
1056 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001057#ifdef NDEBUG
1058 for (size_t i = 0; i < num_masks; ++i) {
1059 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1060 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
1061 }
1062#endif
Eric Laurent74b55762017-07-09 17:04:53 -07001063 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001064}
1065
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001066static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001067 audio_format_t *supported_formats,
1068 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001069{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001070 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001071 switch (bitwidth) {
1072 case 24:
1073 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001074 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001075 break;
1076 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001077 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001078 break;
1079 case 16:
1080 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001081 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001082 break;
1083 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001084 ALOGV("%s: %s supported format %d", __func__,
1085 is_playback ? "P" : "C", bitwidth);
1086 return 1;
1087}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001088
Haynes Mathew George569b7482017-05-08 14:44:27 -07001089static int read_usb_sup_params_and_compare(bool is_playback,
1090 audio_format_t *format,
1091 audio_format_t *supported_formats,
1092 uint32_t max_formats,
1093 audio_channel_mask_t *mask,
1094 audio_channel_mask_t *supported_channel_masks,
1095 uint32_t max_masks,
1096 uint32_t *rate,
1097 uint32_t *supported_sample_rates,
1098 uint32_t max_rates) {
1099 int ret = 0;
1100 int num_formats;
1101 int num_masks;
1102 int num_rates;
1103 int i;
1104
1105 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1106 max_formats);
1107 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1108 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001109
Haynes Mathew George569b7482017-05-08 14:44:27 -07001110 num_rates = read_usb_sup_sample_rates(is_playback,
1111 supported_sample_rates, max_rates);
1112
1113#define LUT(table, len, what, dflt) \
1114 for (i=0; i<len && (table[i] != what); i++); \
1115 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1116
1117 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1118 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1119 LUT(supported_sample_rates, num_rates, *rate, 0);
1120
1121#undef LUT
1122 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001123}
1124
Andy Hungd9653bd2017-08-01 19:31:39 -07001125static bool is_usb_ready(struct audio_device *adev, bool is_playback)
1126{
1127 // Check if usb is ready.
1128 // The usb device may have been removed quickly after insertion and hence
1129 // no longer available. This will show up as empty channel masks, or rates.
1130
1131 pthread_mutex_lock(&adev->lock);
1132 uint32_t supported_sample_rate;
1133
1134 // we consider usb ready if we can fetch at least one sample rate.
1135 const bool ready = read_usb_sup_sample_rates(
1136 is_playback, &supported_sample_rate, 1 /* max_rates */) > 0;
1137 pthread_mutex_unlock(&adev->lock);
1138 return ready;
1139}
1140
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001141static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1142{
1143 struct audio_usecase *usecase;
1144 struct listnode *node;
1145
1146 list_for_each(node, &adev->usecase_list) {
1147 usecase = node_to_item(node, struct audio_usecase, list);
1148 if (usecase->type == VOICE_CALL) {
1149 ALOGV("%s: usecase id %d", __func__, usecase->id);
1150 return usecase->id;
1151 }
1152 }
1153 return USECASE_INVALID;
1154}
1155
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001156struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1157 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001158{
1159 struct audio_usecase *usecase;
1160 struct listnode *node;
1161
1162 list_for_each(node, &adev->usecase_list) {
1163 usecase = node_to_item(node, struct audio_usecase, list);
1164 if (usecase->id == uc_id)
1165 return usecase;
1166 }
1167 return NULL;
1168}
1169
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001170int select_devices(struct audio_device *adev,
1171 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001172{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001173 snd_device_t out_snd_device = SND_DEVICE_NONE;
1174 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001175 struct audio_usecase *usecase = NULL;
1176 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001177 struct audio_usecase *hfp_usecase = NULL;
1178 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001179 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001180 int status = 0;
Eric Laurentf4520b02017-09-20 18:31:58 -07001181 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1182 USECASE_AUDIO_PLAYBACK_VOIP);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001183
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001184 usecase = get_usecase_from_list(adev, uc_id);
1185 if (usecase == NULL) {
1186 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1187 return -EINVAL;
1188 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001189
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001190 if ((usecase->type == VOICE_CALL) ||
1191 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001192 out_snd_device = platform_get_output_snd_device(adev->platform,
1193 usecase->stream.out->devices);
1194 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001195 usecase->devices = usecase->stream.out->devices;
1196 } else {
1197 /*
1198 * If the voice call is active, use the sound devices of voice call usecase
1199 * so that it would not result any device switch. All the usecases will
1200 * be switched to new device when select_devices() is called for voice call
1201 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001202 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001203 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001204 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001205 vc_usecase = get_usecase_from_list(adev,
1206 get_voice_usecase_id_from_list(adev));
1207 if ((vc_usecase != NULL) &&
1208 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1209 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001210 in_snd_device = vc_usecase->in_snd_device;
1211 out_snd_device = vc_usecase->out_snd_device;
1212 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001213 } else if (audio_extn_hfp_is_active(adev)) {
1214 hfp_ucid = audio_extn_hfp_get_usecase();
1215 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1216 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1217 in_snd_device = hfp_usecase->in_snd_device;
1218 out_snd_device = hfp_usecase->out_snd_device;
1219 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001220 }
1221 if (usecase->type == PCM_PLAYBACK) {
1222 usecase->devices = usecase->stream.out->devices;
1223 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001224 if (out_snd_device == SND_DEVICE_NONE) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001225 struct stream_out *voip_out = adev->primary_output;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001226
Eric Laurentb23d5282013-05-14 15:27:20 -07001227 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001228 usecase->stream.out->devices);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001229
1230 if (voip_usecase)
1231 voip_out = voip_usecase->stream.out;
1232
1233 if (usecase->stream.out == voip_out &&
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001234 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001235 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001236 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001237 select_devices(adev, adev->active_input->usecase);
1238 }
1239 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001240 } else if (usecase->type == PCM_CAPTURE) {
1241 usecase->devices = usecase->stream.in->device;
1242 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001243 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001244 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001245 if (adev->active_input &&
1246 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1247 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001248
1249 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1250 USECASE_AUDIO_PLAYBACK_VOIP);
1251
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001252 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001253 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1254 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001255 } else if (voip_usecase) {
1256 out_device = voip_usecase->stream.out->devices;
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001257 } else if (adev->primary_output) {
1258 out_device = adev->primary_output->devices;
1259 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001260 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001261 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001262 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001263 }
1264 }
1265
1266 if (out_snd_device == usecase->out_snd_device &&
1267 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001268 return 0;
1269 }
1270
Eric Laurent2bafff12016-03-17 12:17:23 -07001271 if (out_snd_device != SND_DEVICE_NONE &&
1272 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1273 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1274 __func__,
1275 use_case_table[uc_id],
1276 adev->last_logged_snd_device[uc_id][0],
1277 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1278 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1279 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1280 -1,
1281 out_snd_device,
1282 platform_get_snd_device_name(out_snd_device),
1283 platform_get_snd_device_acdb_id(out_snd_device));
1284 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1285 }
1286 if (in_snd_device != SND_DEVICE_NONE &&
1287 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1288 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1289 __func__,
1290 use_case_table[uc_id],
1291 adev->last_logged_snd_device[uc_id][1],
1292 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1293 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1294 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1295 -1,
1296 in_snd_device,
1297 platform_get_snd_device_name(in_snd_device),
1298 platform_get_snd_device_acdb_id(in_snd_device));
1299 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1300 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001301
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001302 /*
1303 * Limitation: While in call, to do a device switch we need to disable
1304 * and enable both RX and TX devices though one of them is same as current
1305 * device.
1306 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001307 if ((usecase->type == VOICE_CALL) &&
1308 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1309 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001310 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001311 /* Disable sidetone only if voice call already exists */
1312 if (voice_is_call_state_active(adev))
1313 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001314 }
1315
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001316 /* Disable current sound devices */
1317 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001318 disable_audio_route(adev, usecase);
1319 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001320 }
1321
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001322 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001323 disable_audio_route(adev, usecase);
1324 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001325 }
1326
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001327 /* Applicable only on the targets that has external modem.
1328 * New device information should be sent to modem before enabling
1329 * the devices to reduce in-call device switch time.
1330 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001331 if ((usecase->type == VOICE_CALL) &&
1332 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1333 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001334 status = platform_switch_voice_call_enable_device_config(adev->platform,
1335 out_snd_device,
1336 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001337 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001338
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001339 /* Enable new sound devices */
1340 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001341 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Eric Laurent99dab492017-06-17 15:19:08 -07001342 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001343 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001344 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001345 }
1346
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001347 if (in_snd_device != SND_DEVICE_NONE) {
1348 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001349 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001350 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001351
Eric Laurentb23d5282013-05-14 15:27:20 -07001352 if (usecase->type == VOICE_CALL)
1353 status = platform_switch_voice_call_device_post(adev->platform,
1354 out_snd_device,
1355 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001356
sangwoo170731f2013-06-08 15:36:36 +09001357 usecase->in_snd_device = in_snd_device;
1358 usecase->out_snd_device = out_snd_device;
1359
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001360 audio_extn_tfa_98xx_set_mode();
1361
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001362 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001363
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001364 /* Applicable only on the targets that has external modem.
1365 * Enable device command should be sent to modem only after
1366 * enabling voice call mixer controls
1367 */
vivek mehta765eb642015-08-07 19:46:06 -07001368 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001369 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1370 out_snd_device,
1371 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001372 /* Enable sidetone only if voice call already exists */
1373 if (voice_is_call_state_active(adev))
1374 voice_set_sidetone(adev, out_snd_device, true);
1375 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001376
Eric Laurentf4520b02017-09-20 18:31:58 -07001377 if (usecase == voip_usecase) {
1378 struct stream_out *voip_out = voip_usecase->stream.out;
1379 audio_extn_utils_send_app_type_gain(adev,
1380 voip_out->app_type_cfg.app_type,
1381 &voip_out->app_type_cfg.gain[0]);
1382 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001383 return status;
1384}
1385
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001386static int stop_input_stream(struct stream_in *in)
1387{
1388 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001389 struct audio_usecase *uc_info;
1390 struct audio_device *adev = in->dev;
1391
Eric Laurent994a6932013-07-17 11:51:42 -07001392 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001393 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001394
1395 if (adev->active_input) {
1396 if (adev->active_input->usecase == in->usecase) {
1397 adev->active_input = NULL;
1398 } else {
1399 ALOGW("%s adev->active_input->usecase %s, v/s in->usecase %s",
1400 __func__,
1401 use_case_table[adev->active_input->usecase],
1402 use_case_table[in->usecase]);
1403 }
1404 }
1405
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001406 uc_info = get_usecase_from_list(adev, in->usecase);
1407 if (uc_info == NULL) {
1408 ALOGE("%s: Could not find the usecase (%d) in the list",
1409 __func__, in->usecase);
1410 return -EINVAL;
1411 }
1412
vivek mehta781065c2017-04-04 12:55:01 -07001413 /* Close in-call recording streams */
1414 voice_check_and_stop_incall_rec_usecase(adev, in);
1415
Eric Laurent150dbfe2013-02-27 14:31:02 -08001416 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001417 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001418
1419 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001420 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001421
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001422 list_remove(&uc_info->list);
1423 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001424
Eric Laurent994a6932013-07-17 11:51:42 -07001425 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001426 return ret;
1427}
1428
1429int start_input_stream(struct stream_in *in)
1430{
1431 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001432 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001433 struct audio_usecase *uc_info;
1434 struct audio_device *adev = in->dev;
1435
Eric Laurent994a6932013-07-17 11:51:42 -07001436 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001437
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001438 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1439 return -EIO;
1440
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001441 if (in->card_status == CARD_STATUS_OFFLINE ||
1442 adev->card_status == CARD_STATUS_OFFLINE) {
1443 ALOGW("in->card_status or adev->card_status offline, try again");
1444 ret = -EAGAIN;
1445 goto error_config;
1446 }
1447
vivek mehta781065c2017-04-04 12:55:01 -07001448 /* Check if source matches incall recording usecase criteria */
1449 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1450 if (ret)
1451 goto error_config;
1452 else
1453 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1454
Eric Laurentb23d5282013-05-14 15:27:20 -07001455 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001456 if (in->pcm_device_id < 0) {
1457 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1458 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001459 ret = -EINVAL;
1460 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001461 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001462
1463 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001464 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1465 uc_info->id = in->usecase;
1466 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001467 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001468 uc_info->devices = in->device;
1469 uc_info->in_snd_device = SND_DEVICE_NONE;
1470 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001471
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001472 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001473
Wei Wangf4837d52017-11-21 14:51:20 -08001474 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001475 audio_extn_perf_lock_acquire();
1476
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001477 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001478
Eric Laurent0e46adf2016-12-16 12:49:24 -08001479 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001480 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001481 ALOGE("%s: pcm stream not ready", __func__);
1482 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001483 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001484 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001485 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001486 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1487 goto error_open;
1488 }
1489 } else {
1490 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1491 unsigned int pcm_open_retry_count = 0;
1492
1493 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1494 flags |= PCM_MMAP | PCM_NOIRQ;
1495 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1496 } else if (in->realtime) {
1497 flags |= PCM_MMAP | PCM_NOIRQ;
1498 }
1499
1500 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1501 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1502
1503 while (1) {
1504 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1505 flags, &in->config);
1506 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1507 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1508 if (in->pcm != NULL) {
1509 pcm_close(in->pcm);
1510 in->pcm = NULL;
1511 }
1512 if (pcm_open_retry_count-- == 0) {
1513 ret = -EIO;
1514 goto error_open;
1515 }
1516 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1517 continue;
1518 }
1519 break;
1520 }
1521
1522 ALOGV("%s: pcm_prepare", __func__);
1523 ret = pcm_prepare(in->pcm);
1524 if (ret < 0) {
1525 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001526 pcm_close(in->pcm);
1527 in->pcm = NULL;
1528 goto error_open;
1529 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001530 if (in->realtime) {
1531 ret = pcm_start(in->pcm);
1532 if (ret < 0) {
1533 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1534 pcm_close(in->pcm);
1535 in->pcm = NULL;
1536 goto error_open;
1537 }
1538 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001539 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001540 register_in_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001541 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001542 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001543 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001544
Eric Laurent0e46adf2016-12-16 12:49:24 -08001545 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001546
1547error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001548 stop_input_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001549 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001550 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001551
1552error_config:
1553 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001554 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001555 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001556}
1557
Eric Laurenta1478072015-09-21 17:21:52 -07001558void lock_input_stream(struct stream_in *in)
1559{
1560 pthread_mutex_lock(&in->pre_lock);
1561 pthread_mutex_lock(&in->lock);
1562 pthread_mutex_unlock(&in->pre_lock);
1563}
1564
1565void lock_output_stream(struct stream_out *out)
1566{
1567 pthread_mutex_lock(&out->pre_lock);
1568 pthread_mutex_lock(&out->lock);
1569 pthread_mutex_unlock(&out->pre_lock);
1570}
1571
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001572/* must be called with out->lock locked */
1573static int send_offload_cmd_l(struct stream_out* out, int command)
1574{
1575 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1576
1577 ALOGVV("%s %d", __func__, command);
1578
1579 cmd->cmd = command;
1580 list_add_tail(&out->offload_cmd_list, &cmd->node);
1581 pthread_cond_signal(&out->offload_cond);
1582 return 0;
1583}
1584
1585/* must be called iwth out->lock locked */
1586static void stop_compressed_output_l(struct stream_out *out)
1587{
1588 out->offload_state = OFFLOAD_STATE_IDLE;
1589 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001590 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001591 if (out->compr != NULL) {
1592 compress_stop(out->compr);
1593 while (out->offload_thread_blocked) {
1594 pthread_cond_wait(&out->cond, &out->lock);
1595 }
1596 }
1597}
1598
1599static void *offload_thread_loop(void *context)
1600{
1601 struct stream_out *out = (struct stream_out *) context;
1602 struct listnode *item;
1603
1604 out->offload_state = OFFLOAD_STATE_IDLE;
1605 out->playback_started = 0;
1606
1607 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1608 set_sched_policy(0, SP_FOREGROUND);
1609 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1610
1611 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001612 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001613 for (;;) {
1614 struct offload_cmd *cmd = NULL;
1615 stream_callback_event_t event;
1616 bool send_callback = false;
1617
1618 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1619 __func__, list_empty(&out->offload_cmd_list),
1620 out->offload_state);
1621 if (list_empty(&out->offload_cmd_list)) {
1622 ALOGV("%s SLEEPING", __func__);
1623 pthread_cond_wait(&out->offload_cond, &out->lock);
1624 ALOGV("%s RUNNING", __func__);
1625 continue;
1626 }
1627
1628 item = list_head(&out->offload_cmd_list);
1629 cmd = node_to_item(item, struct offload_cmd, node);
1630 list_remove(item);
1631
1632 ALOGVV("%s STATE %d CMD %d out->compr %p",
1633 __func__, out->offload_state, cmd->cmd, out->compr);
1634
1635 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1636 free(cmd);
1637 break;
1638 }
1639
1640 if (out->compr == NULL) {
1641 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001642 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001643 pthread_cond_signal(&out->cond);
1644 continue;
1645 }
1646 out->offload_thread_blocked = true;
1647 pthread_mutex_unlock(&out->lock);
1648 send_callback = false;
1649 switch(cmd->cmd) {
1650 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1651 compress_wait(out->compr, -1);
1652 send_callback = true;
1653 event = STREAM_CBK_EVENT_WRITE_READY;
1654 break;
1655 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001656 compress_next_track(out->compr);
1657 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001658 send_callback = true;
1659 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001660 /* Resend the metadata for next iteration */
1661 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001662 break;
1663 case OFFLOAD_CMD_DRAIN:
1664 compress_drain(out->compr);
1665 send_callback = true;
1666 event = STREAM_CBK_EVENT_DRAIN_READY;
1667 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001668 case OFFLOAD_CMD_ERROR:
1669 send_callback = true;
1670 event = STREAM_CBK_EVENT_ERROR;
1671 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001672 default:
1673 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1674 break;
1675 }
Eric Laurenta1478072015-09-21 17:21:52 -07001676 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001677 out->offload_thread_blocked = false;
1678 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001679 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001680 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001681 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001682 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001683 free(cmd);
1684 }
1685
1686 pthread_cond_signal(&out->cond);
1687 while (!list_empty(&out->offload_cmd_list)) {
1688 item = list_head(&out->offload_cmd_list);
1689 list_remove(item);
1690 free(node_to_item(item, struct offload_cmd, node));
1691 }
1692 pthread_mutex_unlock(&out->lock);
1693
1694 return NULL;
1695}
1696
1697static int create_offload_callback_thread(struct stream_out *out)
1698{
1699 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1700 list_init(&out->offload_cmd_list);
1701 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1702 offload_thread_loop, out);
1703 return 0;
1704}
1705
1706static int destroy_offload_callback_thread(struct stream_out *out)
1707{
Eric Laurenta1478072015-09-21 17:21:52 -07001708 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001709 stop_compressed_output_l(out);
1710 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1711
1712 pthread_mutex_unlock(&out->lock);
1713 pthread_join(out->offload_thread, (void **) NULL);
1714 pthread_cond_destroy(&out->offload_cond);
1715
1716 return 0;
1717}
1718
Eric Laurent07eeafd2013-10-06 12:52:49 -07001719static bool allow_hdmi_channel_config(struct audio_device *adev)
1720{
1721 struct listnode *node;
1722 struct audio_usecase *usecase;
1723 bool ret = true;
1724
1725 list_for_each(node, &adev->usecase_list) {
1726 usecase = node_to_item(node, struct audio_usecase, list);
1727 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1728 /*
1729 * If voice call is already existing, do not proceed further to avoid
1730 * disabling/enabling both RX and TX devices, CSD calls, etc.
1731 * Once the voice call done, the HDMI channels can be configured to
1732 * max channels of remaining use cases.
1733 */
1734 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001735 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001736 __func__);
1737 ret = false;
1738 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001739 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1740 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001741 "no change in HDMI channels", __func__);
1742 ret = false;
1743 break;
1744 }
1745 }
1746 }
1747 return ret;
1748}
1749
1750static int check_and_set_hdmi_channels(struct audio_device *adev,
1751 unsigned int channels)
1752{
1753 struct listnode *node;
1754 struct audio_usecase *usecase;
1755
1756 /* Check if change in HDMI channel config is allowed */
1757 if (!allow_hdmi_channel_config(adev))
1758 return 0;
1759
1760 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001761 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001762 return 0;
1763 }
1764
1765 platform_set_hdmi_channels(adev->platform, channels);
1766 adev->cur_hdmi_channels = channels;
1767
1768 /*
1769 * Deroute all the playback streams routed to HDMI so that
1770 * the back end is deactivated. Note that backend will not
1771 * be deactivated if any one stream is connected to it.
1772 */
1773 list_for_each(node, &adev->usecase_list) {
1774 usecase = node_to_item(node, struct audio_usecase, list);
1775 if (usecase->type == PCM_PLAYBACK &&
1776 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001777 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001778 }
1779 }
1780
1781 /*
1782 * Enable all the streams disabled above. Now the HDMI backend
1783 * will be activated with new channel configuration
1784 */
1785 list_for_each(node, &adev->usecase_list) {
1786 usecase = node_to_item(node, struct audio_usecase, list);
1787 if (usecase->type == PCM_PLAYBACK &&
1788 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001789 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001790 }
1791 }
1792
1793 return 0;
1794}
1795
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001796static int stop_output_stream(struct stream_out *out)
1797{
1798 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001799 struct audio_usecase *uc_info;
1800 struct audio_device *adev = out->dev;
1801
Eric Laurent994a6932013-07-17 11:51:42 -07001802 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001803 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001804 uc_info = get_usecase_from_list(adev, out->usecase);
1805 if (uc_info == NULL) {
1806 ALOGE("%s: Could not find the usecase (%d) in the list",
1807 __func__, out->usecase);
1808 return -EINVAL;
1809 }
1810
Haynes Mathew George41f86652014-06-17 14:22:15 -07001811 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1812 if (adev->visualizer_stop_output != NULL)
1813 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1814 if (adev->offload_effects_stop_output != NULL)
1815 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08001816 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
1817 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
1818 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07001819 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001820
Eric Laurent150dbfe2013-02-27 14:31:02 -08001821 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001822 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001823
1824 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001825 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001826
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001827 list_remove(&uc_info->list);
1828 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001829
Eric Laurent0499d4f2014-08-25 22:39:29 -05001830 audio_extn_extspk_update(adev->extspk);
1831
Eric Laurent07eeafd2013-10-06 12:52:49 -07001832 /* Must be called after removing the usecase from list */
1833 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1834 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07001835 else if (out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
1836 struct listnode *node;
1837 struct audio_usecase *usecase;
1838 list_for_each(node, &adev->usecase_list) {
1839 usecase = node_to_item(node, struct audio_usecase, list);
1840 if (usecase->devices & AUDIO_DEVICE_OUT_SPEAKER)
1841 select_devices(adev, usecase->id);
1842 }
1843 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001844
Eric Laurent994a6932013-07-17 11:51:42 -07001845 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001846 return ret;
1847}
1848
1849int start_output_stream(struct stream_out *out)
1850{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001851 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001852 struct audio_usecase *uc_info;
1853 struct audio_device *adev = out->dev;
1854
Eric Laurent994a6932013-07-17 11:51:42 -07001855 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001856 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001857
1858 if (out->card_status == CARD_STATUS_OFFLINE ||
1859 adev->card_status == CARD_STATUS_OFFLINE) {
1860 ALOGW("out->card_status or adev->card_status offline, try again");
1861 ret = -EAGAIN;
1862 goto error_config;
1863 }
1864
Eric Laurentb23d5282013-05-14 15:27:20 -07001865 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001866 if (out->pcm_device_id < 0) {
1867 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1868 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001869 ret = -EINVAL;
1870 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001871 }
1872
1873 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1874 uc_info->id = out->usecase;
1875 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001876 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001877 uc_info->devices = out->devices;
1878 uc_info->in_snd_device = SND_DEVICE_NONE;
1879 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001880
Eric Laurent07eeafd2013-10-06 12:52:49 -07001881 /* This must be called before adding this usecase to the list */
1882 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1883 check_and_set_hdmi_channels(adev, out->config.channels);
1884
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001885 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001886
Wei Wangf4837d52017-11-21 14:51:20 -08001887 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001888 audio_extn_perf_lock_acquire();
1889
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001890 select_devices(adev, out->usecase);
1891
Eric Laurent0499d4f2014-08-25 22:39:29 -05001892 audio_extn_extspk_update(adev->extspk);
1893
Andy Hung31aca912014-03-20 17:14:59 -07001894 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001895 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001896 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1897 out->pcm = NULL;
1898 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1899 COMPRESS_IN, &out->compr_config);
1900 if (out->compr && !is_compress_ready(out->compr)) {
1901 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1902 compress_close(out->compr);
1903 out->compr = NULL;
1904 ret = -EIO;
1905 goto error_open;
1906 }
1907 if (out->offload_callback)
1908 compress_nonblock(out->compr, out->non_blocking);
1909
1910 if (adev->visualizer_start_output != NULL)
1911 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1912 if (adev->offload_effects_start_output != NULL)
1913 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
1914 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001915 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001916 ALOGE("%s: pcm stream not ready", __func__);
1917 goto error_open;
1918 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001919 ret = pcm_start(out->pcm);
1920 if (ret < 0) {
1921 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1922 goto error_open;
1923 }
1924 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07001925 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001926 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001927
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001928 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1929 flags |= PCM_MMAP | PCM_NOIRQ;
1930 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001931 } else if (out->realtime) {
1932 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07001933 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001934
1935 while (1) {
1936 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1937 flags, &out->config);
1938 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1939 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1940 if (out->pcm != NULL) {
1941 pcm_close(out->pcm);
1942 out->pcm = NULL;
1943 }
1944 if (pcm_open_retry_count-- == 0) {
1945 ret = -EIO;
1946 goto error_open;
1947 }
1948 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1949 continue;
1950 }
1951 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001952 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001953 ALOGV("%s: pcm_prepare", __func__);
1954 if (pcm_is_ready(out->pcm)) {
1955 ret = pcm_prepare(out->pcm);
1956 if (ret < 0) {
1957 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1958 pcm_close(out->pcm);
1959 out->pcm = NULL;
1960 goto error_open;
1961 }
1962 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001963 if (out->realtime) {
1964 ret = pcm_start(out->pcm);
1965 if (ret < 0) {
1966 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1967 pcm_close(out->pcm);
1968 out->pcm = NULL;
1969 goto error_open;
1970 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001971 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001972 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001973 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08001974 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001975 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001976 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07001977
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08001978 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
1979 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
1980 audio_low_latency_hint_start();
1981 }
1982
vivek mehtae59cfb22017-06-16 15:57:11 -07001983 // consider a scenario where on pause lower layers are tear down.
1984 // so on resume, swap mixer control need to be sent only when
1985 // backend is active, hence rather than sending from enable device
1986 // sending it from start of streamtream
1987
1988 platform_set_swap_channels(adev, true);
1989
Eric Laurent994a6932013-07-17 11:51:42 -07001990 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001991 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001992error_open:
Wei Wangf4837d52017-11-21 14:51:20 -08001993 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001994 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001995 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001996error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001997 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001998}
1999
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002000static int check_input_parameters(uint32_t sample_rate,
2001 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07002002 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002003{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002004 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2005 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002006 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2007 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002008 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2009 return -EINVAL;
2010 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002011
Eric Laurent74b55762017-07-09 17:04:53 -07002012 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2013 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002014 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002015 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002016 return -EINVAL;
2017 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002018
2019 switch (sample_rate) {
2020 case 8000:
2021 case 11025:
2022 case 12000:
2023 case 16000:
2024 case 22050:
2025 case 24000:
2026 case 32000:
2027 case 44100:
2028 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002029 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002030 break;
2031 default:
vivek mehtadae44712015-07-27 14:13:18 -07002032 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002033 return -EINVAL;
2034 }
2035
2036 return 0;
2037}
2038
vivek mehtaa68fea62017-06-08 19:04:02 -07002039static size_t get_stream_buffer_size(size_t duration_ms,
2040 uint32_t sample_rate,
2041 audio_format_t format,
2042 int channel_count,
2043 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002044{
2045 size_t size = 0;
2046
vivek mehtaa68fea62017-06-08 19:04:02 -07002047 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002048 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002049 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002050
2051 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002052
Glenn Kasten4f993392014-05-14 07:30:48 -07002053 /* make sure the size is multiple of 32 bytes
2054 * At 48 kHz mono 16-bit PCM:
2055 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2056 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2057 */
2058 size += 0x1f;
2059 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002060
2061 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002062}
2063
2064static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2065{
2066 struct stream_out *out = (struct stream_out *)stream;
2067
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002068 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002069}
2070
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002071static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002072{
2073 return -ENOSYS;
2074}
2075
2076static size_t out_get_buffer_size(const struct audio_stream *stream)
2077{
2078 struct stream_out *out = (struct stream_out *)stream;
2079
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002080 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2081 return out->compr_config.fragment_size;
2082 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002083 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002084 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002085}
2086
2087static uint32_t out_get_channels(const struct audio_stream *stream)
2088{
2089 struct stream_out *out = (struct stream_out *)stream;
2090
2091 return out->channel_mask;
2092}
2093
2094static audio_format_t out_get_format(const struct audio_stream *stream)
2095{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002096 struct stream_out *out = (struct stream_out *)stream;
2097
2098 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002099}
2100
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002101static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002102{
2103 return -ENOSYS;
2104}
2105
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002106/* must be called with out->lock locked */
2107static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002108{
2109 struct stream_out *out = (struct stream_out *)stream;
2110 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002111 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002112
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002113 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002114 if (adev->adm_deregister_stream)
2115 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002116 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002117 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002118 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2119 if (out->pcm) {
2120 pcm_close(out->pcm);
2121 out->pcm = NULL;
2122 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002123 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002124 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002125 out->playback_started = false;
2126 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002127 } else {
2128 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002129 out->gapless_mdata.encoder_delay = 0;
2130 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002131 if (out->compr != NULL) {
2132 compress_close(out->compr);
2133 out->compr = NULL;
2134 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002135 }
Phil Burkbc991042017-02-24 08:06:44 -08002136 if (do_stop) {
2137 stop_output_stream(out);
2138 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002139 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002140 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002141 return 0;
2142}
2143
2144static int out_standby(struct audio_stream *stream)
2145{
2146 struct stream_out *out = (struct stream_out *)stream;
2147
2148 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2149 out->usecase, use_case_table[out->usecase]);
2150
2151 lock_output_stream(out);
2152 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002153 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002154 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002155 return 0;
2156}
2157
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002158static int out_on_error(struct audio_stream *stream)
2159{
2160 struct stream_out *out = (struct stream_out *)stream;
2161 struct audio_device *adev = out->dev;
2162 bool do_standby = false;
2163
2164 lock_output_stream(out);
2165 if (!out->standby) {
2166 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2167 stop_compressed_output_l(out);
2168 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2169 } else
2170 do_standby = true;
2171 }
2172 pthread_mutex_unlock(&out->lock);
2173
2174 if (do_standby)
2175 return out_standby(&out->stream.common);
2176
2177 return 0;
2178}
2179
Andy Hung7401c7c2016-09-21 12:41:21 -07002180static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002181{
Andy Hung7401c7c2016-09-21 12:41:21 -07002182 struct stream_out *out = (struct stream_out *)stream;
2183
2184 // We try to get the lock for consistency,
2185 // but it isn't necessary for these variables.
2186 // If we're not in standby, we may be blocked on a write.
2187 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2188 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2189 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2190
2191 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002192 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002193 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002194
2195 // dump error info
2196 (void)error_log_dump(
2197 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002198
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002199 return 0;
2200}
2201
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002202static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2203{
2204 int ret = 0;
2205 char value[32];
2206 struct compr_gapless_mdata tmp_mdata;
2207
2208 if (!out || !parms) {
2209 return -EINVAL;
2210 }
2211
2212 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2213 if (ret >= 0) {
2214 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2215 } else {
2216 return -EINVAL;
2217 }
2218
2219 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2220 if (ret >= 0) {
2221 tmp_mdata.encoder_padding = atoi(value);
2222 } else {
2223 return -EINVAL;
2224 }
2225
2226 out->gapless_mdata = tmp_mdata;
2227 out->send_new_metadata = 1;
2228 ALOGV("%s new encoder delay %u and padding %u", __func__,
2229 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2230
2231 return 0;
2232}
2233
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002234static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2235{
2236 return out == adev->primary_output || out == adev->voice_tx_output;
2237}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002238
Kevin Rocard1e02c882017-08-09 15:26:07 -07002239static int get_alive_usb_card(struct str_parms* parms) {
2240 int card;
2241 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2242 !audio_extn_usb_alive(card)) {
2243 return card;
2244 }
2245 return -ENODEV;
2246}
2247
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002248static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2249{
2250 struct stream_out *out = (struct stream_out *)stream;
2251 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002252 struct audio_usecase *usecase;
2253 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002254 struct str_parms *parms;
2255 char value[32];
2256 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002257 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002258 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002259
Eric Laurent2e140aa2016-06-30 17:14:46 -07002260 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002261 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002262 parms = str_parms_create_str(kvpairs);
2263 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2264 if (ret >= 0) {
2265 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002266
Eric Laurenta1478072015-09-21 17:21:52 -07002267 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002268
2269 // The usb driver needs to be closed after usb device disconnection
2270 // otherwise audio is no longer played on the new usb devices.
2271 // By forcing the stream in standby, the usb stack refcount drops to 0
2272 // and the driver is closed.
2273 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD && val == AUDIO_DEVICE_NONE &&
2274 audio_is_usb_out_device(out->devices)) {
2275 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2276 out_standby_l(&out->stream.common);
2277 }
2278
Eric Laurent150dbfe2013-02-27 14:31:02 -08002279 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002280
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002281 /*
2282 * When HDMI cable is unplugged the music playback is paused and
2283 * the policy manager sends routing=0. But the audioflinger
2284 * continues to write data until standby time (3sec).
2285 * As the HDMI core is turned off, the write gets blocked.
2286 * Avoid this by routing audio to speaker until standby.
2287 */
2288 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2289 val == AUDIO_DEVICE_NONE) {
2290 val = AUDIO_DEVICE_OUT_SPEAKER;
2291 }
2292
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002293 audio_devices_t new_dev = val;
2294
2295 // Workaround: If routing to an non existing usb device, fail gracefully
2296 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002297 int card;
2298 if (audio_is_usb_out_device(new_dev) &&
2299 (card = get_alive_usb_card(parms)) >= 0) {
2300
2301 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002302 pthread_mutex_unlock(&adev->lock);
2303 pthread_mutex_unlock(&out->lock);
2304 status = -ENOSYS;
2305 goto routing_fail;
2306 }
2307
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002308 /*
2309 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002310 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002311 * the select_devices(). But how do we undo this?
2312 *
2313 * For example, music playback is active on headset (deep-buffer usecase)
2314 * and if we go to ringtones and select a ringtone, low-latency usecase
2315 * will be started on headset+speaker. As we can't enable headset+speaker
2316 * and headset devices at the same time, select_devices() switches the music
2317 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2318 * So when the ringtone playback is completed, how do we undo the same?
2319 *
2320 * We are relying on the out_set_parameters() call on deep-buffer output,
2321 * once the ringtone playback is ended.
2322 * NOTE: We should not check if the current devices are same as new devices.
2323 * Because select_devices() must be called to switch back the music
2324 * playback to headset.
2325 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002326 if (new_dev != AUDIO_DEVICE_NONE) {
2327 bool same_dev = out->devices == new_dev;
2328 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002329
Eric Laurenta7657192014-10-09 21:09:33 -07002330 if (output_drives_call(adev, out)) {
2331 if (!voice_is_in_call(adev)) {
2332 if (adev->mode == AUDIO_MODE_IN_CALL) {
2333 adev->current_call_output = out;
2334 ret = voice_start_call(adev);
2335 }
2336 } else {
2337 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002338 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002339 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002340 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002341
2342 if (!out->standby) {
2343 if (!same_dev) {
2344 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002345 // inform adm before actual routing to prevent glitches.
2346 if (adev->adm_on_routing_change) {
2347 adev->adm_on_routing_change(adev->adm_data,
2348 out->handle);
2349 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002350 }
2351 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002352 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002353
2354 // on device switch force swap, lower functions will make sure
2355 // to check if swap is allowed or not.
2356
2357 if (!same_dev)
2358 platform_set_swap_channels(adev, true);
vivek mehta0d3637a2016-07-24 09:32:02 -07002359 }
2360
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002361 }
2362
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002363 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002364 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002365
2366 /*handles device and call state changes*/
2367 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002368 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002369 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002370
2371 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2372 parse_compress_metadata(out, parms);
2373 }
2374
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002375 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002376 ALOGV("%s: exit: code(%d)", __func__, status);
2377 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002378}
2379
Haynes Mathew George569b7482017-05-08 14:44:27 -07002380static bool stream_get_parameter_channels(struct str_parms *query,
2381 struct str_parms *reply,
2382 audio_channel_mask_t *supported_channel_masks) {
2383 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002384 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002385 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002386 size_t i, j;
2387
2388 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2389 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002390 value[0] = '\0';
2391 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002392 while (supported_channel_masks[i] != 0) {
2393 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2394 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002395 if (!first) {
2396 strcat(value, "|");
2397 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002398 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002399 first = false;
2400 break;
2401 }
2402 }
2403 i++;
2404 }
2405 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002406 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002407 return ret >= 0;
2408}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002409
Haynes Mathew George569b7482017-05-08 14:44:27 -07002410static bool stream_get_parameter_formats(struct str_parms *query,
2411 struct str_parms *reply,
2412 audio_format_t *supported_formats) {
2413 int ret = -1;
2414 char value[256];
2415 int i;
2416
2417 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2418 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002419 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002420 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002421 case AUDIO_FORMAT_PCM_16_BIT:
2422 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2423 break;
2424 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2425 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2426 break;
2427 case AUDIO_FORMAT_PCM_32_BIT:
2428 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2429 break;
2430 default:
2431 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002432 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002433 break;
2434 }
2435 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002436 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002437 return ret >= 0;
2438}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002439
Haynes Mathew George569b7482017-05-08 14:44:27 -07002440static bool stream_get_parameter_rates(struct str_parms *query,
2441 struct str_parms *reply,
2442 uint32_t *supported_sample_rates) {
2443
2444 int i;
2445 char value[256];
2446 int ret = -1;
2447 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2448 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002449 value[0] = '\0';
2450 i=0;
2451 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002452 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002453 int avail = sizeof(value) - cursor;
2454 ret = snprintf(value + cursor, avail, "%s%d",
2455 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002456 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002457 if (ret < 0 || ret >= avail) {
2458 // if cursor is at the last element of the array
2459 // overwrite with \0 is duplicate work as
2460 // snprintf already put a \0 in place.
2461 // else
2462 // we had space to write the '|' at value[cursor]
2463 // (which will be overwritten) or no space to fill
2464 // the first element (=> cursor == 0)
2465 value[cursor] = '\0';
2466 break;
2467 }
2468 cursor += ret;
2469 ++i;
2470 }
2471 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2472 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002473 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002474 return ret >= 0;
2475}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002476
Haynes Mathew George569b7482017-05-08 14:44:27 -07002477static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2478{
2479 struct stream_out *out = (struct stream_out *)stream;
2480 struct str_parms *query = str_parms_create_str(keys);
2481 char *str;
2482 struct str_parms *reply = str_parms_create();
2483 bool replied = false;
2484 ALOGV("%s: enter: keys - %s", __func__, keys);
2485
2486 replied |= stream_get_parameter_channels(query, reply,
2487 &out->supported_channel_masks[0]);
2488 replied |= stream_get_parameter_formats(query, reply,
2489 &out->supported_formats[0]);
2490 replied |= stream_get_parameter_rates(query, reply,
2491 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002492 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002493 str = str_parms_to_str(reply);
2494 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002495 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002496 }
2497 str_parms_destroy(query);
2498 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002499 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002500 return str;
2501}
2502
2503static uint32_t out_get_latency(const struct audio_stream_out *stream)
2504{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002505 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002506 struct stream_out *out = (struct stream_out *)stream;
2507
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002508 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2509 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002510 else if ((out->realtime) ||
2511 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002512 // since the buffer won't be filled up faster than realtime,
2513 // return a smaller number
2514 period_ms = (out->af_period_multiplier * out->config.period_size *
2515 1000) / (out->config.rate);
2516 hw_delay = platform_render_latency(out->usecase)/1000;
2517 return period_ms + hw_delay;
2518 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002519
2520 return (out->config.period_count * out->config.period_size * 1000) /
2521 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002522}
2523
2524static int out_set_volume(struct audio_stream_out *stream, float left,
2525 float right)
2526{
Eric Laurenta9024de2013-04-04 09:19:12 -07002527 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002528 int volume[2];
2529
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002530 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002531 /* only take left channel into account: the API is for stereo anyway */
2532 out->muted = (left == 0.0f);
2533 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002534 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2535 const char *mixer_ctl_name = "Compress Playback Volume";
2536 struct audio_device *adev = out->dev;
2537 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002538 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2539 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002540 /* try with the control based on device id */
2541 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2542 PCM_PLAYBACK);
2543 char ctl_name[128] = {0};
2544 snprintf(ctl_name, sizeof(ctl_name),
2545 "Compress Playback %d Volume", pcm_device_id);
2546 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2547 if (!ctl) {
2548 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2549 return -EINVAL;
2550 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002551 }
2552 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2553 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2554 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2555 return 0;
vivek mehtaa68fea62017-06-08 19:04:02 -07002556 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002557 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2558 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2559 if (!out->standby) {
2560 // if in standby, cached volume will be sent after stream is opened
2561 audio_extn_utils_send_app_type_gain(out->dev,
2562 out->app_type_cfg.app_type,
2563 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002564 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002565 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002566 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002567
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002568 return -ENOSYS;
2569}
2570
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002571// note: this call is safe only if the stream_cb is
2572// removed first in close_output_stream (as is done now).
2573static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2574{
2575 if (!stream || !parms)
2576 return;
2577
2578 struct stream_out *out = (struct stream_out *)stream;
2579 struct audio_device *adev = out->dev;
2580
2581 card_status_t status;
2582 int card;
2583 if (parse_snd_card_status(parms, &card, &status) < 0)
2584 return;
2585
2586 pthread_mutex_lock(&adev->lock);
2587 bool valid_cb = (card == adev->snd_card);
2588 pthread_mutex_unlock(&adev->lock);
2589
2590 if (!valid_cb)
2591 return;
2592
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002593 lock_output_stream(out);
2594 if (out->card_status != status)
2595 out->card_status = status;
2596 pthread_mutex_unlock(&out->lock);
2597
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002598 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2599 use_case_table[out->usecase],
2600 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2601
2602 if (status == CARD_STATUS_OFFLINE)
2603 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002604
2605 return;
2606}
2607
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002608#ifdef NO_AUDIO_OUT
2609static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002610 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002611{
2612 struct stream_out *out = (struct stream_out *)stream;
2613
2614 /* No Output device supported other than BT for playback.
2615 * Sleep for the amount of buffer duration
2616 */
Eric Laurenta1478072015-09-21 17:21:52 -07002617 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002618 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2619 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002620 out_get_sample_rate(&out->stream.common));
2621 pthread_mutex_unlock(&out->lock);
2622 return bytes;
2623}
2624#endif
2625
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002626static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2627 size_t bytes)
2628{
2629 struct stream_out *out = (struct stream_out *)stream;
2630 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002631 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002632 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002633
Eric Laurenta1478072015-09-21 17:21:52 -07002634 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002635 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07002636 const size_t frame_size = audio_stream_out_frame_size(stream);
2637 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002638
Eric Laurent0e46adf2016-12-16 12:49:24 -08002639 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2640 error_code = ERROR_CODE_WRITE;
2641 goto exit;
2642 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002643 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002644 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002645 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002646 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07002647
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002648 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002649 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002650 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07002651 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002652 goto exit;
2653 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002654
vivek mehta40125092017-08-21 18:48:51 -07002655 // after standby always force set last known cal step
2656 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
2657 ALOGD("%s: retry previous failed cal level set", __func__);
2658 send_gain_dep_calibration_l();
2659 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002660 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002661
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002662 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002663 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002664 if (out->send_new_metadata) {
2665 ALOGVV("send new gapless metadata");
2666 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2667 out->send_new_metadata = 0;
2668 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002669 unsigned int avail;
2670 struct timespec tstamp;
2671 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2672 /* Do not limit write size if the available frames count is unknown */
2673 if (ret != 0) {
2674 avail = bytes;
2675 }
2676 if (avail == 0) {
2677 ret = 0;
2678 } else {
2679 if (avail > bytes) {
2680 avail = bytes;
2681 }
2682 ret = compress_write(out->compr, buffer, avail);
2683 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2684 __func__, avail, ret);
2685 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002686
Eric Laurent6e895242013-09-05 16:10:57 -07002687 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002688 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2689 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002690 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002691 compress_start(out->compr);
2692 out->playback_started = 1;
2693 out->offload_state = OFFLOAD_STATE_PLAYING;
2694 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002695 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002696 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002697 } else {
2698 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002699 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002700 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002701 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002702 return ret;
2703 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002704 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002705 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07002706 size_t bytes_to_write = bytes;
2707
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002708 if (out->muted)
2709 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07002710 // FIXME: this can be removed once audio flinger mixer supports mono output
Nadav Bar3d72cfc2018-01-07 12:19:24 +02002711 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP || out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
Eric Laurentad2dde92017-09-20 18:27:31 -07002712 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
2713 int16_t *src = (int16_t *)buffer;
2714 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002715
Eric Laurentad2dde92017-09-20 18:27:31 -07002716 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
2717 out->format != AUDIO_FORMAT_PCM_16_BIT,
2718 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002719
Eric Laurentad2dde92017-09-20 18:27:31 -07002720 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
2721 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
2722 }
2723 bytes_to_write /= 2;
2724 }
2725 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes_to_write);
2726
2727 long ns = (frames * NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002728 request_out_focus(out, ns);
2729
2730 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2731 if (use_mmap)
Eric Laurentad2dde92017-09-20 18:27:31 -07002732 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002733 else
Eric Laurentad2dde92017-09-20 18:27:31 -07002734 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002735
Haynes Mathew George03c40102016-01-29 17:57:48 -08002736 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002737 } else {
2738 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002739 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002740 }
2741
2742exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002743 // For PCM we always consume the buffer and return #bytes regardless of ret.
2744 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07002745 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07002746 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002747 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07002748
Andy Hung7401c7c2016-09-21 12:41:21 -07002749 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07002750 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07002751 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2752 ALOGE_IF(out->pcm != NULL,
2753 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07002754 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002755 // usleep not guaranteed for values over 1 second but we don't limit here.
2756 }
2757 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002758
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002759 pthread_mutex_unlock(&out->lock);
2760
2761 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002762 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002763 if (sleeptime_us != 0)
2764 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002765 }
2766 return bytes;
2767}
2768
2769static int out_get_render_position(const struct audio_stream_out *stream,
2770 uint32_t *dsp_frames)
2771{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002772 struct stream_out *out = (struct stream_out *)stream;
2773 *dsp_frames = 0;
2774 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002775 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002776 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002777 unsigned long frames = 0;
2778 // TODO: check return value
2779 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2780 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002781 ALOGVV("%s rendered frames %d sample_rate %d",
2782 __func__, *dsp_frames, out->sample_rate);
2783 }
2784 pthread_mutex_unlock(&out->lock);
2785 return 0;
2786 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002787 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002788}
2789
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002790static int out_add_audio_effect(const struct audio_stream *stream __unused,
2791 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002792{
2793 return 0;
2794}
2795
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002796static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2797 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002798{
2799 return 0;
2800}
2801
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002802static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2803 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002804{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002805 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002806}
2807
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002808static int out_get_presentation_position(const struct audio_stream_out *stream,
2809 uint64_t *frames, struct timespec *timestamp)
2810{
2811 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002812 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07002813 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002814
Eric Laurenta1478072015-09-21 17:21:52 -07002815 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002816
Eric Laurent949a0892013-09-20 09:20:13 -07002817 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2818 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002819 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002820 compress_get_tstamp(out->compr, &dsp_frames,
2821 &out->sample_rate);
2822 ALOGVV("%s rendered frames %ld sample_rate %d",
2823 __func__, dsp_frames, out->sample_rate);
2824 *frames = dsp_frames;
2825 ret = 0;
2826 /* this is the best we can do */
2827 clock_gettime(CLOCK_MONOTONIC, timestamp);
2828 }
2829 } else {
2830 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002831 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002832 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2833 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002834 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002835 // This adjustment accounts for buffering after app processor.
2836 // It is based on estimated DSP latency per use case, rather than exact.
2837 signed_frames -=
2838 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2839
Eric Laurent949a0892013-09-20 09:20:13 -07002840 // It would be unusual for this value to be negative, but check just in case ...
2841 if (signed_frames >= 0) {
2842 *frames = signed_frames;
2843 ret = 0;
2844 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002845 }
2846 }
2847 }
2848
2849 pthread_mutex_unlock(&out->lock);
2850
2851 return ret;
2852}
2853
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002854static int out_set_callback(struct audio_stream_out *stream,
2855 stream_callback_t callback, void *cookie)
2856{
2857 struct stream_out *out = (struct stream_out *)stream;
2858
2859 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002860 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002861 out->offload_callback = callback;
2862 out->offload_cookie = cookie;
2863 pthread_mutex_unlock(&out->lock);
2864 return 0;
2865}
2866
2867static int out_pause(struct audio_stream_out* stream)
2868{
2869 struct stream_out *out = (struct stream_out *)stream;
2870 int status = -ENOSYS;
2871 ALOGV("%s", __func__);
2872 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002873 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002874 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2875 status = compress_pause(out->compr);
2876 out->offload_state = OFFLOAD_STATE_PAUSED;
2877 }
2878 pthread_mutex_unlock(&out->lock);
2879 }
2880 return status;
2881}
2882
2883static int out_resume(struct audio_stream_out* stream)
2884{
2885 struct stream_out *out = (struct stream_out *)stream;
2886 int status = -ENOSYS;
2887 ALOGV("%s", __func__);
2888 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2889 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002890 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002891 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2892 status = compress_resume(out->compr);
2893 out->offload_state = OFFLOAD_STATE_PLAYING;
2894 }
2895 pthread_mutex_unlock(&out->lock);
2896 }
2897 return status;
2898}
2899
2900static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2901{
2902 struct stream_out *out = (struct stream_out *)stream;
2903 int status = -ENOSYS;
2904 ALOGV("%s", __func__);
2905 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002906 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002907 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2908 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2909 else
2910 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2911 pthread_mutex_unlock(&out->lock);
2912 }
2913 return status;
2914}
2915
2916static int out_flush(struct audio_stream_out* stream)
2917{
2918 struct stream_out *out = (struct stream_out *)stream;
2919 ALOGV("%s", __func__);
2920 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002921 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002922 stop_compressed_output_l(out);
2923 pthread_mutex_unlock(&out->lock);
2924 return 0;
2925 }
2926 return -ENOSYS;
2927}
2928
Eric Laurent0e46adf2016-12-16 12:49:24 -08002929static int out_stop(const struct audio_stream_out* stream)
2930{
2931 struct stream_out *out = (struct stream_out *)stream;
2932 struct audio_device *adev = out->dev;
2933 int ret = -ENOSYS;
2934
2935 ALOGV("%s", __func__);
2936 pthread_mutex_lock(&adev->lock);
2937 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2938 out->playback_started && out->pcm != NULL) {
2939 pcm_stop(out->pcm);
2940 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08002941 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002942 }
2943 pthread_mutex_unlock(&adev->lock);
2944 return ret;
2945}
2946
2947static int out_start(const struct audio_stream_out* stream)
2948{
2949 struct stream_out *out = (struct stream_out *)stream;
2950 struct audio_device *adev = out->dev;
2951 int ret = -ENOSYS;
2952
2953 ALOGV("%s", __func__);
2954 pthread_mutex_lock(&adev->lock);
2955 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2956 !out->playback_started && out->pcm != NULL) {
2957 ret = start_output_stream(out);
2958 if (ret == 0) {
2959 out->playback_started = true;
2960 }
2961 }
2962 pthread_mutex_unlock(&adev->lock);
2963 return ret;
2964}
2965
Phil Burkbc991042017-02-24 08:06:44 -08002966/*
2967 * Modify config->period_count based on min_size_frames
2968 */
2969static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
2970{
2971 int periodCountRequested = (min_size_frames + config->period_size - 1)
2972 / config->period_size;
2973 int periodCount = MMAP_PERIOD_COUNT_MIN;
2974
2975 ALOGV("%s original config.period_size = %d config.period_count = %d",
2976 __func__, config->period_size, config->period_count);
2977
2978 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
2979 periodCount *= 2;
2980 }
2981 config->period_count = periodCount;
2982
2983 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
2984}
2985
Eric Laurent0e46adf2016-12-16 12:49:24 -08002986static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2987 int32_t min_size_frames,
2988 struct audio_mmap_buffer_info *info)
2989{
2990 struct stream_out *out = (struct stream_out *)stream;
2991 struct audio_device *adev = out->dev;
2992 int ret = 0;
2993 unsigned int offset1;
2994 unsigned int frames1;
2995 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07002996 uint32_t mmap_size;
2997 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002998
2999 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003000 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003001 pthread_mutex_lock(&adev->lock);
3002
3003 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003004 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003005 ret = -EINVAL;
3006 goto exit;
3007 }
3008 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003009 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003010 ret = -ENOSYS;
3011 goto exit;
3012 }
3013 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3014 if (out->pcm_device_id < 0) {
3015 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3016 __func__, out->pcm_device_id, out->usecase);
3017 ret = -EINVAL;
3018 goto exit;
3019 }
Phil Burkbc991042017-02-24 08:06:44 -08003020
3021 adjust_mmap_period_count(&out->config, min_size_frames);
3022
Eric Laurent0e46adf2016-12-16 12:49:24 -08003023 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3024 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3025 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3026 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3027 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3028 step = "open";
3029 ret = -ENODEV;
3030 goto exit;
3031 }
3032 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3033 if (ret < 0) {
3034 step = "begin";
3035 goto exit;
3036 }
3037 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003038 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003039 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003040 ret = platform_get_mmap_data_fd(adev->platform,
3041 out->pcm_device_id, 0 /*playback*/,
3042 &info->shared_memory_fd,
3043 &mmap_size);
3044 if (ret < 0) {
3045 // Fall back to non exclusive mode
3046 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3047 } else {
3048 if (mmap_size < buffer_size) {
3049 step = "mmap";
3050 goto exit;
3051 }
3052 // FIXME: indicate exclusive mode support by returning a negative buffer size
3053 info->buffer_size_frames *= -1;
3054 }
3055 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003056
3057 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3058 if (ret < 0) {
3059 step = "commit";
3060 goto exit;
3061 }
Phil Burkbc991042017-02-24 08:06:44 -08003062
3063 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003064 ret = 0;
3065
3066 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3067 __func__, info->shared_memory_address, info->buffer_size_frames);
3068
3069exit:
3070 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003071 if (out->pcm == NULL) {
3072 ALOGE("%s: %s - %d", __func__, step, ret);
3073 } else {
3074 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003075 pcm_close(out->pcm);
3076 out->pcm = NULL;
3077 }
3078 }
3079 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003080 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003081 return ret;
3082}
3083
3084static int out_get_mmap_position(const struct audio_stream_out *stream,
3085 struct audio_mmap_position *position)
3086{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003087 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003088 struct stream_out *out = (struct stream_out *)stream;
3089 ALOGVV("%s", __func__);
3090 if (position == NULL) {
3091 return -EINVAL;
3092 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003093 lock_output_stream(out);
3094 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3095 out->pcm == NULL) {
3096 ret = -ENOSYS;
3097 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003098 }
3099
3100 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003101 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003102 if (ret < 0) {
3103 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003104 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003105 }
Andy Hungfc044e12017-03-20 09:24:22 -07003106 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003107exit:
3108 pthread_mutex_unlock(&out->lock);
3109 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003110}
3111
3112
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003113/** audio_stream_in implementation **/
3114static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3115{
3116 struct stream_in *in = (struct stream_in *)stream;
3117
3118 return in->config.rate;
3119}
3120
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003121static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003122{
3123 return -ENOSYS;
3124}
3125
3126static size_t in_get_buffer_size(const struct audio_stream *stream)
3127{
3128 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003129 return in->config.period_size * in->af_period_multiplier *
3130 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003131}
3132
3133static uint32_t in_get_channels(const struct audio_stream *stream)
3134{
3135 struct stream_in *in = (struct stream_in *)stream;
3136
3137 return in->channel_mask;
3138}
3139
vivek mehta4ed66e62016-04-15 23:33:34 -07003140static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003141{
vivek mehta4ed66e62016-04-15 23:33:34 -07003142 struct stream_in *in = (struct stream_in *)stream;
3143 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003144}
3145
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003146static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003147{
3148 return -ENOSYS;
3149}
3150
3151static int in_standby(struct audio_stream *stream)
3152{
3153 struct stream_in *in = (struct stream_in *)stream;
3154 struct audio_device *adev = in->dev;
3155 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003156 bool do_stop = true;
3157
Eric Laurent994a6932013-07-17 11:51:42 -07003158 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003159
3160 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003161
3162 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003163 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003164 audio_extn_sound_trigger_stop_lab(in);
3165 in->standby = true;
3166 }
3167
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003168 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003169 if (adev->adm_deregister_stream)
3170 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3171
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003172 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003173 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003174 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003175 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003176 in->capture_started = false;
3177 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003178 if (in->pcm) {
3179 pcm_close(in->pcm);
3180 in->pcm = NULL;
3181 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003182 adev->enable_voicerx = false;
3183 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003184 if (do_stop) {
3185 status = stop_input_stream(in);
3186 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003187 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003188 }
3189 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003190 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003191 return status;
3192}
3193
Andy Hungd13f0d32017-06-12 13:58:37 -07003194static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003195{
Andy Hungd13f0d32017-06-12 13:58:37 -07003196 struct stream_in *in = (struct stream_in *)stream;
3197
3198 // We try to get the lock for consistency,
3199 // but it isn't necessary for these variables.
3200 // If we're not in standby, we may be blocked on a read.
3201 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3202 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3203 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3204 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3205
3206 if (locked) {
3207 pthread_mutex_unlock(&in->lock);
3208 }
3209
3210 // dump error info
3211 (void)error_log_dump(
3212 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003213 return 0;
3214}
3215
3216static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3217{
3218 struct stream_in *in = (struct stream_in *)stream;
3219 struct audio_device *adev = in->dev;
3220 struct str_parms *parms;
3221 char *str;
3222 char value[32];
3223 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003224 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003225
Eric Laurent994a6932013-07-17 11:51:42 -07003226 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003227 parms = str_parms_create_str(kvpairs);
3228
3229 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3230
Eric Laurenta1478072015-09-21 17:21:52 -07003231 lock_input_stream(in);
3232
Eric Laurent150dbfe2013-02-27 14:31:02 -08003233 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003234 if (ret >= 0) {
3235 val = atoi(value);
3236 /* no audio source uses val == 0 */
3237 if ((in->source != val) && (val != 0)) {
3238 in->source = val;
3239 }
3240 }
3241
3242 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003243
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003244 if (ret >= 0) {
3245 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003246 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003247
3248 // Workaround: If routing to an non existing usb device, fail gracefully
3249 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003250 int card;
3251 if (audio_is_usb_in_device(val) &&
3252 (card = get_alive_usb_card(parms)) >= 0) {
3253
3254 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003255 status = -ENOSYS;
3256 } else {
3257
3258 in->device = val;
3259 /* If recording is in progress, change the tx device to new device */
3260 if (!in->standby) {
3261 ALOGV("update input routing change");
3262 // inform adm before actual routing to prevent glitches.
3263 if (adev->adm_on_routing_change) {
3264 adev->adm_on_routing_change(adev->adm_data,
3265 in->capture_handle);
3266 }
3267 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003268 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003269 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003270 }
3271 }
3272
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003273 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003274 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003275
3276 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003277 ALOGV("%s: exit: status(%d)", __func__, status);
3278 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003279}
3280
Haynes Mathew George569b7482017-05-08 14:44:27 -07003281static char* in_get_parameters(const struct audio_stream *stream,
3282 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003283{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003284 struct stream_in *in = (struct stream_in *)stream;
3285 struct str_parms *query = str_parms_create_str(keys);
3286 char *str;
3287 struct str_parms *reply = str_parms_create();
3288 bool replied = false;
3289
3290 ALOGV("%s: enter: keys - %s", __func__, keys);
3291 replied |= stream_get_parameter_channels(query, reply,
3292 &in->supported_channel_masks[0]);
3293 replied |= stream_get_parameter_formats(query, reply,
3294 &in->supported_formats[0]);
3295 replied |= stream_get_parameter_rates(query, reply,
3296 &in->supported_sample_rates[0]);
3297 if (replied) {
3298 str = str_parms_to_str(reply);
3299 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003300 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003301 }
3302 str_parms_destroy(query);
3303 str_parms_destroy(reply);
3304 ALOGV("%s: exit: returns - %s", __func__, str);
3305 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003306}
3307
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003308static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003309{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003310 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003311}
3312
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003313static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3314{
3315 if (!stream || !parms)
3316 return;
3317
3318 struct stream_in *in = (struct stream_in *)stream;
3319 struct audio_device *adev = in->dev;
3320
3321 card_status_t status;
3322 int card;
3323 if (parse_snd_card_status(parms, &card, &status) < 0)
3324 return;
3325
3326 pthread_mutex_lock(&adev->lock);
3327 bool valid_cb = (card == adev->snd_card);
3328 pthread_mutex_unlock(&adev->lock);
3329
3330 if (!valid_cb)
3331 return;
3332
3333 lock_input_stream(in);
3334 if (in->card_status != status)
3335 in->card_status = status;
3336 pthread_mutex_unlock(&in->lock);
3337
3338 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3339 use_case_table[in->usecase],
3340 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3341
3342 // a better solution would be to report error back to AF and let
3343 // it put the stream to standby
3344 if (status == CARD_STATUS_OFFLINE)
3345 in_standby(&in->stream.common);
3346
3347 return;
3348}
3349
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003350static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3351 size_t bytes)
3352{
3353 struct stream_in *in = (struct stream_in *)stream;
3354 struct audio_device *adev = in->dev;
3355 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003356 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003357 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003358
Eric Laurenta1478072015-09-21 17:21:52 -07003359 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003360 const size_t frame_size = audio_stream_in_frame_size(stream);
3361 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003362
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003363 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003364 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003365 /* Read from sound trigger HAL */
3366 audio_extn_sound_trigger_read(in, buffer, bytes);
3367 pthread_mutex_unlock(&in->lock);
3368 return bytes;
3369 }
3370
Eric Laurent0e46adf2016-12-16 12:49:24 -08003371 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3372 ret = -ENOSYS;
3373 goto exit;
3374 }
3375
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003376 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003377 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003378 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003379 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003380 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003381 goto exit;
3382 }
3383 in->standby = 0;
3384 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003385
Andy Hungd13f0d32017-06-12 13:58:37 -07003386 // errors that occur here are read errors.
3387 error_code = ERROR_CODE_READ;
3388
Haynes Mathew George03c40102016-01-29 17:57:48 -08003389 //what's the duration requested by the client?
3390 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3391 in->config.rate;
3392 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003393
Haynes Mathew George03c40102016-01-29 17:57:48 -08003394 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003395 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003396 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003397 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003398 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003399 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003400 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003401 if (ret < 0) {
3402 ALOGE("Failed to read w/err %s", strerror(errno));
3403 ret = -errno;
3404 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003405 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3406 if (bytes % 4 == 0) {
3407 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3408 int_buf_stream = buffer;
3409 for (size_t itt=0; itt < bytes/4 ; itt++) {
3410 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003411 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003412 } else {
3413 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3414 ret = -EINVAL;
3415 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003416 }
3417 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003418 }
3419
Haynes Mathew George03c40102016-01-29 17:57:48 -08003420 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003421
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003422 /*
3423 * Instead of writing zeroes here, we could trust the hardware
3424 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003425 * 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 -08003426 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08003427 if (ret == 0 && adev->mic_muted &&
3428 !voice_is_in_call_rec_stream(in) &&
3429 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003430 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07003431 in->frames_muted += frames;
3432 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003433
3434exit:
3435 pthread_mutex_unlock(&in->lock);
3436
3437 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07003438 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003439 in_standby(&in->stream.common);
3440 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003441 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003442 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07003443 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08003444 }
3445 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003446 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003447 }
3448 return bytes;
3449}
3450
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003451static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003452{
3453 return 0;
3454}
3455
Andy Hung6ebe5962016-01-15 17:46:57 -08003456static int in_get_capture_position(const struct audio_stream_in *stream,
3457 int64_t *frames, int64_t *time)
3458{
3459 if (stream == NULL || frames == NULL || time == NULL) {
3460 return -EINVAL;
3461 }
3462 struct stream_in *in = (struct stream_in *)stream;
3463 int ret = -ENOSYS;
3464
3465 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003466 // note: ST sessions do not close the alsa pcm driver synchronously
3467 // on standby. Therefore, we may return an error even though the
3468 // pcm stream is still opened.
3469 if (in->standby) {
3470 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
3471 "%s stream in standby but pcm not NULL for non ST session", __func__);
3472 goto exit;
3473 }
Andy Hung6ebe5962016-01-15 17:46:57 -08003474 if (in->pcm) {
3475 struct timespec timestamp;
3476 unsigned int avail;
3477 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3478 *frames = in->frames_read + avail;
3479 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3480 ret = 0;
3481 }
3482 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003483exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08003484 pthread_mutex_unlock(&in->lock);
3485 return ret;
3486}
3487
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003488static int add_remove_audio_effect(const struct audio_stream *stream,
3489 effect_handle_t effect,
3490 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003491{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003492 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003493 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003494 int status = 0;
3495 effect_descriptor_t desc;
3496
3497 status = (*effect)->get_descriptor(effect, &desc);
3498 if (status != 0)
3499 return status;
3500
Eric Laurenta1478072015-09-21 17:21:52 -07003501 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003502 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003503 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003504 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003505 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003506 in->enable_aec != enable &&
3507 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3508 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003509 if (!enable)
3510 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003511 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3512 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3513 adev->enable_voicerx = enable;
3514 struct audio_usecase *usecase;
3515 struct listnode *node;
3516 list_for_each(node, &adev->usecase_list) {
3517 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07003518 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07003519 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05003520 }
3521 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003522 if (!in->standby)
3523 select_devices(in->dev, in->usecase);
3524 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003525 if (in->enable_ns != enable &&
3526 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3527 in->enable_ns = enable;
3528 if (!in->standby)
3529 select_devices(in->dev, in->usecase);
3530 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003531 pthread_mutex_unlock(&in->dev->lock);
3532 pthread_mutex_unlock(&in->lock);
3533
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003534 return 0;
3535}
3536
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003537static int in_add_audio_effect(const struct audio_stream *stream,
3538 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003539{
Eric Laurent994a6932013-07-17 11:51:42 -07003540 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003541 return add_remove_audio_effect(stream, effect, true);
3542}
3543
3544static int in_remove_audio_effect(const struct audio_stream *stream,
3545 effect_handle_t effect)
3546{
Eric Laurent994a6932013-07-17 11:51:42 -07003547 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003548 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003549}
3550
Eric Laurent0e46adf2016-12-16 12:49:24 -08003551static int in_stop(const struct audio_stream_in* stream)
3552{
3553 struct stream_in *in = (struct stream_in *)stream;
3554 struct audio_device *adev = in->dev;
3555
3556 int ret = -ENOSYS;
3557 ALOGV("%s", __func__);
3558 pthread_mutex_lock(&adev->lock);
3559 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3560 in->capture_started && in->pcm != NULL) {
3561 pcm_stop(in->pcm);
3562 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003563 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003564 }
3565 pthread_mutex_unlock(&adev->lock);
3566 return ret;
3567}
3568
3569static int in_start(const struct audio_stream_in* stream)
3570{
3571 struct stream_in *in = (struct stream_in *)stream;
3572 struct audio_device *adev = in->dev;
3573 int ret = -ENOSYS;
3574
3575 ALOGV("%s in %p", __func__, in);
3576 pthread_mutex_lock(&adev->lock);
3577 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3578 !in->capture_started && in->pcm != NULL) {
3579 if (!in->capture_started) {
3580 ret = start_input_stream(in);
3581 if (ret == 0) {
3582 in->capture_started = true;
3583 }
3584 }
3585 }
3586 pthread_mutex_unlock(&adev->lock);
3587 return ret;
3588}
3589
3590static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3591 int32_t min_size_frames,
3592 struct audio_mmap_buffer_info *info)
3593{
3594 struct stream_in *in = (struct stream_in *)stream;
3595 struct audio_device *adev = in->dev;
3596 int ret = 0;
3597 unsigned int offset1;
3598 unsigned int frames1;
3599 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003600 uint32_t mmap_size;
3601 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003602
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003603 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003604 pthread_mutex_lock(&adev->lock);
3605 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003606
Eric Laurent0e46adf2016-12-16 12:49:24 -08003607 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003608 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003609 ret = -EINVAL;
3610 goto exit;
3611 }
3612 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003613 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003614 ALOGV("%s in %p", __func__, in);
3615 ret = -ENOSYS;
3616 goto exit;
3617 }
3618 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3619 if (in->pcm_device_id < 0) {
3620 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3621 __func__, in->pcm_device_id, in->usecase);
3622 ret = -EINVAL;
3623 goto exit;
3624 }
Phil Burkbc991042017-02-24 08:06:44 -08003625
3626 adjust_mmap_period_count(&in->config, min_size_frames);
3627
Eric Laurent0e46adf2016-12-16 12:49:24 -08003628 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3629 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3630 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3631 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3632 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3633 step = "open";
3634 ret = -ENODEV;
3635 goto exit;
3636 }
3637
3638 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3639 if (ret < 0) {
3640 step = "begin";
3641 goto exit;
3642 }
3643 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003644 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003645 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003646 ret = platform_get_mmap_data_fd(adev->platform,
3647 in->pcm_device_id, 1 /*capture*/,
3648 &info->shared_memory_fd,
3649 &mmap_size);
3650 if (ret < 0) {
3651 // Fall back to non exclusive mode
3652 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3653 } else {
3654 if (mmap_size < buffer_size) {
3655 step = "mmap";
3656 goto exit;
3657 }
3658 // FIXME: indicate exclusive mode support by returning a negative buffer size
3659 info->buffer_size_frames *= -1;
3660 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08003661
Haynes Mathew George96483a22017-03-28 14:52:47 -07003662 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003663
3664 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3665 if (ret < 0) {
3666 step = "commit";
3667 goto exit;
3668 }
3669
Phil Burkbc991042017-02-24 08:06:44 -08003670 in->standby = false;
3671 ret = 0;
3672
Eric Laurent0e46adf2016-12-16 12:49:24 -08003673 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3674 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003675
3676exit:
3677 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003678 if (in->pcm == NULL) {
3679 ALOGE("%s: %s - %d", __func__, step, ret);
3680 } else {
3681 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003682 pcm_close(in->pcm);
3683 in->pcm = NULL;
3684 }
3685 }
3686 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003687 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003688 return ret;
3689}
3690
3691static int in_get_mmap_position(const struct audio_stream_in *stream,
3692 struct audio_mmap_position *position)
3693{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003694 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003695 struct stream_in *in = (struct stream_in *)stream;
3696 ALOGVV("%s", __func__);
3697 if (position == NULL) {
3698 return -EINVAL;
3699 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003700 lock_input_stream(in);
3701 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
3702 in->pcm == NULL) {
3703 ret = -ENOSYS;
3704 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003705 }
3706 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003707 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003708 if (ret < 0) {
3709 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003710 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003711 }
Andy Hungfc044e12017-03-20 09:24:22 -07003712 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003713exit:
3714 pthread_mutex_unlock(&in->lock);
3715 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003716}
3717
3718
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003719static int adev_open_output_stream(struct audio_hw_device *dev,
3720 audio_io_handle_t handle,
3721 audio_devices_t devices,
3722 audio_output_flags_t flags,
3723 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003724 struct audio_stream_out **stream_out,
3725 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003726{
3727 struct audio_device *adev = (struct audio_device *)dev;
3728 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003729 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003730 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
3731 bool is_usb_dev = audio_is_usb_out_device(devices) &&
3732 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003733
Andy Hungd9653bd2017-08-01 19:31:39 -07003734 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
3735 return -ENOSYS;
3736 }
3737
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003738 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
3739 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003740 *stream_out = NULL;
3741 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3742
3743 if (devices == AUDIO_DEVICE_NONE)
3744 devices = AUDIO_DEVICE_OUT_SPEAKER;
3745
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003746 out->flags = flags;
3747 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003748 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003749 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003750 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003751
3752 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003753 if ((is_hdmi || is_usb_dev) &&
3754 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
3755 (flags == AUDIO_OUTPUT_FLAG_NONE ||
3756 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003757 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003758 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003759 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003760 if (config->sample_rate == 0)
3761 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3762 if (config->channel_mask == 0)
3763 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3764 if (config->format == AUDIO_FORMAT_DEFAULT)
3765 config->format = AUDIO_FORMAT_PCM_16_BIT;
3766 } else if (is_usb_dev) {
3767 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
3768 &config->format,
3769 &out->supported_formats[0],
3770 MAX_SUPPORTED_FORMATS,
3771 &config->channel_mask,
3772 &out->supported_channel_masks[0],
3773 MAX_SUPPORTED_CHANNEL_MASKS,
3774 &config->sample_rate,
3775 &out->supported_sample_rates[0],
3776 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003777 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003778 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003779 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003780 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003781 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003782
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003783
Haynes Mathew George569b7482017-05-08 14:44:27 -07003784 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003785 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003786 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003787 if (is_hdmi) {
3788 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3789 out->config = pcm_config_hdmi_multi;
3790 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3791 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3792 out->config = pcm_config_mmap_playback;
3793 out->stream.start = out_start;
3794 out->stream.stop = out_stop;
3795 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3796 out->stream.get_mmap_position = out_get_mmap_position;
3797 } else {
3798 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3799 out->config = pcm_config_hifi;
3800 }
3801
3802 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003803 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003804 if (is_hdmi) {
3805 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
3806 audio_bytes_per_sample(out->format));
3807 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003808 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003809 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003810 pthread_mutex_lock(&adev->lock);
3811 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3812 pthread_mutex_unlock(&adev->lock);
3813
3814 // reject offload during card offline to allow
3815 // fallback to s/w paths
3816 if (offline) {
3817 ret = -ENODEV;
3818 goto error_open;
3819 }
3820
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003821 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3822 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3823 ALOGE("%s: Unsupported Offload information", __func__);
3824 ret = -EINVAL;
3825 goto error_open;
3826 }
3827 if (!is_supported_format(config->offload_info.format)) {
3828 ALOGE("%s: Unsupported audio format", __func__);
3829 ret = -EINVAL;
3830 goto error_open;
3831 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003832 out->sample_rate = config->offload_info.sample_rate;
3833 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
3834 out->channel_mask = config->offload_info.channel_mask;
3835 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
3836 out->channel_mask = config->channel_mask;
3837 else
3838 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3839
3840 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003841
3842 out->compr_config.codec = (struct snd_codec *)
3843 calloc(1, sizeof(struct snd_codec));
3844
3845 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003846
3847 out->stream.set_callback = out_set_callback;
3848 out->stream.pause = out_pause;
3849 out->stream.resume = out_resume;
3850 out->stream.drain = out_drain;
3851 out->stream.flush = out_flush;
3852
3853 out->compr_config.codec->id =
3854 get_snd_codec_id(config->offload_info.format);
3855 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3856 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003857 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003858 out->compr_config.codec->bit_rate =
3859 config->offload_info.bit_rate;
3860 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003861 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003862 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3863
3864 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3865 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003866
3867 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003868 create_offload_callback_thread(out);
3869 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3870 __func__, config->offload_info.version,
3871 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02003872 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3873 switch (config->sample_rate) {
3874 case 0:
3875 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3876 break;
3877 case 8000:
3878 case 16000:
3879 case 48000:
3880 out->sample_rate = config->sample_rate;
3881 break;
3882 default:
3883 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
3884 config->sample_rate);
3885 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3886 ret = -EINVAL;
3887 goto error_open;
3888 }
3889 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
3890 switch (config->channel_mask) {
3891 case AUDIO_CHANNEL_NONE:
3892 case AUDIO_CHANNEL_OUT_STEREO:
3893 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3894 break;
3895 default:
3896 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
3897 config->channel_mask);
3898 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3899 ret = -EINVAL;
3900 goto error_open;
3901 }
3902 switch (config->format) {
3903 case AUDIO_FORMAT_DEFAULT:
3904 case AUDIO_FORMAT_PCM_16_BIT:
3905 out->format = AUDIO_FORMAT_PCM_16_BIT;
3906 break;
3907 default:
3908 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
3909 config->format);
3910 config->format = AUDIO_FORMAT_PCM_16_BIT;
3911 ret = -EINVAL;
3912 goto error_open;
3913 }
3914
3915 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003916 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07003917 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003918 case 0:
3919 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
3920 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07003921 case 8000:
3922 case 16000:
3923 case 48000:
3924 out->sample_rate = config->sample_rate;
3925 break;
3926 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003927 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
3928 config->sample_rate);
3929 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3930 ret = -EINVAL;
3931 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003932 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003933 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
3934 switch (config->channel_mask) {
3935 case AUDIO_CHANNEL_NONE:
3936 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3937 break;
3938 case AUDIO_CHANNEL_OUT_STEREO:
3939 out->channel_mask = config->channel_mask;
3940 break;
3941 default:
3942 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
3943 config->channel_mask);
3944 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3945 ret = -EINVAL;
3946 break;
3947 }
3948 switch (config->format) {
3949 case AUDIO_FORMAT_DEFAULT:
3950 out->format = AUDIO_FORMAT_PCM_16_BIT;
3951 break;
3952 case AUDIO_FORMAT_PCM_16_BIT:
3953 out->format = config->format;
3954 break;
3955 default:
3956 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
3957 config->format);
3958 config->format = AUDIO_FORMAT_PCM_16_BIT;
3959 ret = -EINVAL;
3960 break;
3961 }
3962 if (ret != 0)
3963 goto error_open;
3964
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003965 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3966 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003967 out->config.rate = out->sample_rate;
3968 out->config.channels =
3969 audio_channel_count_from_out_mask(out->channel_mask);
3970 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003971 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003972 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
3973 switch (config->sample_rate) {
3974 case 0:
3975 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3976 break;
3977 case 8000:
3978 case 16000:
3979 case 32000:
3980 case 48000:
3981 out->sample_rate = config->sample_rate;
3982 break;
3983 default:
3984 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
3985 config->sample_rate);
3986 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3987 ret = -EINVAL;
3988 break;
3989 }
Eric Laurentad2dde92017-09-20 18:27:31 -07003990 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003991 switch (config->channel_mask) {
3992 case AUDIO_CHANNEL_NONE:
3993 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3994 break;
3995 case AUDIO_CHANNEL_OUT_STEREO:
3996 out->channel_mask = config->channel_mask;
3997 break;
3998 default:
3999 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
4000 config->channel_mask);
4001 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4002 ret = -EINVAL;
4003 break;
4004 }
4005 switch (config->format) {
4006 case AUDIO_FORMAT_DEFAULT:
4007 out->format = AUDIO_FORMAT_PCM_16_BIT;
4008 break;
4009 case AUDIO_FORMAT_PCM_16_BIT:
4010 out->format = config->format;
4011 break;
4012 default:
4013 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
4014 config->format);
4015 config->format = AUDIO_FORMAT_PCM_16_BIT;
4016 ret = -EINVAL;
4017 break;
4018 }
4019 if (ret != 0)
4020 goto error_open;
4021
vivek mehtaa68fea62017-06-08 19:04:02 -07004022 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07004023 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4024 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004025 out->config.rate = out->sample_rate;
4026 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07004027 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004028 out->sample_rate,
4029 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07004030 out->config.channels,
4031 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004032 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07004033 out->config.period_size = buffer_size / frame_size;
4034 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
4035 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004036 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004037 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07004038 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4039 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004040 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07004041 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
4042 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004043 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07004044 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004045 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004046 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004047 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004048 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4049 out->config = pcm_config_mmap_playback;
4050 out->stream.start = out_start;
4051 out->stream.stop = out_stop;
4052 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4053 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004054 } else {
4055 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4056 out->config = pcm_config_low_latency;
4057 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004058
4059 if (config->sample_rate == 0) {
4060 out->sample_rate = out->config.rate;
4061 } else {
4062 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004063 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004064 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
4065 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
4066 } else {
4067 out->channel_mask = config->channel_mask;
4068 }
4069 if (config->format == AUDIO_FORMAT_DEFAULT)
4070 out->format = audio_format_from_pcm_format(out->config.format);
4071 else if (!audio_is_linear_pcm(config->format)) {
4072 config->format = AUDIO_FORMAT_PCM_16_BIT;
4073 ret = -EINVAL;
4074 goto error_open;
4075 } else {
4076 out->format = config->format;
4077 }
4078
4079 out->config.rate = out->sample_rate;
4080 out->config.channels =
4081 audio_channel_count_from_out_mask(out->channel_mask);
4082 if (out->format != audio_format_from_pcm_format(out->config.format)) {
4083 out->config.format = pcm_format_from_audio_format(out->format);
4084 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004085 }
Kevin Rocard50eff892017-05-02 16:52:05 -07004086
4087 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
4088 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004089 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004090 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
4091 __func__, config->sample_rate, config->format, config->channel_mask);
4092 config->sample_rate = out->sample_rate;
4093 config->format = out->format;
4094 config->channel_mask = out->channel_mask;
4095 ret = -EINVAL;
4096 goto error_open;
4097 }
4098
Andy Hung6fcba9c2014-03-18 11:53:32 -07004099 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
4100 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004101
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004102 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004103 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004104 adev->primary_output = out;
4105 else {
4106 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004107 ret = -EEXIST;
4108 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004109 }
4110 }
4111
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004112 /* Check if this usecase is already existing */
4113 pthread_mutex_lock(&adev->lock);
4114 if (get_usecase_from_list(adev, out->usecase) != NULL) {
4115 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004116 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004117 ret = -EEXIST;
4118 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004119 }
4120 pthread_mutex_unlock(&adev->lock);
4121
4122 out->stream.common.get_sample_rate = out_get_sample_rate;
4123 out->stream.common.set_sample_rate = out_set_sample_rate;
4124 out->stream.common.get_buffer_size = out_get_buffer_size;
4125 out->stream.common.get_channels = out_get_channels;
4126 out->stream.common.get_format = out_get_format;
4127 out->stream.common.set_format = out_set_format;
4128 out->stream.common.standby = out_standby;
4129 out->stream.common.dump = out_dump;
4130 out->stream.common.set_parameters = out_set_parameters;
4131 out->stream.common.get_parameters = out_get_parameters;
4132 out->stream.common.add_audio_effect = out_add_audio_effect;
4133 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4134 out->stream.get_latency = out_get_latency;
4135 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004136#ifdef NO_AUDIO_OUT
4137 out->stream.write = out_write_for_no_output;
4138#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004139 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004140#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004141 out->stream.get_render_position = out_get_render_position;
4142 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004143 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004144
Eric Laurent0e46adf2016-12-16 12:49:24 -08004145 if (out->realtime)
4146 out->af_period_multiplier = af_period_multiplier;
4147 else
4148 out->af_period_multiplier = 1;
4149
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004150 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004151 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004152 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004153
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004154 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004155 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004156 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4157
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004158 config->format = out->stream.common.get_format(&out->stream.common);
4159 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4160 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4161
Andy Hunga452b0a2017-03-15 14:51:15 -07004162 out->error_log = error_log_create(
4163 ERROR_LOG_ENTRIES,
4164 1000000000 /* aggregate consecutive identical errors within one second in ns */);
4165
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004166 /*
4167 By locking output stream before registering, we allow the callback
4168 to update stream's state only after stream's initial state is set to
4169 adev state.
4170 */
4171 lock_output_stream(out);
4172 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4173 pthread_mutex_lock(&adev->lock);
4174 out->card_status = adev->card_status;
4175 pthread_mutex_unlock(&adev->lock);
4176 pthread_mutex_unlock(&out->lock);
4177
vivek mehta4a824772017-06-08 19:05:49 -07004178 stream_app_type_cfg_init(&out->app_type_cfg);
4179
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004180 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004181
Eric Laurent994a6932013-07-17 11:51:42 -07004182 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004183 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004184
4185error_open:
4186 free(out);
4187 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07004188 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004189 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004190}
4191
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004192static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004193 struct audio_stream_out *stream)
4194{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004195 struct stream_out *out = (struct stream_out *)stream;
4196 struct audio_device *adev = out->dev;
4197
Eric Laurent994a6932013-07-17 11:51:42 -07004198 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004199
4200 // must deregister from sndmonitor first to prevent races
4201 // between the callback and close_stream
4202 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004203 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004204 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
4205 destroy_offload_callback_thread(out);
4206
4207 if (out->compr_config.codec != NULL)
4208 free(out->compr_config.codec);
4209 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004210
4211 if (adev->voice_tx_output == out)
4212 adev->voice_tx_output = NULL;
4213
Andy Hunga452b0a2017-03-15 14:51:15 -07004214 error_log_destroy(out->error_log);
4215 out->error_log = NULL;
4216
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004217 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004218 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004219 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004220 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004221 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004222}
4223
4224static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4225{
4226 struct audio_device *adev = (struct audio_device *)dev;
4227 struct str_parms *parms;
4228 char *str;
4229 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004230 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004231 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07004232 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004233
Joe Onorato188b6222016-03-01 11:02:27 -08004234 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004235
4236 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004237
4238 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004239 status = voice_set_parameters(adev, parms);
4240 if (status != 0) {
4241 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004242 }
4243
4244 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4245 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07004246 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004247 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4248 adev->bluetooth_nrec = true;
4249 else
4250 adev->bluetooth_nrec = false;
4251 }
4252
4253 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4254 if (ret >= 0) {
4255 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4256 adev->screen_off = false;
4257 else
4258 adev->screen_off = true;
4259 }
4260
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004261 ret = str_parms_get_int(parms, "rotation", &val);
4262 if (ret >= 0) {
4263 bool reverse_speakers = false;
4264 switch(val) {
4265 // FIXME: note that the code below assumes that the speakers are in the correct placement
4266 // relative to the user when the device is rotated 90deg from its default rotation. This
4267 // assumption is device-specific, not platform-specific like this code.
4268 case 270:
4269 reverse_speakers = true;
4270 break;
4271 case 0:
4272 case 90:
4273 case 180:
4274 break;
4275 default:
4276 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07004277 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004278 }
Eric Laurent03f09432014-03-25 18:09:11 -07004279 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004280 // check and set swap
4281 // - check if orientation changed and speaker active
4282 // - set rotation and cache the rotation value
4283 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004284 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004285 }
4286
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004287 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4288 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004289 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004290 }
4291
David Linee3fe402017-03-13 10:00:42 -07004292 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4293 if (ret >= 0) {
4294 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004295 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004296 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4297 if (ret >= 0) {
4298 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004299 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004300 }
Eric Laurent99dab492017-06-17 15:19:08 -07004301 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004302 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4303 if (ret >= 0) {
4304 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004305 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004306 }
4307 }
4308 }
4309
4310 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4311 if (ret >= 0) {
4312 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004313 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004314 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4315 if (ret >= 0) {
4316 const int card = atoi(value);
4317
Eric Laurent99dab492017-06-17 15:19:08 -07004318 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004319 }
Eric Laurent99dab492017-06-17 15:19:08 -07004320 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004321 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4322 if (ret >= 0) {
4323 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004324 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004325 }
4326 }
4327 }
4328
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004329 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004330done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004331 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004332 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004333 ALOGV("%s: exit with code(%d)", __func__, status);
4334 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004335}
4336
4337static char* adev_get_parameters(const struct audio_hw_device *dev,
4338 const char *keys)
4339{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004340 struct audio_device *adev = (struct audio_device *)dev;
4341 struct str_parms *reply = str_parms_create();
4342 struct str_parms *query = str_parms_create_str(keys);
4343 char *str;
4344
4345 pthread_mutex_lock(&adev->lock);
4346
4347 voice_get_parameters(adev, query, reply);
4348 str = str_parms_to_str(reply);
4349 str_parms_destroy(query);
4350 str_parms_destroy(reply);
4351
4352 pthread_mutex_unlock(&adev->lock);
4353 ALOGV("%s: exit: returns - %s", __func__, str);
4354 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004355}
4356
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004357static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004358{
4359 return 0;
4360}
4361
Haynes Mathew George5191a852013-09-11 14:19:36 -07004362static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4363{
4364 int ret;
4365 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004366
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004367 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4368
Haynes Mathew George5191a852013-09-11 14:19:36 -07004369 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004370 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004371 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004372
Haynes Mathew George5191a852013-09-11 14:19:36 -07004373 return ret;
4374}
4375
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004376static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004377{
4378 return -ENOSYS;
4379}
4380
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004381static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4382 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004383{
4384 return -ENOSYS;
4385}
4386
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004387static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004388{
4389 return -ENOSYS;
4390}
4391
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004392static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004393{
4394 return -ENOSYS;
4395}
4396
4397static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4398{
4399 struct audio_device *adev = (struct audio_device *)dev;
4400
4401 pthread_mutex_lock(&adev->lock);
4402 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004403 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004404 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004405 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4406 voice_is_in_call(adev)) {
4407 voice_stop_call(adev);
4408 adev->current_call_output = NULL;
4409 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004410 }
4411 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004412
4413 audio_extn_extspk_set_mode(adev->extspk, mode);
4414
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004415 return 0;
4416}
4417
4418static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4419{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004420 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004421 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004422
Eric Laurent2bafff12016-03-17 12:17:23 -07004423 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004424 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004425 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4426 ret = audio_extn_hfp_set_mic_mute(adev, state);
4427 } else {
4428 ret = voice_set_mic_mute(adev, state);
4429 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004430 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004431 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004432
4433 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004434}
4435
4436static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4437{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004438 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004439 return 0;
4440}
4441
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004442static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004443 const struct audio_config *config)
4444{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004445 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004446
Eric Laurent74b55762017-07-09 17:04:53 -07004447 /* Don't know if USB HIFI in this context so use true to be conservative */
4448 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4449 true /*is_usb_hifi */) != 0)
4450 return 0;
4451
vivek mehtaa68fea62017-06-08 19:04:02 -07004452 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4453 config->sample_rate, config->format,
4454 channel_count,
4455 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004456}
4457
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004458static bool adev_input_allow_hifi_record(struct audio_device *adev,
4459 audio_devices_t devices,
4460 audio_input_flags_t flags,
4461 audio_source_t source) {
4462 const bool allowed = true;
4463
4464 if (!audio_is_usb_in_device(devices))
4465 return !allowed;
4466
4467 switch (flags) {
4468 case AUDIO_INPUT_FLAG_NONE:
4469 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4470 break;
4471 default:
4472 return !allowed;
4473 }
4474
4475 switch (source) {
4476 case AUDIO_SOURCE_DEFAULT:
4477 case AUDIO_SOURCE_MIC:
4478 case AUDIO_SOURCE_UNPROCESSED:
4479 break;
4480 default:
4481 return !allowed;
4482 }
4483
4484 switch (adev->mode) {
4485 case 0:
4486 break;
4487 default:
4488 return !allowed;
4489 }
4490
4491 return allowed;
4492}
4493
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004494static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004495 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004496 audio_devices_t devices,
4497 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004498 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004499 audio_input_flags_t flags,
4500 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004501 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004502{
4503 struct audio_device *adev = (struct audio_device *)dev;
4504 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004505 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004506 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004507 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004508 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004509 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4510 devices,
4511 flags,
4512 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004513 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004514 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004515
Andy Hungd9653bd2017-08-01 19:31:39 -07004516 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
4517 return -ENOSYS;
4518 }
4519
Eric Laurent74b55762017-07-09 17:04:53 -07004520 if (!(is_usb_dev && may_use_hifi_record)) {
4521 if (config->sample_rate == 0)
4522 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4523 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4524 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4525 if (config->format == AUDIO_FORMAT_DEFAULT)
4526 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004527
Eric Laurent74b55762017-07-09 17:04:53 -07004528 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
4529
4530 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
4531 return -EINVAL;
4532 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004533
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004534 if (audio_extn_tfa_98xx_is_supported() &&
4535 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004536 return -EINVAL;
4537
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004538 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4539
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004540 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004541 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004542
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004543 in->stream.common.get_sample_rate = in_get_sample_rate;
4544 in->stream.common.set_sample_rate = in_set_sample_rate;
4545 in->stream.common.get_buffer_size = in_get_buffer_size;
4546 in->stream.common.get_channels = in_get_channels;
4547 in->stream.common.get_format = in_get_format;
4548 in->stream.common.set_format = in_set_format;
4549 in->stream.common.standby = in_standby;
4550 in->stream.common.dump = in_dump;
4551 in->stream.common.set_parameters = in_set_parameters;
4552 in->stream.common.get_parameters = in_get_parameters;
4553 in->stream.common.add_audio_effect = in_add_audio_effect;
4554 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4555 in->stream.set_gain = in_set_gain;
4556 in->stream.read = in_read;
4557 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08004558 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004559
4560 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004561 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004562 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004563 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004564 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004565 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004566
Haynes Mathew George569b7482017-05-08 14:44:27 -07004567 if (is_usb_dev && may_use_hifi_record) {
4568 /* HiFi record selects an appropriate format, channel, rate combo
4569 depending on sink capabilities*/
4570 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
4571 &config->format,
4572 &in->supported_formats[0],
4573 MAX_SUPPORTED_FORMATS,
4574 &config->channel_mask,
4575 &in->supported_channel_masks[0],
4576 MAX_SUPPORTED_CHANNEL_MASKS,
4577 &config->sample_rate,
4578 &in->supported_sample_rates[0],
4579 MAX_SUPPORTED_SAMPLE_RATES);
4580 if (ret != 0) {
4581 ret = -EINVAL;
4582 goto err_open;
4583 }
Eric Laurent74b55762017-07-09 17:04:53 -07004584 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004585 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07004586 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07004587 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
4588 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
4589 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4590 bool ret_error = false;
4591 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4592 from HAL is 8_24
4593 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4594 8_24 return error indicating supported format is 8_24
4595 *> In case of any other source requesting 24 bit or float return error
4596 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07004597
vivek mehta57ff9b52016-04-28 14:13:08 -07004598 on error flinger will retry with supported format passed
4599 */
4600 if (source != AUDIO_SOURCE_UNPROCESSED) {
4601 config->format = AUDIO_FORMAT_PCM_16_BIT;
4602 ret_error = true;
4603 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
4604 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
4605 ret_error = true;
4606 }
4607
4608 if (ret_error) {
4609 ret = -EINVAL;
4610 goto err_open;
4611 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004612 }
4613
vivek mehta57ff9b52016-04-28 14:13:08 -07004614 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07004615 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07004616
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004617 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004618 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
4619 if (config->sample_rate == 0)
4620 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4621 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4622 config->sample_rate != 8000) {
4623 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4624 ret = -EINVAL;
4625 goto err_open;
4626 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004627
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004628 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4629 config->format = AUDIO_FORMAT_PCM_16_BIT;
4630 ret = -EINVAL;
4631 goto err_open;
4632 }
4633
4634 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4635 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07004636 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004637 } else if (is_usb_dev && may_use_hifi_record) {
4638 in->usecase = USECASE_AUDIO_RECORD_HIFI;
4639 in->config = pcm_config_audio_capture;
4640 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004641 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4642 config->sample_rate,
4643 config->format,
4644 channel_count,
4645 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004646 in->config.period_size = buffer_size / frame_size;
4647 in->config.rate = config->sample_rate;
4648 in->af_period_multiplier = 1;
4649 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004650 } else {
4651 in->usecase = USECASE_AUDIO_RECORD;
4652 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08004653 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004654 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07004655#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004656 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07004657#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08004658 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004659 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08004660 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004661 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004662 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4663 config->sample_rate,
4664 config->format,
4665 channel_count,
4666 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004667 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004668 in->config.rate = config->sample_rate;
4669 in->af_period_multiplier = 1;
4670 } else {
4671 // period size is left untouched for rt mode playback
4672 in->config = pcm_config_audio_capture_rt;
4673 in->af_period_multiplier = af_period_multiplier;
4674 }
4675 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
4676 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004677 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08004678 in->usecase = USECASE_AUDIO_RECORD_MMAP;
4679 in->config = pcm_config_mmap_capture;
4680 in->stream.start = in_start;
4681 in->stream.stop = in_stop;
4682 in->stream.create_mmap_buffer = in_create_mmap_buffer;
4683 in->stream.get_mmap_position = in_get_mmap_position;
4684 in->af_period_multiplier = 1;
4685 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07004686 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07004687 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07004688 (config->sample_rate == 8000 ||
4689 config->sample_rate == 16000 ||
4690 config->sample_rate == 32000 ||
4691 config->sample_rate == 48000) &&
4692 channel_count == 1) {
4693 in->usecase = USECASE_AUDIO_RECORD_VOIP;
4694 in->config = pcm_config_audio_capture;
4695 frame_size = audio_stream_in_frame_size(&in->stream);
4696 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
4697 config->sample_rate,
4698 config->format,
4699 channel_count, false /*is_low_latency*/);
4700 in->config.period_size = buffer_size / frame_size;
4701 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
4702 in->config.rate = config->sample_rate;
4703 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004704 } else {
4705 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004706 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004707 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4708 config->sample_rate,
4709 config->format,
4710 channel_count,
4711 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004712 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004713 in->config.rate = config->sample_rate;
4714 in->af_period_multiplier = 1;
4715 }
4716 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
4717 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004718 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004719
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004720 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07004721 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004722
Andy Hungd13f0d32017-06-12 13:58:37 -07004723 in->error_log = error_log_create(
4724 ERROR_LOG_ENTRIES,
4725 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
4726
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004727 /* This stream could be for sound trigger lab,
4728 get sound trigger pcm if present */
4729 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004730
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004731 lock_input_stream(in);
4732 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
4733 pthread_mutex_lock(&adev->lock);
4734 in->card_status = adev->card_status;
4735 pthread_mutex_unlock(&adev->lock);
4736 pthread_mutex_unlock(&in->lock);
4737
vivek mehta4a824772017-06-08 19:05:49 -07004738 stream_app_type_cfg_init(&in->app_type_cfg);
4739
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004740 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004741 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004742 return 0;
4743
4744err_open:
4745 free(in);
4746 *stream_in = NULL;
4747 return ret;
4748}
4749
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004750static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004751 struct audio_stream_in *stream)
4752{
Andy Hungd13f0d32017-06-12 13:58:37 -07004753 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004754 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004755
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004756 // must deregister from sndmonitor first to prevent races
4757 // between the callback and close_stream
4758 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004759 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07004760
4761 error_log_destroy(in->error_log);
4762 in->error_log = NULL;
4763
Andy Hung0dbb52b2017-08-09 13:51:38 -07004764 pthread_mutex_destroy(&in->pre_lock);
4765 pthread_mutex_destroy(&in->lock);
4766
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004767 free(stream);
4768
4769 return;
4770}
4771
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004772static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004773{
4774 return 0;
4775}
4776
Andy Hung31aca912014-03-20 17:14:59 -07004777/* verifies input and output devices and their capabilities.
4778 *
4779 * This verification is required when enabling extended bit-depth or
4780 * sampling rates, as not all qcom products support it.
4781 *
4782 * Suitable for calling only on initialization such as adev_open().
4783 * It fills the audio_device use_case_table[] array.
4784 *
4785 * Has a side-effect that it needs to configure audio routing / devices
4786 * in order to power up the devices and read the device parameters.
4787 * It does not acquire any hw device lock. Should restore the devices
4788 * back to "normal state" upon completion.
4789 */
4790static int adev_verify_devices(struct audio_device *adev)
4791{
4792 /* enumeration is a bit difficult because one really wants to pull
4793 * the use_case, device id, etc from the hidden pcm_device_table[].
4794 * In this case there are the following use cases and device ids.
4795 *
4796 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
4797 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004798 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07004799 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
4800 * [USECASE_AUDIO_RECORD] = {0, 0},
4801 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
4802 * [USECASE_VOICE_CALL] = {2, 2},
4803 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004804 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07004805 * USECASE_VOICE_CALL omitted, but possible for either input or output.
4806 */
4807
4808 /* should be the usecases enabled in adev_open_input_stream() */
4809 static const int test_in_usecases[] = {
4810 USECASE_AUDIO_RECORD,
4811 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
4812 };
4813 /* should be the usecases enabled in adev_open_output_stream()*/
4814 static const int test_out_usecases[] = {
4815 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
4816 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
4817 };
4818 static const usecase_type_t usecase_type_by_dir[] = {
4819 PCM_PLAYBACK,
4820 PCM_CAPTURE,
4821 };
4822 static const unsigned flags_by_dir[] = {
4823 PCM_OUT,
4824 PCM_IN,
4825 };
4826
4827 size_t i;
4828 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004829 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07004830 char info[512]; /* for possible debug info */
4831
4832 for (dir = 0; dir < 2; ++dir) {
4833 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
4834 const unsigned flags_dir = flags_by_dir[dir];
4835 const size_t testsize =
4836 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
4837 const int *testcases =
4838 dir ? test_in_usecases : test_out_usecases;
4839 const audio_devices_t audio_device =
4840 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
4841
4842 for (i = 0; i < testsize; ++i) {
4843 const audio_usecase_t audio_usecase = testcases[i];
4844 int device_id;
4845 snd_device_t snd_device;
4846 struct pcm_params **pparams;
4847 struct stream_out out;
4848 struct stream_in in;
4849 struct audio_usecase uc_info;
4850 int retval;
4851
4852 pparams = &adev->use_case_table[audio_usecase];
4853 pcm_params_free(*pparams); /* can accept null input */
4854 *pparams = NULL;
4855
4856 /* find the device ID for the use case (signed, for error) */
4857 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
4858 if (device_id < 0)
4859 continue;
4860
4861 /* prepare structures for device probing */
4862 memset(&uc_info, 0, sizeof(uc_info));
4863 uc_info.id = audio_usecase;
4864 uc_info.type = usecase_type;
4865 if (dir) {
4866 adev->active_input = &in;
4867 memset(&in, 0, sizeof(in));
4868 in.device = audio_device;
4869 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4870 uc_info.stream.in = &in;
4871 } else {
4872 adev->active_input = NULL;
4873 }
4874 memset(&out, 0, sizeof(out));
4875 out.devices = audio_device; /* only field needed in select_devices */
4876 uc_info.stream.out = &out;
4877 uc_info.devices = audio_device;
4878 uc_info.in_snd_device = SND_DEVICE_NONE;
4879 uc_info.out_snd_device = SND_DEVICE_NONE;
4880 list_add_tail(&adev->usecase_list, &uc_info.list);
4881
4882 /* select device - similar to start_(in/out)put_stream() */
4883 retval = select_devices(adev, audio_usecase);
4884 if (retval >= 0) {
4885 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4886#if LOG_NDEBUG == 0
4887 if (*pparams) {
4888 ALOGV("%s: (%s) card %d device %d", __func__,
4889 dir ? "input" : "output", card_id, device_id);
4890 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004891 } else {
4892 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4893 }
4894#endif
4895 }
4896
4897 /* deselect device - similar to stop_(in/out)put_stream() */
4898 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004899 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004900 /* 2. Disable the rx device */
4901 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004902 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004903 list_remove(&uc_info.list);
4904 }
4905 }
4906 adev->active_input = NULL; /* restore adev state */
4907 return 0;
4908}
4909
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004910static int adev_close(hw_device_t *device)
4911{
Andy Hung31aca912014-03-20 17:14:59 -07004912 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004913 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004914
4915 if (!adev)
4916 return 0;
4917
4918 pthread_mutex_lock(&adev_init_lock);
4919
4920 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004921 audio_extn_snd_mon_unregister_listener(adev);
4922 audio_extn_tfa_98xx_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004923 audio_route_free(adev->audio_route);
4924 free(adev->snd_dev_ref_cnt);
4925 platform_deinit(adev->platform);
4926 audio_extn_extspk_deinit(adev->extspk);
4927 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004928 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004929 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4930 pcm_params_free(adev->use_case_table[i]);
4931 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004932 if (adev->adm_deinit)
4933 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004934 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004935 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004936 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004937
4938 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004939
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004940 return 0;
4941}
4942
Glenn Kasten4f993392014-05-14 07:30:48 -07004943/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4944 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4945 * just that it _might_ work.
4946 */
4947static int period_size_is_plausible_for_low_latency(int period_size)
4948{
4949 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004950 case 48:
4951 case 96:
4952 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004953 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004954 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004955 case 240:
4956 case 320:
4957 case 480:
4958 return 1;
4959 default:
4960 return 0;
4961 }
4962}
4963
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004964static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4965{
4966 int card;
4967 card_status_t status;
4968
4969 if (!parms)
4970 return;
4971
4972 if (parse_snd_card_status(parms, &card, &status) < 0)
4973 return;
4974
4975 pthread_mutex_lock(&adev->lock);
4976 bool valid_cb = (card == adev->snd_card);
4977 if (valid_cb) {
4978 if (adev->card_status != status) {
4979 adev->card_status = status;
4980 platform_snd_card_update(adev->platform, status);
4981 }
4982 }
4983 pthread_mutex_unlock(&adev->lock);
4984 return;
4985}
4986
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004987static int adev_open(const hw_module_t *module, const char *name,
4988 hw_device_t **device)
4989{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004990 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004991
Eric Laurent2bafff12016-03-17 12:17:23 -07004992 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004993 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004994 pthread_mutex_lock(&adev_init_lock);
4995 if (audio_device_ref_count != 0) {
4996 *device = &adev->device.common;
4997 audio_device_ref_count++;
4998 ALOGV("%s: returning existing instance of adev", __func__);
4999 ALOGV("%s: exit", __func__);
5000 pthread_mutex_unlock(&adev_init_lock);
5001 return 0;
5002 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005003 adev = calloc(1, sizeof(struct audio_device));
5004
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005005 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5006
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005007 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5008 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5009 adev->device.common.module = (struct hw_module_t *)module;
5010 adev->device.common.close = adev_close;
5011
5012 adev->device.init_check = adev_init_check;
5013 adev->device.set_voice_volume = adev_set_voice_volume;
5014 adev->device.set_master_volume = adev_set_master_volume;
5015 adev->device.get_master_volume = adev_get_master_volume;
5016 adev->device.set_master_mute = adev_set_master_mute;
5017 adev->device.get_master_mute = adev_get_master_mute;
5018 adev->device.set_mode = adev_set_mode;
5019 adev->device.set_mic_mute = adev_set_mic_mute;
5020 adev->device.get_mic_mute = adev_get_mic_mute;
5021 adev->device.set_parameters = adev_set_parameters;
5022 adev->device.get_parameters = adev_get_parameters;
5023 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5024 adev->device.open_output_stream = adev_open_output_stream;
5025 adev->device.close_output_stream = adev_close_output_stream;
5026 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005027
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005028 adev->device.close_input_stream = adev_close_input_stream;
5029 adev->device.dump = adev_dump;
5030
5031 /* Set the default route before the PCM stream is opened */
5032 pthread_mutex_lock(&adev->lock);
5033 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005034 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005035 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005036 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005037 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005038 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005039 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005040 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005041 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005042 pthread_mutex_unlock(&adev->lock);
5043
5044 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005045 adev->platform = platform_init(adev);
5046 if (!adev->platform) {
5047 free(adev->snd_dev_ref_cnt);
5048 free(adev);
5049 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5050 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005051 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005052 return -EINVAL;
5053 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05005054 adev->extspk = audio_extn_extspk_init(adev);
5055
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005056 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5057 if (adev->visualizer_lib == NULL) {
5058 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5059 } else {
5060 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5061 adev->visualizer_start_output =
5062 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5063 "visualizer_hal_start_output");
5064 adev->visualizer_stop_output =
5065 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5066 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07005067 }
5068
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005069 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5070 if (adev->offload_effects_lib == NULL) {
5071 ALOGW("%s: DLOPEN failed for %s", __func__,
5072 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5073 } else {
5074 ALOGV("%s: DLOPEN successful for %s", __func__,
5075 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5076 adev->offload_effects_start_output =
5077 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5078 "offload_effects_bundle_hal_start_output");
5079 adev->offload_effects_stop_output =
5080 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5081 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07005082 }
5083
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005084 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5085 if (adev->adm_lib == NULL) {
5086 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5087 } else {
5088 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5089 adev->adm_init = (adm_init_t)
5090 dlsym(adev->adm_lib, "adm_init");
5091 adev->adm_deinit = (adm_deinit_t)
5092 dlsym(adev->adm_lib, "adm_deinit");
5093 adev->adm_register_input_stream = (adm_register_input_stream_t)
5094 dlsym(adev->adm_lib, "adm_register_input_stream");
5095 adev->adm_register_output_stream = (adm_register_output_stream_t)
5096 dlsym(adev->adm_lib, "adm_register_output_stream");
5097 adev->adm_deregister_stream = (adm_deregister_stream_t)
5098 dlsym(adev->adm_lib, "adm_deregister_stream");
5099 adev->adm_request_focus = (adm_request_focus_t)
5100 dlsym(adev->adm_lib, "adm_request_focus");
5101 adev->adm_abandon_focus = (adm_abandon_focus_t)
5102 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08005103 adev->adm_set_config = (adm_set_config_t)
5104 dlsym(adev->adm_lib, "adm_set_config");
5105 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5106 dlsym(adev->adm_lib, "adm_request_focus_v2");
5107 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5108 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5109 adev->adm_on_routing_change = (adm_on_routing_change_t)
5110 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005111 }
5112
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005113 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005114 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005115
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005116 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005117
Andy Hung31aca912014-03-20 17:14:59 -07005118 if (k_enable_extended_precision)
5119 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005120
Glenn Kasten4f993392014-05-14 07:30:48 -07005121 char value[PROPERTY_VALUE_MAX];
5122 int trial;
5123 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5124 trial = atoi(value);
5125 if (period_size_is_plausible_for_low_latency(trial)) {
5126 pcm_config_low_latency.period_size = trial;
5127 pcm_config_low_latency.start_threshold = trial / 4;
5128 pcm_config_low_latency.avail_min = trial / 4;
5129 configured_low_latency_capture_period_size = trial;
5130 }
5131 }
5132 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5133 trial = atoi(value);
5134 if (period_size_is_plausible_for_low_latency(trial)) {
5135 configured_low_latency_capture_period_size = trial;
5136 }
5137 }
5138
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005139 // commented as full set of app type cfg is sent from platform
5140 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005141 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005142
5143 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5144 af_period_multiplier = atoi(value);
5145 if (af_period_multiplier < 0) {
5146 af_period_multiplier = 2;
5147 } else if (af_period_multiplier > 4) {
5148 af_period_multiplier = 4;
5149 }
5150 ALOGV("new period_multiplier = %d", af_period_multiplier);
5151 }
5152
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005153 audio_extn_tfa_98xx_init(adev);
5154
vivek mehta1a9b7c02015-06-25 11:49:38 -07005155 pthread_mutex_unlock(&adev_init_lock);
5156
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005157 if (adev->adm_init)
5158 adev->adm_data = adev->adm_init();
5159
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005160 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005161 audio_extn_snd_mon_init();
5162 pthread_mutex_lock(&adev->lock);
5163 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
5164 adev->card_status = CARD_STATUS_ONLINE;
5165 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005166 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005167
Eric Laurent2bafff12016-03-17 12:17:23 -07005168 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005169 return 0;
5170}
5171
5172static struct hw_module_methods_t hal_module_methods = {
5173 .open = adev_open,
5174};
5175
5176struct audio_module HAL_MODULE_INFO_SYM = {
5177 .common = {
5178 .tag = HARDWARE_MODULE_TAG,
5179 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5180 .hal_api_version = HARDWARE_HAL_API_VERSION,
5181 .id = AUDIO_HARDWARE_MODULE_ID,
5182 .name = "QCOM Audio HAL",
5183 .author = "Code Aurora Forum",
5184 .methods = &hal_module_methods,
5185 },
5186};