blob: 0ea8f145bc5be9a79766ee31a6aad271a1188cd1 [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",
Eric Laurentb23d5282013-05-14 15:27:20 -0700290};
291
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800292
293#define STRING_TO_ENUM(string) { #string, string }
294
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800295struct string_to_enum {
296 const char *name;
297 uint32_t value;
298};
299
Haynes Mathew George569b7482017-05-08 14:44:27 -0700300static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800301 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
302 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
303 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Eric Laurent74b55762017-07-09 17:04:53 -0700304 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
Haynes Mathew George569b7482017-05-08 14:44:27 -0700305 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
Eric Laurent74b55762017-07-09 17:04:53 -0700306 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
307 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
308 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
309 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
310 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
311 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
312 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
313 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
314 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800315};
316
Haynes Mathew George5191a852013-09-11 14:19:36 -0700317static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700318static struct audio_device *adev = NULL;
Andy Hung9e737de2017-05-22 10:51:22 -0700319static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700320static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700321//cache last MBDRC cal step level
322static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700323
Haynes Mathew George03c40102016-01-29 17:57:48 -0800324static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
325 int flags __unused)
326{
327 int dir = 0;
328 switch (uc_id) {
329 case USECASE_AUDIO_RECORD_LOW_LATENCY:
330 dir = 1;
331 case USECASE_AUDIO_PLAYBACK_ULL:
332 break;
333 default:
334 return false;
335 }
336
337 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
338 PCM_PLAYBACK : PCM_CAPTURE);
339 if (adev->adm_is_noirq_avail)
340 return adev->adm_is_noirq_avail(adev->adm_data,
341 adev->snd_card, dev_id, dir);
342 return false;
343}
344
345static void register_out_stream(struct stream_out *out)
346{
347 struct audio_device *adev = out->dev;
348 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
349 return;
350
351 if (!adev->adm_register_output_stream)
352 return;
353
354 adev->adm_register_output_stream(adev->adm_data,
355 out->handle,
356 out->flags);
357
358 if (!adev->adm_set_config)
359 return;
360
361 if (out->realtime) {
362 adev->adm_set_config(adev->adm_data,
363 out->handle,
364 out->pcm, &out->config);
365 }
366}
367
368static void register_in_stream(struct stream_in *in)
369{
370 struct audio_device *adev = in->dev;
371 if (!adev->adm_register_input_stream)
372 return;
373
374 adev->adm_register_input_stream(adev->adm_data,
375 in->capture_handle,
376 in->flags);
377
378 if (!adev->adm_set_config)
379 return;
380
381 if (in->realtime) {
382 adev->adm_set_config(adev->adm_data,
383 in->capture_handle,
384 in->pcm,
385 &in->config);
386 }
387}
388
389static void request_out_focus(struct stream_out *out, long ns)
390{
391 struct audio_device *adev = out->dev;
392
Haynes Mathew George03c40102016-01-29 17:57:48 -0800393 if (adev->adm_request_focus_v2) {
394 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
395 } else if (adev->adm_request_focus) {
396 adev->adm_request_focus(adev->adm_data, out->handle);
397 }
398}
399
400static void request_in_focus(struct stream_in *in, long ns)
401{
402 struct audio_device *adev = in->dev;
403
Haynes Mathew George03c40102016-01-29 17:57:48 -0800404 if (adev->adm_request_focus_v2) {
405 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
406 } else if (adev->adm_request_focus) {
407 adev->adm_request_focus(adev->adm_data, in->capture_handle);
408 }
409}
410
411static void release_out_focus(struct stream_out *out, long ns __unused)
412{
413 struct audio_device *adev = out->dev;
414
415 if (adev->adm_abandon_focus)
416 adev->adm_abandon_focus(adev->adm_data, out->handle);
417}
418
419static void release_in_focus(struct stream_in *in, long ns __unused)
420{
421 struct audio_device *adev = in->dev;
422 if (adev->adm_abandon_focus)
423 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
424}
425
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700426static int parse_snd_card_status(struct str_parms * parms, int * card,
427 card_status_t * status)
428{
429 char value[32]={0};
430 char state[32]={0};
431
432 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
433
434 if (ret < 0)
435 return -1;
436
437 // sscanf should be okay as value is of max length 32.
438 // same as sizeof state.
439 if (sscanf(value, "%d,%s", card, state) < 2)
440 return -1;
441
442 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
443 CARD_STATUS_OFFLINE;
444 return 0;
445}
446
vivek mehta40125092017-08-21 18:48:51 -0700447// always call with adev lock held
448void send_gain_dep_calibration_l() {
449 if (last_known_cal_step >= 0)
450 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
451}
452
vivek mehta1a9b7c02015-06-25 11:49:38 -0700453__attribute__ ((visibility ("default")))
454bool audio_hw_send_gain_dep_calibration(int level) {
455 bool ret_val = false;
456 ALOGV("%s: enter ... ", __func__);
457
458 pthread_mutex_lock(&adev_init_lock);
459
460 if (adev != NULL && adev->platform != NULL) {
461 pthread_mutex_lock(&adev->lock);
vivek mehta40125092017-08-21 18:48:51 -0700462 last_known_cal_step = level;
463 send_gain_dep_calibration_l();
vivek mehta1a9b7c02015-06-25 11:49:38 -0700464 pthread_mutex_unlock(&adev->lock);
465 } else {
466 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
467 }
468
469 pthread_mutex_unlock(&adev_init_lock);
470
471 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
472 return ret_val;
473}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700474
vivek mehtaa8d7c922016-05-25 14:40:44 -0700475__attribute__ ((visibility ("default")))
476int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
477 int table_size) {
478 int ret_val = 0;
479 ALOGV("%s: enter ... ", __func__);
480
481 pthread_mutex_lock(&adev_init_lock);
482 if (adev == NULL) {
483 ALOGW("%s: adev is NULL .... ", __func__);
484 goto done;
485 }
486
487 pthread_mutex_lock(&adev->lock);
488 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
489 pthread_mutex_unlock(&adev->lock);
490done:
491 pthread_mutex_unlock(&adev_init_lock);
492 ALOGV("%s: exit ... ", __func__);
493 return ret_val;
494}
495
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700496static bool is_supported_format(audio_format_t format)
497{
Eric Laurent8251ac82014-07-23 11:00:25 -0700498 switch (format) {
499 case AUDIO_FORMAT_MP3:
500 case AUDIO_FORMAT_AAC_LC:
501 case AUDIO_FORMAT_AAC_HE_V1:
502 case AUDIO_FORMAT_AAC_HE_V2:
503 return true;
504 default:
505 break;
506 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700507 return false;
508}
509
Haynes Mathew George03c40102016-01-29 17:57:48 -0800510static inline bool is_mmap_usecase(audio_usecase_t uc_id)
511{
512 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
513 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
514}
515
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700516static int get_snd_codec_id(audio_format_t format)
517{
518 int id = 0;
519
Eric Laurent8251ac82014-07-23 11:00:25 -0700520 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700521 case AUDIO_FORMAT_MP3:
522 id = SND_AUDIOCODEC_MP3;
523 break;
524 case AUDIO_FORMAT_AAC:
525 id = SND_AUDIOCODEC_AAC;
526 break;
527 default:
528 ALOGE("%s: Unsupported audio format", __func__);
529 }
530
531 return id;
532}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800533
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800534static int audio_ssr_status(struct audio_device *adev)
535{
536 int ret = 0;
537 struct mixer_ctl *ctl;
538 const char *mixer_ctl_name = "Audio SSR Status";
539
540 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
541 ret = mixer_ctl_get_value(ctl, 0);
542 ALOGD("%s: value: %d", __func__, ret);
543 return ret;
544}
545
vivek mehta4a824772017-06-08 19:05:49 -0700546static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
547{
548 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
549}
550
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800551int enable_audio_route(struct audio_device *adev,
552 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800553{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700554 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800555 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800556
557 if (usecase == NULL)
558 return -EINVAL;
559
560 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
561
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800562 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700563 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800564 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700565 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800566
Yamit Mehtae3b99562016-09-16 22:44:00 +0530567 audio_extn_utils_send_app_type_cfg(adev, usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800568 audio_extn_utils_send_audio_calibration(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800569 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500570 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700571 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700572 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800573
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800574 ALOGV("%s: exit", __func__);
575 return 0;
576}
577
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800578int disable_audio_route(struct audio_device *adev,
579 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800580{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700581 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800582 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800583
584 if (usecase == NULL)
585 return -EINVAL;
586
587 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700588 if (usecase->type == PCM_CAPTURE)
589 snd_device = usecase->in_snd_device;
590 else
591 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800592 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500593 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700594 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700595 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800596
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800597 ALOGV("%s: exit", __func__);
598 return 0;
599}
600
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800601int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700602 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800603{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700604 int i, num_devices = 0;
605 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800606 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800607 if (snd_device < SND_DEVICE_MIN ||
608 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800609 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800610 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800611 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700612
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700613 platform_send_audio_calibration(adev->platform, snd_device);
614
vivek mehtade4849c2016-03-03 17:23:38 -0800615 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700616 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700617 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800618 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700619 }
620
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700621 /* due to the possibility of calibration overwrite between listen
622 and audio, notify sound trigger hal before audio calibration is sent */
623 audio_extn_sound_trigger_update_device_status(snd_device,
624 ST_EVENT_SND_DEVICE_BUSY);
625
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700626 if (audio_extn_spkr_prot_is_enabled())
627 audio_extn_spkr_prot_calib_cancel(adev);
628
zhaoyang yin4211fad2015-06-04 21:13:25 +0800629 audio_extn_dsm_feedback_enable(adev, snd_device, true);
630
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700631 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
632 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
633 audio_extn_spkr_prot_is_enabled()) {
634 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800635 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700636 }
637 if (audio_extn_spkr_prot_start_processing(snd_device)) {
638 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800639 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700640 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700641 } else if (platform_can_split_snd_device(snd_device,
642 &num_devices,
643 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700644 for (i = 0; i < num_devices; i++) {
645 enable_snd_device(adev, new_snd_devices[i]);
646 }
vivek mehtab6506412015-08-07 16:55:17 -0700647 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700648 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800649 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
650 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
651 ALOGE(" %s: Invalid sound device returned", __func__);
652 goto on_error;
653 }
Ed Tam70b5c142016-03-21 19:14:29 -0700654
Eric Laurent2e140aa2016-06-30 17:14:46 -0700655 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800656 audio_route_apply_and_update_path(adev->audio_route, device_name);
657 }
658on_success:
659 adev->snd_dev_ref_cnt[snd_device]++;
660 ret_val = 0;
661on_error:
662 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800663}
664
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800665int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700666 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800667{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700668 int i, num_devices = 0;
669 snd_device_t new_snd_devices[2];
670
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800671 if (snd_device < SND_DEVICE_MIN ||
672 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800673 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800674 return -EINVAL;
675 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700676 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
677 ALOGE("%s: device ref cnt is already 0", __func__);
678 return -EINVAL;
679 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800680 audio_extn_tfa_98xx_disable_speaker(snd_device);
681
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700682 adev->snd_dev_ref_cnt[snd_device]--;
683 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800684 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700685 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700686 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700687 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
688 audio_extn_spkr_prot_is_enabled()) {
689 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700690
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700691 // FIXME b/65363602: bullhead is the only Nexus with audio_extn_spkr_prot_is_enabled()
692 // and does not use speaker swap. As this code causes a problem with device enable ref
693 // counting we remove it for now.
vivek mehtae59cfb22017-06-16 15:57:11 -0700694 // when speaker device is disabled, reset swap.
695 // will be renabled on usecase start
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700696 // platform_set_swap_channels(adev, false);
vivek mehtae59cfb22017-06-16 15:57:11 -0700697
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700698 } else if (platform_can_split_snd_device(snd_device,
699 &num_devices,
700 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700701 for (i = 0; i < num_devices; i++) {
702 disable_snd_device(adev, new_snd_devices[i]);
703 }
vivek mehtab6506412015-08-07 16:55:17 -0700704 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700705 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800706 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
707 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
708 ALOGE(" %s: Invalid sound device returned", __func__);
709 return -EINVAL;
710 }
711
Eric Laurent2e140aa2016-06-30 17:14:46 -0700712 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800713 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700714 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700715 audio_extn_sound_trigger_update_device_status(snd_device,
716 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700717 }
vivek mehtab6506412015-08-07 16:55:17 -0700718
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800719 return 0;
720}
721
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700722/*
723 legend:
724 uc - existing usecase
725 new_uc - new usecase
726 d1, d11, d2 - SND_DEVICE enums
727 a1, a2 - corresponding ANDROID device enums
728 B, B1, B2 - backend strings
729
730case 1
731 uc->dev d1 (a1) B1
732 new_uc->dev d1 (a1), d2 (a2) B1, B2
733
734 resolution: disable and enable uc->dev on d1
735
736case 2
737 uc->dev d1 (a1) B1
738 new_uc->dev d11 (a1) B1
739
740 resolution: need to switch uc since d1 and d11 are related
741 (e.g. speaker and voice-speaker)
742 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
743
744case 3
745 uc->dev d1 (a1) B1
746 new_uc->dev d2 (a2) B2
747
748 resolution: no need to switch uc
749
750case 4
751 uc->dev d1 (a1) B
752 new_uc->dev d2 (a2) B
753
754 resolution: disable enable uc-dev on d2 since backends match
755 we cannot enable two streams on two different devices if they
756 share the same backend. e.g. if offload is on speaker device using
757 QUAD_MI2S backend and a low-latency stream is started on voice-handset
758 using the same backend, offload must also be switched to voice-handset.
759
760case 5
761 uc->dev d1 (a1) B
762 new_uc->dev d1 (a1), d2 (a2) B
763
764 resolution: disable enable uc-dev on d2 since backends match
765 we cannot enable two streams on two different devices if they
766 share the same backend.
767
768case 6
769 uc->dev d1 a1 B1
770 new_uc->dev d2 a1 B2
771
772 resolution: no need to switch
773
774case 7
775
776 uc->dev d1 (a1), d2 (a2) B1, B2
777 new_uc->dev d1 B1
778
779 resolution: no need to switch
780
781*/
782static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
783 struct audio_usecase *new_uc,
784 snd_device_t new_snd_device)
785{
786 audio_devices_t a1 = uc->stream.out->devices;
787 audio_devices_t a2 = new_uc->stream.out->devices;
788
789 snd_device_t d1 = uc->out_snd_device;
790 snd_device_t d2 = new_snd_device;
791
792 // Treat as a special case when a1 and a2 are not disjoint
793 if ((a1 != a2) && (a1 & a2)) {
794 snd_device_t d3[2];
795 int num_devices = 0;
796 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
797 &num_devices,
798 d3);
799 if (ret < 0) {
800 if (ret != -ENOSYS) {
801 ALOGW("%s failed to split snd_device %d",
802 __func__,
803 popcount(a1) > 1 ? d1 : d2);
804 }
805 goto end;
806 }
807
808 // NB: case 7 is hypothetical and isn't a practical usecase yet.
809 // But if it does happen, we need to give priority to d2 if
810 // the combo devices active on the existing usecase share a backend.
811 // This is because we cannot have a usecase active on a combo device
812 // and a new usecase requests one device in this combo pair.
813 if (platform_check_backends_match(d3[0], d3[1])) {
814 return d2; // case 5
815 } else {
816 return d1; // case 1
817 }
818 } else {
819 if (platform_check_backends_match(d1, d2)) {
820 return d2; // case 2, 4
821 } else {
822 return d1; // case 6, 3
823 }
824 }
825
826end:
827 return d2; // return whatever was calculated before.
828}
829
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700830static void check_and_route_playback_usecases(struct audio_device *adev,
831 struct audio_usecase *uc_info,
832 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700833{
834 struct listnode *node;
835 struct audio_usecase *usecase;
836 bool switch_device[AUDIO_USECASE_MAX];
837 int i, num_uc_to_switch = 0;
838
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700839 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
840 uc_info,
841 snd_device);
David Linee3fe402017-03-13 10:00:42 -0700842
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700843 /*
844 * This function is to make sure that all the usecases that are active on
845 * the hardware codec backend are always routed to any one device that is
846 * handled by the hardware codec.
847 * For example, if low-latency and deep-buffer usecases are currently active
848 * on speaker and out_set_parameters(headset) is received on low-latency
849 * output, then we have to make sure deep-buffer is also switched to headset,
850 * because of the limitation that both the devices cannot be enabled
851 * at the same time as they share the same backend.
852 */
853 /* Disable all the usecases on the shared backend other than the
854 specified usecase */
855 for (i = 0; i < AUDIO_USECASE_MAX; i++)
856 switch_device[i] = false;
857
858 list_for_each(node, &adev->usecase_list) {
859 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700860 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
861 continue;
862
863 if (force_routing ||
864 (usecase->out_snd_device != snd_device &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -0700865 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
866 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700867 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700868 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
869 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700870 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700871 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700872 switch_device[usecase->id] = true;
873 num_uc_to_switch++;
874 }
875 }
876
877 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700878 list_for_each(node, &adev->usecase_list) {
879 usecase = node_to_item(node, struct audio_usecase, list);
880 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700881 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900882 }
883 }
884
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700885 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900886 list_for_each(node, &adev->usecase_list) {
887 usecase = node_to_item(node, struct audio_usecase, list);
888 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700889 d_device = derive_playback_snd_device(usecase, uc_info,
890 snd_device);
891 enable_snd_device(adev, d_device);
892 /* Update the out_snd_device before enabling the audio route */
893 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700894 }
895 }
896
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700897 /* Re-route all the usecases on the shared backend other than the
898 specified usecase to new snd devices */
899 list_for_each(node, &adev->usecase_list) {
900 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700901 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700902 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700903 }
904 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700905 }
906}
907
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700908static void check_and_route_capture_usecases(struct audio_device *adev,
909 struct audio_usecase *uc_info,
910 snd_device_t snd_device)
911{
912 struct listnode *node;
913 struct audio_usecase *usecase;
914 bool switch_device[AUDIO_USECASE_MAX];
915 int i, num_uc_to_switch = 0;
916
vivek mehta4ed66e62016-04-15 23:33:34 -0700917 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
918
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700919 /*
920 * This function is to make sure that all the active capture usecases
921 * are always routed to the same input sound device.
922 * For example, if audio-record and voice-call usecases are currently
923 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
924 * is received for voice call then we have to make sure that audio-record
925 * usecase is also switched to earpiece i.e. voice-dmic-ef,
926 * because of the limitation that two devices cannot be enabled
927 * at the same time if they share the same backend.
928 */
929 for (i = 0; i < AUDIO_USECASE_MAX; i++)
930 switch_device[i] = false;
931
932 list_for_each(node, &adev->usecase_list) {
933 usecase = node_to_item(node, struct audio_usecase, list);
934 if (usecase->type != PCM_PLAYBACK &&
935 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700936 usecase->in_snd_device != snd_device &&
937 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700938 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
939 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700940 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700941 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700942 switch_device[usecase->id] = true;
943 num_uc_to_switch++;
944 }
945 }
946
947 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700948 list_for_each(node, &adev->usecase_list) {
949 usecase = node_to_item(node, struct audio_usecase, list);
950 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700951 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700952 }
953 }
954
955 list_for_each(node, &adev->usecase_list) {
956 usecase = node_to_item(node, struct audio_usecase, list);
957 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700958 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700959 }
960 }
961
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700962 /* Re-route all the usecases on the shared backend other than the
963 specified usecase to new snd devices */
964 list_for_each(node, &adev->usecase_list) {
965 usecase = node_to_item(node, struct audio_usecase, list);
966 /* Update the in_snd_device only before enabling the audio route */
967 if (switch_device[usecase->id] ) {
968 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700969 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700970 }
971 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700972 }
973}
974
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800975/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700976static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800977{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700978 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700979 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800980
981 switch (channels) {
982 /*
983 * Do not handle stereo output in Multi-channel cases
984 * Stereo case is handled in normal playback path
985 */
986 case 6:
987 ALOGV("%s: HDMI supports 5.1", __func__);
988 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
989 break;
990 case 8:
991 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
992 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
993 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
994 break;
995 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700996 ALOGE("HDMI does not support multi channel playback");
997 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800998 break;
999 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001000 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001001}
1002
Andy Hung18859412017-08-09 11:47:21 -07001003static ssize_t read_usb_sup_sample_rates(bool is_playback,
1004 uint32_t *supported_sample_rates,
1005 uint32_t max_rates)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001006{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001007 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1008 supported_sample_rates,
1009 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001010#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001011 for (ssize_t i=0; i<count; i++) {
1012 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1013 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001014 }
1015#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001016 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001017}
1018
Haynes Mathew George569b7482017-05-08 14:44:27 -07001019static int read_usb_sup_channel_masks(bool is_playback,
1020 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001021 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001022{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001023 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001024 int channel_count;
1025 uint32_t num_masks = 0;
1026 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1027 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001028 }
Eric Laurent74b55762017-07-09 17:04:53 -07001029 if (is_playback) {
1030 // For playback we never report mono because the framework always outputs stereo
1031 channel_count = DEFAULT_CHANNEL_COUNT;
1032 // audio_channel_out_mask_from_count() does return positional masks for channel counts
1033 // above 2 but we want indexed masks here. So we
1034 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1035 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1036 }
1037 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1038 supported_channel_masks[num_masks++] =
1039 audio_channel_mask_for_index_assignment_from_count(channel_count);
1040 }
1041 } else {
1042 // For capture we report all supported channel masks from 1 channel up.
1043 channel_count = MIN_CHANNEL_COUNT;
1044 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1045 // indexed mask
1046 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1047 supported_channel_masks[num_masks++] =
1048 audio_channel_in_mask_from_count(channel_count);
1049 }
1050 }
1051 ALOGV("%s: %s supported ch %d supported_channel_masks[0] %08x num_masks %d", __func__,
1052 is_playback ? "P" : "C", channels, supported_channel_masks[0], num_masks);
1053 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001054}
1055
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001056static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001057 audio_format_t *supported_formats,
1058 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001059{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001060 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001061 switch (bitwidth) {
1062 case 24:
1063 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001064 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001065 break;
1066 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001067 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001068 break;
1069 case 16:
1070 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001071 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001072 break;
1073 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001074 ALOGV("%s: %s supported format %d", __func__,
1075 is_playback ? "P" : "C", bitwidth);
1076 return 1;
1077}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001078
Haynes Mathew George569b7482017-05-08 14:44:27 -07001079static int read_usb_sup_params_and_compare(bool is_playback,
1080 audio_format_t *format,
1081 audio_format_t *supported_formats,
1082 uint32_t max_formats,
1083 audio_channel_mask_t *mask,
1084 audio_channel_mask_t *supported_channel_masks,
1085 uint32_t max_masks,
1086 uint32_t *rate,
1087 uint32_t *supported_sample_rates,
1088 uint32_t max_rates) {
1089 int ret = 0;
1090 int num_formats;
1091 int num_masks;
1092 int num_rates;
1093 int i;
1094
1095 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1096 max_formats);
1097 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1098 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001099
Haynes Mathew George569b7482017-05-08 14:44:27 -07001100 num_rates = read_usb_sup_sample_rates(is_playback,
1101 supported_sample_rates, max_rates);
1102
1103#define LUT(table, len, what, dflt) \
1104 for (i=0; i<len && (table[i] != what); i++); \
1105 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1106
1107 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1108 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1109 LUT(supported_sample_rates, num_rates, *rate, 0);
1110
1111#undef LUT
1112 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001113}
1114
Andy Hungd9653bd2017-08-01 19:31:39 -07001115static bool is_usb_ready(struct audio_device *adev, bool is_playback)
1116{
1117 // Check if usb is ready.
1118 // The usb device may have been removed quickly after insertion and hence
1119 // no longer available. This will show up as empty channel masks, or rates.
1120
1121 pthread_mutex_lock(&adev->lock);
1122 uint32_t supported_sample_rate;
1123
1124 // we consider usb ready if we can fetch at least one sample rate.
1125 const bool ready = read_usb_sup_sample_rates(
1126 is_playback, &supported_sample_rate, 1 /* max_rates */) > 0;
1127 pthread_mutex_unlock(&adev->lock);
1128 return ready;
1129}
1130
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001131static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1132{
1133 struct audio_usecase *usecase;
1134 struct listnode *node;
1135
1136 list_for_each(node, &adev->usecase_list) {
1137 usecase = node_to_item(node, struct audio_usecase, list);
1138 if (usecase->type == VOICE_CALL) {
1139 ALOGV("%s: usecase id %d", __func__, usecase->id);
1140 return usecase->id;
1141 }
1142 }
1143 return USECASE_INVALID;
1144}
1145
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001146struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1147 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001148{
1149 struct audio_usecase *usecase;
1150 struct listnode *node;
1151
1152 list_for_each(node, &adev->usecase_list) {
1153 usecase = node_to_item(node, struct audio_usecase, list);
1154 if (usecase->id == uc_id)
1155 return usecase;
1156 }
1157 return NULL;
1158}
1159
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001160int select_devices(struct audio_device *adev,
1161 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001162{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001163 snd_device_t out_snd_device = SND_DEVICE_NONE;
1164 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001165 struct audio_usecase *usecase = NULL;
1166 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001167 struct audio_usecase *hfp_usecase = NULL;
1168 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001169 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001170 int status = 0;
Eric Laurentf4520b02017-09-20 18:31:58 -07001171 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1172 USECASE_AUDIO_PLAYBACK_VOIP);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001173
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001174 usecase = get_usecase_from_list(adev, uc_id);
1175 if (usecase == NULL) {
1176 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1177 return -EINVAL;
1178 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001179
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001180 if ((usecase->type == VOICE_CALL) ||
1181 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001182 out_snd_device = platform_get_output_snd_device(adev->platform,
1183 usecase->stream.out->devices);
1184 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001185 usecase->devices = usecase->stream.out->devices;
1186 } else {
1187 /*
1188 * If the voice call is active, use the sound devices of voice call usecase
1189 * so that it would not result any device switch. All the usecases will
1190 * be switched to new device when select_devices() is called for voice call
1191 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001192 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001193 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001194 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001195 vc_usecase = get_usecase_from_list(adev,
1196 get_voice_usecase_id_from_list(adev));
1197 if ((vc_usecase != NULL) &&
1198 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1199 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001200 in_snd_device = vc_usecase->in_snd_device;
1201 out_snd_device = vc_usecase->out_snd_device;
1202 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001203 } else if (audio_extn_hfp_is_active(adev)) {
1204 hfp_ucid = audio_extn_hfp_get_usecase();
1205 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1206 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1207 in_snd_device = hfp_usecase->in_snd_device;
1208 out_snd_device = hfp_usecase->out_snd_device;
1209 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001210 }
1211 if (usecase->type == PCM_PLAYBACK) {
1212 usecase->devices = usecase->stream.out->devices;
1213 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001214 if (out_snd_device == SND_DEVICE_NONE) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001215 struct stream_out *voip_out = adev->primary_output;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001216
Eric Laurentb23d5282013-05-14 15:27:20 -07001217 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001218 usecase->stream.out->devices);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001219
1220 if (voip_usecase)
1221 voip_out = voip_usecase->stream.out;
1222
1223 if (usecase->stream.out == voip_out &&
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001224 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001225 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001226 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001227 select_devices(adev, adev->active_input->usecase);
1228 }
1229 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001230 } else if (usecase->type == PCM_CAPTURE) {
1231 usecase->devices = usecase->stream.in->device;
1232 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001233 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001234 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001235 if (adev->active_input &&
1236 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1237 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001238
1239 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1240 USECASE_AUDIO_PLAYBACK_VOIP);
1241
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001242 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001243 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1244 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001245 } else if (voip_usecase) {
1246 out_device = voip_usecase->stream.out->devices;
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001247 } else if (adev->primary_output) {
1248 out_device = adev->primary_output->devices;
1249 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001250 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001251 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001252 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001253 }
1254 }
1255
1256 if (out_snd_device == usecase->out_snd_device &&
1257 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001258 return 0;
1259 }
1260
Eric Laurent2bafff12016-03-17 12:17:23 -07001261 if (out_snd_device != SND_DEVICE_NONE &&
1262 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1263 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1264 __func__,
1265 use_case_table[uc_id],
1266 adev->last_logged_snd_device[uc_id][0],
1267 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1268 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1269 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1270 -1,
1271 out_snd_device,
1272 platform_get_snd_device_name(out_snd_device),
1273 platform_get_snd_device_acdb_id(out_snd_device));
1274 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1275 }
1276 if (in_snd_device != SND_DEVICE_NONE &&
1277 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1278 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1279 __func__,
1280 use_case_table[uc_id],
1281 adev->last_logged_snd_device[uc_id][1],
1282 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1283 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1284 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1285 -1,
1286 in_snd_device,
1287 platform_get_snd_device_name(in_snd_device),
1288 platform_get_snd_device_acdb_id(in_snd_device));
1289 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1290 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001291
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001292 /*
1293 * Limitation: While in call, to do a device switch we need to disable
1294 * and enable both RX and TX devices though one of them is same as current
1295 * device.
1296 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001297 if ((usecase->type == VOICE_CALL) &&
1298 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1299 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001300 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001301 /* Disable sidetone only if voice call already exists */
1302 if (voice_is_call_state_active(adev))
1303 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001304 }
1305
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001306 /* Disable current sound devices */
1307 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001308 disable_audio_route(adev, usecase);
1309 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001310 }
1311
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001312 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001313 disable_audio_route(adev, usecase);
1314 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001315 }
1316
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001317 /* Applicable only on the targets that has external modem.
1318 * New device information should be sent to modem before enabling
1319 * the devices to reduce in-call device switch time.
1320 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001321 if ((usecase->type == VOICE_CALL) &&
1322 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1323 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001324 status = platform_switch_voice_call_enable_device_config(adev->platform,
1325 out_snd_device,
1326 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001327 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001328
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001329 /* Enable new sound devices */
1330 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001331 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Eric Laurent99dab492017-06-17 15:19:08 -07001332 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001333 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001334 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001335 }
1336
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001337 if (in_snd_device != SND_DEVICE_NONE) {
1338 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001339 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001340 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001341
Eric Laurentb23d5282013-05-14 15:27:20 -07001342 if (usecase->type == VOICE_CALL)
1343 status = platform_switch_voice_call_device_post(adev->platform,
1344 out_snd_device,
1345 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001346
sangwoo170731f2013-06-08 15:36:36 +09001347 usecase->in_snd_device = in_snd_device;
1348 usecase->out_snd_device = out_snd_device;
1349
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001350 audio_extn_tfa_98xx_set_mode();
1351
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001352 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001353
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001354 /* Applicable only on the targets that has external modem.
1355 * Enable device command should be sent to modem only after
1356 * enabling voice call mixer controls
1357 */
vivek mehta765eb642015-08-07 19:46:06 -07001358 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001359 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1360 out_snd_device,
1361 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001362 /* Enable sidetone only if voice call already exists */
1363 if (voice_is_call_state_active(adev))
1364 voice_set_sidetone(adev, out_snd_device, true);
1365 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001366
Eric Laurentf4520b02017-09-20 18:31:58 -07001367 if (usecase == voip_usecase) {
1368 struct stream_out *voip_out = voip_usecase->stream.out;
1369 audio_extn_utils_send_app_type_gain(adev,
1370 voip_out->app_type_cfg.app_type,
1371 &voip_out->app_type_cfg.gain[0]);
1372 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001373 return status;
1374}
1375
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001376static int stop_input_stream(struct stream_in *in)
1377{
1378 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001379 struct audio_usecase *uc_info;
1380 struct audio_device *adev = in->dev;
1381
Eric Laurent994a6932013-07-17 11:51:42 -07001382 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001383 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001384
1385 if (adev->active_input) {
1386 if (adev->active_input->usecase == in->usecase) {
1387 adev->active_input = NULL;
1388 } else {
1389 ALOGW("%s adev->active_input->usecase %s, v/s in->usecase %s",
1390 __func__,
1391 use_case_table[adev->active_input->usecase],
1392 use_case_table[in->usecase]);
1393 }
1394 }
1395
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001396 uc_info = get_usecase_from_list(adev, in->usecase);
1397 if (uc_info == NULL) {
1398 ALOGE("%s: Could not find the usecase (%d) in the list",
1399 __func__, in->usecase);
1400 return -EINVAL;
1401 }
1402
vivek mehta781065c2017-04-04 12:55:01 -07001403 /* Close in-call recording streams */
1404 voice_check_and_stop_incall_rec_usecase(adev, in);
1405
Eric Laurent150dbfe2013-02-27 14:31:02 -08001406 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001407 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001408
1409 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001410 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001411
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001412 list_remove(&uc_info->list);
1413 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001414
Eric Laurent994a6932013-07-17 11:51:42 -07001415 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001416 return ret;
1417}
1418
1419int start_input_stream(struct stream_in *in)
1420{
1421 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001422 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001423 struct audio_usecase *uc_info;
1424 struct audio_device *adev = in->dev;
1425
Eric Laurent994a6932013-07-17 11:51:42 -07001426 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001427
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001428 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1429 return -EIO;
1430
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001431 if (in->card_status == CARD_STATUS_OFFLINE ||
1432 adev->card_status == CARD_STATUS_OFFLINE) {
1433 ALOGW("in->card_status or adev->card_status offline, try again");
1434 ret = -EAGAIN;
1435 goto error_config;
1436 }
1437
vivek mehta781065c2017-04-04 12:55:01 -07001438 /* Check if source matches incall recording usecase criteria */
1439 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1440 if (ret)
1441 goto error_config;
1442 else
1443 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1444
Eric Laurentb23d5282013-05-14 15:27:20 -07001445 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001446 if (in->pcm_device_id < 0) {
1447 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1448 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001449 ret = -EINVAL;
1450 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001451 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001452
1453 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001454 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1455 uc_info->id = in->usecase;
1456 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001457 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001458 uc_info->devices = in->device;
1459 uc_info->in_snd_device = SND_DEVICE_NONE;
1460 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001461
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001462 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001463
Wei Wangf4837d52017-11-21 14:51:20 -08001464 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001465 audio_extn_perf_lock_acquire();
1466
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001467 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001468
Eric Laurent0e46adf2016-12-16 12:49:24 -08001469 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001470 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001471 ALOGE("%s: pcm stream not ready", __func__);
1472 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001473 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001474 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001475 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001476 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1477 goto error_open;
1478 }
1479 } else {
1480 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1481 unsigned int pcm_open_retry_count = 0;
1482
1483 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1484 flags |= PCM_MMAP | PCM_NOIRQ;
1485 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1486 } else if (in->realtime) {
1487 flags |= PCM_MMAP | PCM_NOIRQ;
1488 }
1489
1490 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1491 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1492
1493 while (1) {
1494 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1495 flags, &in->config);
1496 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1497 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1498 if (in->pcm != NULL) {
1499 pcm_close(in->pcm);
1500 in->pcm = NULL;
1501 }
1502 if (pcm_open_retry_count-- == 0) {
1503 ret = -EIO;
1504 goto error_open;
1505 }
1506 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1507 continue;
1508 }
1509 break;
1510 }
1511
1512 ALOGV("%s: pcm_prepare", __func__);
1513 ret = pcm_prepare(in->pcm);
1514 if (ret < 0) {
1515 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001516 pcm_close(in->pcm);
1517 in->pcm = NULL;
1518 goto error_open;
1519 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001520 if (in->realtime) {
1521 ret = pcm_start(in->pcm);
1522 if (ret < 0) {
1523 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1524 pcm_close(in->pcm);
1525 in->pcm = NULL;
1526 goto error_open;
1527 }
1528 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001529 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001530 register_in_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001531 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001532 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001533 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001534
Eric Laurent0e46adf2016-12-16 12:49:24 -08001535 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001536
1537error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001538 stop_input_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001539 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001540 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001541
1542error_config:
1543 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001544 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001545 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001546}
1547
Eric Laurenta1478072015-09-21 17:21:52 -07001548void lock_input_stream(struct stream_in *in)
1549{
1550 pthread_mutex_lock(&in->pre_lock);
1551 pthread_mutex_lock(&in->lock);
1552 pthread_mutex_unlock(&in->pre_lock);
1553}
1554
1555void lock_output_stream(struct stream_out *out)
1556{
1557 pthread_mutex_lock(&out->pre_lock);
1558 pthread_mutex_lock(&out->lock);
1559 pthread_mutex_unlock(&out->pre_lock);
1560}
1561
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001562/* must be called with out->lock locked */
1563static int send_offload_cmd_l(struct stream_out* out, int command)
1564{
1565 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1566
1567 ALOGVV("%s %d", __func__, command);
1568
1569 cmd->cmd = command;
1570 list_add_tail(&out->offload_cmd_list, &cmd->node);
1571 pthread_cond_signal(&out->offload_cond);
1572 return 0;
1573}
1574
1575/* must be called iwth out->lock locked */
1576static void stop_compressed_output_l(struct stream_out *out)
1577{
1578 out->offload_state = OFFLOAD_STATE_IDLE;
1579 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001580 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001581 if (out->compr != NULL) {
1582 compress_stop(out->compr);
1583 while (out->offload_thread_blocked) {
1584 pthread_cond_wait(&out->cond, &out->lock);
1585 }
1586 }
1587}
1588
1589static void *offload_thread_loop(void *context)
1590{
1591 struct stream_out *out = (struct stream_out *) context;
1592 struct listnode *item;
1593
1594 out->offload_state = OFFLOAD_STATE_IDLE;
1595 out->playback_started = 0;
1596
1597 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1598 set_sched_policy(0, SP_FOREGROUND);
1599 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1600
1601 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001602 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001603 for (;;) {
1604 struct offload_cmd *cmd = NULL;
1605 stream_callback_event_t event;
1606 bool send_callback = false;
1607
1608 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1609 __func__, list_empty(&out->offload_cmd_list),
1610 out->offload_state);
1611 if (list_empty(&out->offload_cmd_list)) {
1612 ALOGV("%s SLEEPING", __func__);
1613 pthread_cond_wait(&out->offload_cond, &out->lock);
1614 ALOGV("%s RUNNING", __func__);
1615 continue;
1616 }
1617
1618 item = list_head(&out->offload_cmd_list);
1619 cmd = node_to_item(item, struct offload_cmd, node);
1620 list_remove(item);
1621
1622 ALOGVV("%s STATE %d CMD %d out->compr %p",
1623 __func__, out->offload_state, cmd->cmd, out->compr);
1624
1625 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1626 free(cmd);
1627 break;
1628 }
1629
1630 if (out->compr == NULL) {
1631 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001632 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001633 pthread_cond_signal(&out->cond);
1634 continue;
1635 }
1636 out->offload_thread_blocked = true;
1637 pthread_mutex_unlock(&out->lock);
1638 send_callback = false;
1639 switch(cmd->cmd) {
1640 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1641 compress_wait(out->compr, -1);
1642 send_callback = true;
1643 event = STREAM_CBK_EVENT_WRITE_READY;
1644 break;
1645 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001646 compress_next_track(out->compr);
1647 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001648 send_callback = true;
1649 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001650 /* Resend the metadata for next iteration */
1651 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001652 break;
1653 case OFFLOAD_CMD_DRAIN:
1654 compress_drain(out->compr);
1655 send_callback = true;
1656 event = STREAM_CBK_EVENT_DRAIN_READY;
1657 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001658 case OFFLOAD_CMD_ERROR:
1659 send_callback = true;
1660 event = STREAM_CBK_EVENT_ERROR;
1661 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001662 default:
1663 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1664 break;
1665 }
Eric Laurenta1478072015-09-21 17:21:52 -07001666 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001667 out->offload_thread_blocked = false;
1668 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001669 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001670 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001671 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001672 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001673 free(cmd);
1674 }
1675
1676 pthread_cond_signal(&out->cond);
1677 while (!list_empty(&out->offload_cmd_list)) {
1678 item = list_head(&out->offload_cmd_list);
1679 list_remove(item);
1680 free(node_to_item(item, struct offload_cmd, node));
1681 }
1682 pthread_mutex_unlock(&out->lock);
1683
1684 return NULL;
1685}
1686
1687static int create_offload_callback_thread(struct stream_out *out)
1688{
1689 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1690 list_init(&out->offload_cmd_list);
1691 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1692 offload_thread_loop, out);
1693 return 0;
1694}
1695
1696static int destroy_offload_callback_thread(struct stream_out *out)
1697{
Eric Laurenta1478072015-09-21 17:21:52 -07001698 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001699 stop_compressed_output_l(out);
1700 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1701
1702 pthread_mutex_unlock(&out->lock);
1703 pthread_join(out->offload_thread, (void **) NULL);
1704 pthread_cond_destroy(&out->offload_cond);
1705
1706 return 0;
1707}
1708
Eric Laurent07eeafd2013-10-06 12:52:49 -07001709static bool allow_hdmi_channel_config(struct audio_device *adev)
1710{
1711 struct listnode *node;
1712 struct audio_usecase *usecase;
1713 bool ret = true;
1714
1715 list_for_each(node, &adev->usecase_list) {
1716 usecase = node_to_item(node, struct audio_usecase, list);
1717 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1718 /*
1719 * If voice call is already existing, do not proceed further to avoid
1720 * disabling/enabling both RX and TX devices, CSD calls, etc.
1721 * Once the voice call done, the HDMI channels can be configured to
1722 * max channels of remaining use cases.
1723 */
1724 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001725 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001726 __func__);
1727 ret = false;
1728 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001729 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1730 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001731 "no change in HDMI channels", __func__);
1732 ret = false;
1733 break;
1734 }
1735 }
1736 }
1737 return ret;
1738}
1739
1740static int check_and_set_hdmi_channels(struct audio_device *adev,
1741 unsigned int channels)
1742{
1743 struct listnode *node;
1744 struct audio_usecase *usecase;
1745
1746 /* Check if change in HDMI channel config is allowed */
1747 if (!allow_hdmi_channel_config(adev))
1748 return 0;
1749
1750 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001751 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001752 return 0;
1753 }
1754
1755 platform_set_hdmi_channels(adev->platform, channels);
1756 adev->cur_hdmi_channels = channels;
1757
1758 /*
1759 * Deroute all the playback streams routed to HDMI so that
1760 * the back end is deactivated. Note that backend will not
1761 * be deactivated if any one stream is connected to it.
1762 */
1763 list_for_each(node, &adev->usecase_list) {
1764 usecase = node_to_item(node, struct audio_usecase, list);
1765 if (usecase->type == PCM_PLAYBACK &&
1766 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001767 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001768 }
1769 }
1770
1771 /*
1772 * Enable all the streams disabled above. Now the HDMI backend
1773 * will be activated with new channel configuration
1774 */
1775 list_for_each(node, &adev->usecase_list) {
1776 usecase = node_to_item(node, struct audio_usecase, list);
1777 if (usecase->type == PCM_PLAYBACK &&
1778 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001779 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001780 }
1781 }
1782
1783 return 0;
1784}
1785
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001786static int stop_output_stream(struct stream_out *out)
1787{
1788 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001789 struct audio_usecase *uc_info;
1790 struct audio_device *adev = out->dev;
1791
Eric Laurent994a6932013-07-17 11:51:42 -07001792 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001793 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001794 uc_info = get_usecase_from_list(adev, out->usecase);
1795 if (uc_info == NULL) {
1796 ALOGE("%s: Could not find the usecase (%d) in the list",
1797 __func__, out->usecase);
1798 return -EINVAL;
1799 }
1800
Haynes Mathew George41f86652014-06-17 14:22:15 -07001801 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1802 if (adev->visualizer_stop_output != NULL)
1803 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1804 if (adev->offload_effects_stop_output != NULL)
1805 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08001806 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
1807 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
1808 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07001809 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001810
Eric Laurent150dbfe2013-02-27 14:31:02 -08001811 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001812 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001813
1814 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001815 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001816
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001817 list_remove(&uc_info->list);
1818 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001819
Eric Laurent0499d4f2014-08-25 22:39:29 -05001820 audio_extn_extspk_update(adev->extspk);
1821
Eric Laurent07eeafd2013-10-06 12:52:49 -07001822 /* Must be called after removing the usecase from list */
1823 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1824 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07001825 else if (out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
1826 struct listnode *node;
1827 struct audio_usecase *usecase;
1828 list_for_each(node, &adev->usecase_list) {
1829 usecase = node_to_item(node, struct audio_usecase, list);
1830 if (usecase->devices & AUDIO_DEVICE_OUT_SPEAKER)
1831 select_devices(adev, usecase->id);
1832 }
1833 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001834
Eric Laurent994a6932013-07-17 11:51:42 -07001835 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001836 return ret;
1837}
1838
1839int start_output_stream(struct stream_out *out)
1840{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001841 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001842 struct audio_usecase *uc_info;
1843 struct audio_device *adev = out->dev;
1844
Eric Laurent994a6932013-07-17 11:51:42 -07001845 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001846 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001847
1848 if (out->card_status == CARD_STATUS_OFFLINE ||
1849 adev->card_status == CARD_STATUS_OFFLINE) {
1850 ALOGW("out->card_status or adev->card_status offline, try again");
1851 ret = -EAGAIN;
1852 goto error_config;
1853 }
1854
Eric Laurentb23d5282013-05-14 15:27:20 -07001855 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001856 if (out->pcm_device_id < 0) {
1857 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1858 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001859 ret = -EINVAL;
1860 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001861 }
1862
1863 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1864 uc_info->id = out->usecase;
1865 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001866 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001867 uc_info->devices = out->devices;
1868 uc_info->in_snd_device = SND_DEVICE_NONE;
1869 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001870
Eric Laurent07eeafd2013-10-06 12:52:49 -07001871 /* This must be called before adding this usecase to the list */
1872 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1873 check_and_set_hdmi_channels(adev, out->config.channels);
1874
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001875 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001876
Wei Wangf4837d52017-11-21 14:51:20 -08001877 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001878 audio_extn_perf_lock_acquire();
1879
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001880 select_devices(adev, out->usecase);
1881
Eric Laurent0499d4f2014-08-25 22:39:29 -05001882 audio_extn_extspk_update(adev->extspk);
1883
Andy Hung31aca912014-03-20 17:14:59 -07001884 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001885 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001886 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1887 out->pcm = NULL;
1888 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1889 COMPRESS_IN, &out->compr_config);
1890 if (out->compr && !is_compress_ready(out->compr)) {
1891 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1892 compress_close(out->compr);
1893 out->compr = NULL;
1894 ret = -EIO;
1895 goto error_open;
1896 }
1897 if (out->offload_callback)
1898 compress_nonblock(out->compr, out->non_blocking);
1899
1900 if (adev->visualizer_start_output != NULL)
1901 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1902 if (adev->offload_effects_start_output != NULL)
1903 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
1904 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001905 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001906 ALOGE("%s: pcm stream not ready", __func__);
1907 goto error_open;
1908 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001909 ret = pcm_start(out->pcm);
1910 if (ret < 0) {
1911 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1912 goto error_open;
1913 }
1914 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07001915 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001916 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001917
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001918 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1919 flags |= PCM_MMAP | PCM_NOIRQ;
1920 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001921 } else if (out->realtime) {
1922 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07001923 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001924
1925 while (1) {
1926 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1927 flags, &out->config);
1928 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1929 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1930 if (out->pcm != NULL) {
1931 pcm_close(out->pcm);
1932 out->pcm = NULL;
1933 }
1934 if (pcm_open_retry_count-- == 0) {
1935 ret = -EIO;
1936 goto error_open;
1937 }
1938 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1939 continue;
1940 }
1941 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001942 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001943 ALOGV("%s: pcm_prepare", __func__);
1944 if (pcm_is_ready(out->pcm)) {
1945 ret = pcm_prepare(out->pcm);
1946 if (ret < 0) {
1947 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1948 pcm_close(out->pcm);
1949 out->pcm = NULL;
1950 goto error_open;
1951 }
1952 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001953 if (out->realtime) {
1954 ret = pcm_start(out->pcm);
1955 if (ret < 0) {
1956 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1957 pcm_close(out->pcm);
1958 out->pcm = NULL;
1959 goto error_open;
1960 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001961 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001962 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001963 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08001964 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001965 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001966 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07001967
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08001968 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
1969 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
1970 audio_low_latency_hint_start();
1971 }
1972
vivek mehtae59cfb22017-06-16 15:57:11 -07001973 // consider a scenario where on pause lower layers are tear down.
1974 // so on resume, swap mixer control need to be sent only when
1975 // backend is active, hence rather than sending from enable device
1976 // sending it from start of streamtream
1977
1978 platform_set_swap_channels(adev, true);
1979
Eric Laurent994a6932013-07-17 11:51:42 -07001980 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001981 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001982error_open:
Wei Wangf4837d52017-11-21 14:51:20 -08001983 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001984 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001985 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001986error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001987 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001988}
1989
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001990static int check_input_parameters(uint32_t sample_rate,
1991 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07001992 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001993{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001994 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
1995 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07001996 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
1997 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07001998 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1999 return -EINVAL;
2000 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002001
Eric Laurent74b55762017-07-09 17:04:53 -07002002 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2003 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002004 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002005 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002006 return -EINVAL;
2007 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002008
2009 switch (sample_rate) {
2010 case 8000:
2011 case 11025:
2012 case 12000:
2013 case 16000:
2014 case 22050:
2015 case 24000:
2016 case 32000:
2017 case 44100:
2018 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002019 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002020 break;
2021 default:
vivek mehtadae44712015-07-27 14:13:18 -07002022 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002023 return -EINVAL;
2024 }
2025
2026 return 0;
2027}
2028
vivek mehtaa68fea62017-06-08 19:04:02 -07002029static size_t get_stream_buffer_size(size_t duration_ms,
2030 uint32_t sample_rate,
2031 audio_format_t format,
2032 int channel_count,
2033 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002034{
2035 size_t size = 0;
2036
vivek mehtaa68fea62017-06-08 19:04:02 -07002037 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002038 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002039 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002040
2041 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002042
Glenn Kasten4f993392014-05-14 07:30:48 -07002043 /* make sure the size is multiple of 32 bytes
2044 * At 48 kHz mono 16-bit PCM:
2045 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2046 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2047 */
2048 size += 0x1f;
2049 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002050
2051 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002052}
2053
2054static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2055{
2056 struct stream_out *out = (struct stream_out *)stream;
2057
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002058 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002059}
2060
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002061static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002062{
2063 return -ENOSYS;
2064}
2065
2066static size_t out_get_buffer_size(const struct audio_stream *stream)
2067{
2068 struct stream_out *out = (struct stream_out *)stream;
2069
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002070 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2071 return out->compr_config.fragment_size;
2072 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002073 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002074 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002075}
2076
2077static uint32_t out_get_channels(const struct audio_stream *stream)
2078{
2079 struct stream_out *out = (struct stream_out *)stream;
2080
2081 return out->channel_mask;
2082}
2083
2084static audio_format_t out_get_format(const struct audio_stream *stream)
2085{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002086 struct stream_out *out = (struct stream_out *)stream;
2087
2088 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002089}
2090
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002091static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002092{
2093 return -ENOSYS;
2094}
2095
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002096/* must be called with out->lock locked */
2097static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002098{
2099 struct stream_out *out = (struct stream_out *)stream;
2100 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002101 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002102
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002103 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002104 if (adev->adm_deregister_stream)
2105 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002106 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002107 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002108 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2109 if (out->pcm) {
2110 pcm_close(out->pcm);
2111 out->pcm = NULL;
2112 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002113 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002114 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002115 out->playback_started = false;
2116 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002117 } else {
2118 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002119 out->gapless_mdata.encoder_delay = 0;
2120 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002121 if (out->compr != NULL) {
2122 compress_close(out->compr);
2123 out->compr = NULL;
2124 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002125 }
Phil Burkbc991042017-02-24 08:06:44 -08002126 if (do_stop) {
2127 stop_output_stream(out);
2128 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002129 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002130 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002131 return 0;
2132}
2133
2134static int out_standby(struct audio_stream *stream)
2135{
2136 struct stream_out *out = (struct stream_out *)stream;
2137
2138 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2139 out->usecase, use_case_table[out->usecase]);
2140
2141 lock_output_stream(out);
2142 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002143 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002144 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002145 return 0;
2146}
2147
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002148static int out_on_error(struct audio_stream *stream)
2149{
2150 struct stream_out *out = (struct stream_out *)stream;
2151 struct audio_device *adev = out->dev;
2152 bool do_standby = false;
2153
2154 lock_output_stream(out);
2155 if (!out->standby) {
2156 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2157 stop_compressed_output_l(out);
2158 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2159 } else
2160 do_standby = true;
2161 }
2162 pthread_mutex_unlock(&out->lock);
2163
2164 if (do_standby)
2165 return out_standby(&out->stream.common);
2166
2167 return 0;
2168}
2169
Andy Hung7401c7c2016-09-21 12:41:21 -07002170static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002171{
Andy Hung7401c7c2016-09-21 12:41:21 -07002172 struct stream_out *out = (struct stream_out *)stream;
2173
2174 // We try to get the lock for consistency,
2175 // but it isn't necessary for these variables.
2176 // If we're not in standby, we may be blocked on a write.
2177 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2178 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2179 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2180
2181 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002182 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002183 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002184
2185 // dump error info
2186 (void)error_log_dump(
2187 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002188
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002189 return 0;
2190}
2191
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002192static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2193{
2194 int ret = 0;
2195 char value[32];
2196 struct compr_gapless_mdata tmp_mdata;
2197
2198 if (!out || !parms) {
2199 return -EINVAL;
2200 }
2201
2202 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2203 if (ret >= 0) {
2204 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2205 } else {
2206 return -EINVAL;
2207 }
2208
2209 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2210 if (ret >= 0) {
2211 tmp_mdata.encoder_padding = atoi(value);
2212 } else {
2213 return -EINVAL;
2214 }
2215
2216 out->gapless_mdata = tmp_mdata;
2217 out->send_new_metadata = 1;
2218 ALOGV("%s new encoder delay %u and padding %u", __func__,
2219 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2220
2221 return 0;
2222}
2223
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002224static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2225{
2226 return out == adev->primary_output || out == adev->voice_tx_output;
2227}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002228
Kevin Rocard1e02c882017-08-09 15:26:07 -07002229static int get_alive_usb_card(struct str_parms* parms) {
2230 int card;
2231 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2232 !audio_extn_usb_alive(card)) {
2233 return card;
2234 }
2235 return -ENODEV;
2236}
2237
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002238static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2239{
2240 struct stream_out *out = (struct stream_out *)stream;
2241 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002242 struct audio_usecase *usecase;
2243 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002244 struct str_parms *parms;
2245 char value[32];
2246 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002247 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002248 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002249
Eric Laurent2e140aa2016-06-30 17:14:46 -07002250 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002251 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002252 parms = str_parms_create_str(kvpairs);
2253 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2254 if (ret >= 0) {
2255 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002256
Eric Laurenta1478072015-09-21 17:21:52 -07002257 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002258
2259 // The usb driver needs to be closed after usb device disconnection
2260 // otherwise audio is no longer played on the new usb devices.
2261 // By forcing the stream in standby, the usb stack refcount drops to 0
2262 // and the driver is closed.
2263 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD && val == AUDIO_DEVICE_NONE &&
2264 audio_is_usb_out_device(out->devices)) {
2265 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2266 out_standby_l(&out->stream.common);
2267 }
2268
Eric Laurent150dbfe2013-02-27 14:31:02 -08002269 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002270
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002271 /*
2272 * When HDMI cable is unplugged the music playback is paused and
2273 * the policy manager sends routing=0. But the audioflinger
2274 * continues to write data until standby time (3sec).
2275 * As the HDMI core is turned off, the write gets blocked.
2276 * Avoid this by routing audio to speaker until standby.
2277 */
2278 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2279 val == AUDIO_DEVICE_NONE) {
2280 val = AUDIO_DEVICE_OUT_SPEAKER;
2281 }
2282
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002283 audio_devices_t new_dev = val;
2284
2285 // Workaround: If routing to an non existing usb device, fail gracefully
2286 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002287 int card;
2288 if (audio_is_usb_out_device(new_dev) &&
2289 (card = get_alive_usb_card(parms)) >= 0) {
2290
2291 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002292 pthread_mutex_unlock(&adev->lock);
2293 pthread_mutex_unlock(&out->lock);
2294 status = -ENOSYS;
2295 goto routing_fail;
2296 }
2297
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002298 /*
2299 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002300 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002301 * the select_devices(). But how do we undo this?
2302 *
2303 * For example, music playback is active on headset (deep-buffer usecase)
2304 * and if we go to ringtones and select a ringtone, low-latency usecase
2305 * will be started on headset+speaker. As we can't enable headset+speaker
2306 * and headset devices at the same time, select_devices() switches the music
2307 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2308 * So when the ringtone playback is completed, how do we undo the same?
2309 *
2310 * We are relying on the out_set_parameters() call on deep-buffer output,
2311 * once the ringtone playback is ended.
2312 * NOTE: We should not check if the current devices are same as new devices.
2313 * Because select_devices() must be called to switch back the music
2314 * playback to headset.
2315 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002316 if (new_dev != AUDIO_DEVICE_NONE) {
2317 bool same_dev = out->devices == new_dev;
2318 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002319
Eric Laurenta7657192014-10-09 21:09:33 -07002320 if (output_drives_call(adev, out)) {
2321 if (!voice_is_in_call(adev)) {
2322 if (adev->mode == AUDIO_MODE_IN_CALL) {
2323 adev->current_call_output = out;
2324 ret = voice_start_call(adev);
2325 }
2326 } else {
2327 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002328 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002329 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002330 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002331
2332 if (!out->standby) {
2333 if (!same_dev) {
2334 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002335 // inform adm before actual routing to prevent glitches.
2336 if (adev->adm_on_routing_change) {
2337 adev->adm_on_routing_change(adev->adm_data,
2338 out->handle);
2339 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002340 }
2341 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002342 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002343
2344 // on device switch force swap, lower functions will make sure
2345 // to check if swap is allowed or not.
2346
2347 if (!same_dev)
2348 platform_set_swap_channels(adev, true);
vivek mehta0d3637a2016-07-24 09:32:02 -07002349 }
2350
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002351 }
2352
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002353 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002354 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002355
2356 /*handles device and call state changes*/
2357 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002358 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002359 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002360
2361 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2362 parse_compress_metadata(out, parms);
2363 }
2364
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002365 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002366 ALOGV("%s: exit: code(%d)", __func__, status);
2367 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002368}
2369
Haynes Mathew George569b7482017-05-08 14:44:27 -07002370static bool stream_get_parameter_channels(struct str_parms *query,
2371 struct str_parms *reply,
2372 audio_channel_mask_t *supported_channel_masks) {
2373 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002374 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002375 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002376 size_t i, j;
2377
2378 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2379 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002380 value[0] = '\0';
2381 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002382 while (supported_channel_masks[i] != 0) {
2383 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2384 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002385 if (!first) {
2386 strcat(value, "|");
2387 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002388 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002389 first = false;
2390 break;
2391 }
2392 }
2393 i++;
2394 }
2395 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002396 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002397 return ret >= 0;
2398}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002399
Haynes Mathew George569b7482017-05-08 14:44:27 -07002400static bool stream_get_parameter_formats(struct str_parms *query,
2401 struct str_parms *reply,
2402 audio_format_t *supported_formats) {
2403 int ret = -1;
2404 char value[256];
2405 int i;
2406
2407 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2408 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002409 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002410 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002411 case AUDIO_FORMAT_PCM_16_BIT:
2412 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2413 break;
2414 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2415 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2416 break;
2417 case AUDIO_FORMAT_PCM_32_BIT:
2418 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2419 break;
2420 default:
2421 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002422 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002423 break;
2424 }
2425 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002426 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002427 return ret >= 0;
2428}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002429
Haynes Mathew George569b7482017-05-08 14:44:27 -07002430static bool stream_get_parameter_rates(struct str_parms *query,
2431 struct str_parms *reply,
2432 uint32_t *supported_sample_rates) {
2433
2434 int i;
2435 char value[256];
2436 int ret = -1;
2437 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2438 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002439 value[0] = '\0';
2440 i=0;
2441 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002442 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002443 int avail = sizeof(value) - cursor;
2444 ret = snprintf(value + cursor, avail, "%s%d",
2445 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002446 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002447 if (ret < 0 || ret >= avail) {
2448 // if cursor is at the last element of the array
2449 // overwrite with \0 is duplicate work as
2450 // snprintf already put a \0 in place.
2451 // else
2452 // we had space to write the '|' at value[cursor]
2453 // (which will be overwritten) or no space to fill
2454 // the first element (=> cursor == 0)
2455 value[cursor] = '\0';
2456 break;
2457 }
2458 cursor += ret;
2459 ++i;
2460 }
2461 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2462 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002463 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002464 return ret >= 0;
2465}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002466
Haynes Mathew George569b7482017-05-08 14:44:27 -07002467static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2468{
2469 struct stream_out *out = (struct stream_out *)stream;
2470 struct str_parms *query = str_parms_create_str(keys);
2471 char *str;
2472 struct str_parms *reply = str_parms_create();
2473 bool replied = false;
2474 ALOGV("%s: enter: keys - %s", __func__, keys);
2475
2476 replied |= stream_get_parameter_channels(query, reply,
2477 &out->supported_channel_masks[0]);
2478 replied |= stream_get_parameter_formats(query, reply,
2479 &out->supported_formats[0]);
2480 replied |= stream_get_parameter_rates(query, reply,
2481 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002482 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002483 str = str_parms_to_str(reply);
2484 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002485 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002486 }
2487 str_parms_destroy(query);
2488 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002489 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002490 return str;
2491}
2492
2493static uint32_t out_get_latency(const struct audio_stream_out *stream)
2494{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002495 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002496 struct stream_out *out = (struct stream_out *)stream;
2497
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002498 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2499 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002500 else if ((out->realtime) ||
2501 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002502 // since the buffer won't be filled up faster than realtime,
2503 // return a smaller number
2504 period_ms = (out->af_period_multiplier * out->config.period_size *
2505 1000) / (out->config.rate);
2506 hw_delay = platform_render_latency(out->usecase)/1000;
2507 return period_ms + hw_delay;
2508 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002509
2510 return (out->config.period_count * out->config.period_size * 1000) /
2511 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002512}
2513
2514static int out_set_volume(struct audio_stream_out *stream, float left,
2515 float right)
2516{
Eric Laurenta9024de2013-04-04 09:19:12 -07002517 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002518 int volume[2];
2519
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002520 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002521 /* only take left channel into account: the API is for stereo anyway */
2522 out->muted = (left == 0.0f);
2523 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002524 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2525 const char *mixer_ctl_name = "Compress Playback Volume";
2526 struct audio_device *adev = out->dev;
2527 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002528 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2529 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002530 /* try with the control based on device id */
2531 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2532 PCM_PLAYBACK);
2533 char ctl_name[128] = {0};
2534 snprintf(ctl_name, sizeof(ctl_name),
2535 "Compress Playback %d Volume", pcm_device_id);
2536 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2537 if (!ctl) {
2538 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2539 return -EINVAL;
2540 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002541 }
2542 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2543 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2544 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2545 return 0;
vivek mehtaa68fea62017-06-08 19:04:02 -07002546 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002547 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2548 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2549 if (!out->standby) {
2550 // if in standby, cached volume will be sent after stream is opened
2551 audio_extn_utils_send_app_type_gain(out->dev,
2552 out->app_type_cfg.app_type,
2553 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002554 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002555 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002556 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002557
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002558 return -ENOSYS;
2559}
2560
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002561// note: this call is safe only if the stream_cb is
2562// removed first in close_output_stream (as is done now).
2563static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2564{
2565 if (!stream || !parms)
2566 return;
2567
2568 struct stream_out *out = (struct stream_out *)stream;
2569 struct audio_device *adev = out->dev;
2570
2571 card_status_t status;
2572 int card;
2573 if (parse_snd_card_status(parms, &card, &status) < 0)
2574 return;
2575
2576 pthread_mutex_lock(&adev->lock);
2577 bool valid_cb = (card == adev->snd_card);
2578 pthread_mutex_unlock(&adev->lock);
2579
2580 if (!valid_cb)
2581 return;
2582
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002583 lock_output_stream(out);
2584 if (out->card_status != status)
2585 out->card_status = status;
2586 pthread_mutex_unlock(&out->lock);
2587
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002588 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2589 use_case_table[out->usecase],
2590 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2591
2592 if (status == CARD_STATUS_OFFLINE)
2593 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002594
2595 return;
2596}
2597
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002598#ifdef NO_AUDIO_OUT
2599static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002600 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002601{
2602 struct stream_out *out = (struct stream_out *)stream;
2603
2604 /* No Output device supported other than BT for playback.
2605 * Sleep for the amount of buffer duration
2606 */
Eric Laurenta1478072015-09-21 17:21:52 -07002607 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002608 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2609 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002610 out_get_sample_rate(&out->stream.common));
2611 pthread_mutex_unlock(&out->lock);
2612 return bytes;
2613}
2614#endif
2615
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002616static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2617 size_t bytes)
2618{
2619 struct stream_out *out = (struct stream_out *)stream;
2620 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002621 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002622 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002623
Eric Laurenta1478072015-09-21 17:21:52 -07002624 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002625 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07002626 const size_t frame_size = audio_stream_out_frame_size(stream);
2627 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002628
Eric Laurent0e46adf2016-12-16 12:49:24 -08002629 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2630 error_code = ERROR_CODE_WRITE;
2631 goto exit;
2632 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002633 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002634 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002635 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002636 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07002637
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002638 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002639 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002640 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07002641 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002642 goto exit;
2643 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002644
vivek mehta40125092017-08-21 18:48:51 -07002645 // after standby always force set last known cal step
2646 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
2647 ALOGD("%s: retry previous failed cal level set", __func__);
2648 send_gain_dep_calibration_l();
2649 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002650 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002651
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002652 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002653 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002654 if (out->send_new_metadata) {
2655 ALOGVV("send new gapless metadata");
2656 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2657 out->send_new_metadata = 0;
2658 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002659 unsigned int avail;
2660 struct timespec tstamp;
2661 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2662 /* Do not limit write size if the available frames count is unknown */
2663 if (ret != 0) {
2664 avail = bytes;
2665 }
2666 if (avail == 0) {
2667 ret = 0;
2668 } else {
2669 if (avail > bytes) {
2670 avail = bytes;
2671 }
2672 ret = compress_write(out->compr, buffer, avail);
2673 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2674 __func__, avail, ret);
2675 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002676
Eric Laurent6e895242013-09-05 16:10:57 -07002677 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002678 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2679 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002680 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002681 compress_start(out->compr);
2682 out->playback_started = 1;
2683 out->offload_state = OFFLOAD_STATE_PLAYING;
2684 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002685 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002686 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002687 } else {
2688 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002689 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002690 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002691 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002692 return ret;
2693 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002694 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002695 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07002696 size_t bytes_to_write = bytes;
2697
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002698 if (out->muted)
2699 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07002700 // FIXME: this can be removed once audio flinger mixer supports mono output
2701 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
2702 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
2703 int16_t *src = (int16_t *)buffer;
2704 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002705
Eric Laurentad2dde92017-09-20 18:27:31 -07002706 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
2707 out->format != AUDIO_FORMAT_PCM_16_BIT,
2708 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002709
Eric Laurentad2dde92017-09-20 18:27:31 -07002710 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
2711 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
2712 }
2713 bytes_to_write /= 2;
2714 }
2715 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes_to_write);
2716
2717 long ns = (frames * NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002718 request_out_focus(out, ns);
2719
2720 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2721 if (use_mmap)
Eric Laurentad2dde92017-09-20 18:27:31 -07002722 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002723 else
Eric Laurentad2dde92017-09-20 18:27:31 -07002724 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002725
Haynes Mathew George03c40102016-01-29 17:57:48 -08002726 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002727 } else {
2728 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002729 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002730 }
2731
2732exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002733 // For PCM we always consume the buffer and return #bytes regardless of ret.
2734 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07002735 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07002736 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002737 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07002738
Andy Hung7401c7c2016-09-21 12:41:21 -07002739 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07002740 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07002741 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2742 ALOGE_IF(out->pcm != NULL,
2743 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07002744 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002745 // usleep not guaranteed for values over 1 second but we don't limit here.
2746 }
2747 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002748
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002749 pthread_mutex_unlock(&out->lock);
2750
2751 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002752 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002753 if (sleeptime_us != 0)
2754 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002755 }
2756 return bytes;
2757}
2758
2759static int out_get_render_position(const struct audio_stream_out *stream,
2760 uint32_t *dsp_frames)
2761{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002762 struct stream_out *out = (struct stream_out *)stream;
2763 *dsp_frames = 0;
2764 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002765 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002766 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002767 unsigned long frames = 0;
2768 // TODO: check return value
2769 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2770 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002771 ALOGVV("%s rendered frames %d sample_rate %d",
2772 __func__, *dsp_frames, out->sample_rate);
2773 }
2774 pthread_mutex_unlock(&out->lock);
2775 return 0;
2776 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002777 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002778}
2779
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002780static int out_add_audio_effect(const struct audio_stream *stream __unused,
2781 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002782{
2783 return 0;
2784}
2785
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002786static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2787 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002788{
2789 return 0;
2790}
2791
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002792static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2793 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002794{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002795 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002796}
2797
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002798static int out_get_presentation_position(const struct audio_stream_out *stream,
2799 uint64_t *frames, struct timespec *timestamp)
2800{
2801 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002802 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07002803 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002804
Eric Laurenta1478072015-09-21 17:21:52 -07002805 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002806
Eric Laurent949a0892013-09-20 09:20:13 -07002807 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2808 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002809 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002810 compress_get_tstamp(out->compr, &dsp_frames,
2811 &out->sample_rate);
2812 ALOGVV("%s rendered frames %ld sample_rate %d",
2813 __func__, dsp_frames, out->sample_rate);
2814 *frames = dsp_frames;
2815 ret = 0;
2816 /* this is the best we can do */
2817 clock_gettime(CLOCK_MONOTONIC, timestamp);
2818 }
2819 } else {
2820 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002821 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002822 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2823 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002824 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002825 // This adjustment accounts for buffering after app processor.
2826 // It is based on estimated DSP latency per use case, rather than exact.
2827 signed_frames -=
2828 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2829
Eric Laurent949a0892013-09-20 09:20:13 -07002830 // It would be unusual for this value to be negative, but check just in case ...
2831 if (signed_frames >= 0) {
2832 *frames = signed_frames;
2833 ret = 0;
2834 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002835 }
2836 }
2837 }
2838
2839 pthread_mutex_unlock(&out->lock);
2840
2841 return ret;
2842}
2843
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002844static int out_set_callback(struct audio_stream_out *stream,
2845 stream_callback_t callback, void *cookie)
2846{
2847 struct stream_out *out = (struct stream_out *)stream;
2848
2849 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002850 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002851 out->offload_callback = callback;
2852 out->offload_cookie = cookie;
2853 pthread_mutex_unlock(&out->lock);
2854 return 0;
2855}
2856
2857static int out_pause(struct audio_stream_out* stream)
2858{
2859 struct stream_out *out = (struct stream_out *)stream;
2860 int status = -ENOSYS;
2861 ALOGV("%s", __func__);
2862 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002863 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002864 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2865 status = compress_pause(out->compr);
2866 out->offload_state = OFFLOAD_STATE_PAUSED;
2867 }
2868 pthread_mutex_unlock(&out->lock);
2869 }
2870 return status;
2871}
2872
2873static int out_resume(struct audio_stream_out* stream)
2874{
2875 struct stream_out *out = (struct stream_out *)stream;
2876 int status = -ENOSYS;
2877 ALOGV("%s", __func__);
2878 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2879 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002880 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002881 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2882 status = compress_resume(out->compr);
2883 out->offload_state = OFFLOAD_STATE_PLAYING;
2884 }
2885 pthread_mutex_unlock(&out->lock);
2886 }
2887 return status;
2888}
2889
2890static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2891{
2892 struct stream_out *out = (struct stream_out *)stream;
2893 int status = -ENOSYS;
2894 ALOGV("%s", __func__);
2895 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002896 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002897 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2898 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2899 else
2900 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2901 pthread_mutex_unlock(&out->lock);
2902 }
2903 return status;
2904}
2905
2906static int out_flush(struct audio_stream_out* stream)
2907{
2908 struct stream_out *out = (struct stream_out *)stream;
2909 ALOGV("%s", __func__);
2910 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002911 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002912 stop_compressed_output_l(out);
2913 pthread_mutex_unlock(&out->lock);
2914 return 0;
2915 }
2916 return -ENOSYS;
2917}
2918
Eric Laurent0e46adf2016-12-16 12:49:24 -08002919static int out_stop(const struct audio_stream_out* stream)
2920{
2921 struct stream_out *out = (struct stream_out *)stream;
2922 struct audio_device *adev = out->dev;
2923 int ret = -ENOSYS;
2924
2925 ALOGV("%s", __func__);
2926 pthread_mutex_lock(&adev->lock);
2927 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2928 out->playback_started && out->pcm != NULL) {
2929 pcm_stop(out->pcm);
2930 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08002931 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002932 }
2933 pthread_mutex_unlock(&adev->lock);
2934 return ret;
2935}
2936
2937static int out_start(const struct audio_stream_out* stream)
2938{
2939 struct stream_out *out = (struct stream_out *)stream;
2940 struct audio_device *adev = out->dev;
2941 int ret = -ENOSYS;
2942
2943 ALOGV("%s", __func__);
2944 pthread_mutex_lock(&adev->lock);
2945 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2946 !out->playback_started && out->pcm != NULL) {
2947 ret = start_output_stream(out);
2948 if (ret == 0) {
2949 out->playback_started = true;
2950 }
2951 }
2952 pthread_mutex_unlock(&adev->lock);
2953 return ret;
2954}
2955
Phil Burkbc991042017-02-24 08:06:44 -08002956/*
2957 * Modify config->period_count based on min_size_frames
2958 */
2959static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
2960{
2961 int periodCountRequested = (min_size_frames + config->period_size - 1)
2962 / config->period_size;
2963 int periodCount = MMAP_PERIOD_COUNT_MIN;
2964
2965 ALOGV("%s original config.period_size = %d config.period_count = %d",
2966 __func__, config->period_size, config->period_count);
2967
2968 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
2969 periodCount *= 2;
2970 }
2971 config->period_count = periodCount;
2972
2973 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
2974}
2975
Eric Laurent0e46adf2016-12-16 12:49:24 -08002976static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2977 int32_t min_size_frames,
2978 struct audio_mmap_buffer_info *info)
2979{
2980 struct stream_out *out = (struct stream_out *)stream;
2981 struct audio_device *adev = out->dev;
2982 int ret = 0;
2983 unsigned int offset1;
2984 unsigned int frames1;
2985 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07002986 uint32_t mmap_size;
2987 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002988
2989 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08002990 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002991 pthread_mutex_lock(&adev->lock);
2992
2993 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002994 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002995 ret = -EINVAL;
2996 goto exit;
2997 }
2998 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08002999 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003000 ret = -ENOSYS;
3001 goto exit;
3002 }
3003 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3004 if (out->pcm_device_id < 0) {
3005 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3006 __func__, out->pcm_device_id, out->usecase);
3007 ret = -EINVAL;
3008 goto exit;
3009 }
Phil Burkbc991042017-02-24 08:06:44 -08003010
3011 adjust_mmap_period_count(&out->config, min_size_frames);
3012
Eric Laurent0e46adf2016-12-16 12:49:24 -08003013 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3014 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3015 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3016 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3017 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3018 step = "open";
3019 ret = -ENODEV;
3020 goto exit;
3021 }
3022 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3023 if (ret < 0) {
3024 step = "begin";
3025 goto exit;
3026 }
3027 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003028 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003029 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003030 ret = platform_get_mmap_data_fd(adev->platform,
3031 out->pcm_device_id, 0 /*playback*/,
3032 &info->shared_memory_fd,
3033 &mmap_size);
3034 if (ret < 0) {
3035 // Fall back to non exclusive mode
3036 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3037 } else {
3038 if (mmap_size < buffer_size) {
3039 step = "mmap";
3040 goto exit;
3041 }
3042 // FIXME: indicate exclusive mode support by returning a negative buffer size
3043 info->buffer_size_frames *= -1;
3044 }
3045 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003046
3047 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3048 if (ret < 0) {
3049 step = "commit";
3050 goto exit;
3051 }
Phil Burkbc991042017-02-24 08:06:44 -08003052
3053 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003054 ret = 0;
3055
3056 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3057 __func__, info->shared_memory_address, info->buffer_size_frames);
3058
3059exit:
3060 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003061 if (out->pcm == NULL) {
3062 ALOGE("%s: %s - %d", __func__, step, ret);
3063 } else {
3064 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003065 pcm_close(out->pcm);
3066 out->pcm = NULL;
3067 }
3068 }
3069 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003070 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003071 return ret;
3072}
3073
3074static int out_get_mmap_position(const struct audio_stream_out *stream,
3075 struct audio_mmap_position *position)
3076{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003077 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003078 struct stream_out *out = (struct stream_out *)stream;
3079 ALOGVV("%s", __func__);
3080 if (position == NULL) {
3081 return -EINVAL;
3082 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003083 lock_output_stream(out);
3084 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3085 out->pcm == NULL) {
3086 ret = -ENOSYS;
3087 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003088 }
3089
3090 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003091 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003092 if (ret < 0) {
3093 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003094 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003095 }
Andy Hungfc044e12017-03-20 09:24:22 -07003096 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003097exit:
3098 pthread_mutex_unlock(&out->lock);
3099 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003100}
3101
3102
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003103/** audio_stream_in implementation **/
3104static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3105{
3106 struct stream_in *in = (struct stream_in *)stream;
3107
3108 return in->config.rate;
3109}
3110
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003111static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003112{
3113 return -ENOSYS;
3114}
3115
3116static size_t in_get_buffer_size(const struct audio_stream *stream)
3117{
3118 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003119 return in->config.period_size * in->af_period_multiplier *
3120 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003121}
3122
3123static uint32_t in_get_channels(const struct audio_stream *stream)
3124{
3125 struct stream_in *in = (struct stream_in *)stream;
3126
3127 return in->channel_mask;
3128}
3129
vivek mehta4ed66e62016-04-15 23:33:34 -07003130static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003131{
vivek mehta4ed66e62016-04-15 23:33:34 -07003132 struct stream_in *in = (struct stream_in *)stream;
3133 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003134}
3135
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003136static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003137{
3138 return -ENOSYS;
3139}
3140
3141static int in_standby(struct audio_stream *stream)
3142{
3143 struct stream_in *in = (struct stream_in *)stream;
3144 struct audio_device *adev = in->dev;
3145 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003146 bool do_stop = true;
3147
Eric Laurent994a6932013-07-17 11:51:42 -07003148 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003149
3150 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003151
3152 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003153 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003154 audio_extn_sound_trigger_stop_lab(in);
3155 in->standby = true;
3156 }
3157
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003158 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003159 if (adev->adm_deregister_stream)
3160 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3161
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003162 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003163 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003164 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003165 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003166 in->capture_started = false;
3167 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003168 if (in->pcm) {
3169 pcm_close(in->pcm);
3170 in->pcm = NULL;
3171 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003172 adev->enable_voicerx = false;
3173 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003174 if (do_stop) {
3175 status = stop_input_stream(in);
3176 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003177 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003178 }
3179 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003180 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003181 return status;
3182}
3183
Andy Hungd13f0d32017-06-12 13:58:37 -07003184static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003185{
Andy Hungd13f0d32017-06-12 13:58:37 -07003186 struct stream_in *in = (struct stream_in *)stream;
3187
3188 // We try to get the lock for consistency,
3189 // but it isn't necessary for these variables.
3190 // If we're not in standby, we may be blocked on a read.
3191 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3192 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3193 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3194 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3195
3196 if (locked) {
3197 pthread_mutex_unlock(&in->lock);
3198 }
3199
3200 // dump error info
3201 (void)error_log_dump(
3202 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003203 return 0;
3204}
3205
3206static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3207{
3208 struct stream_in *in = (struct stream_in *)stream;
3209 struct audio_device *adev = in->dev;
3210 struct str_parms *parms;
3211 char *str;
3212 char value[32];
3213 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003214 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003215
Eric Laurent994a6932013-07-17 11:51:42 -07003216 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003217 parms = str_parms_create_str(kvpairs);
3218
3219 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3220
Eric Laurenta1478072015-09-21 17:21:52 -07003221 lock_input_stream(in);
3222
Eric Laurent150dbfe2013-02-27 14:31:02 -08003223 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003224 if (ret >= 0) {
3225 val = atoi(value);
3226 /* no audio source uses val == 0 */
3227 if ((in->source != val) && (val != 0)) {
3228 in->source = val;
3229 }
3230 }
3231
3232 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003233
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003234 if (ret >= 0) {
3235 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003236 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003237
3238 // Workaround: If routing to an non existing usb device, fail gracefully
3239 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003240 int card;
3241 if (audio_is_usb_in_device(val) &&
3242 (card = get_alive_usb_card(parms)) >= 0) {
3243
3244 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003245 status = -ENOSYS;
3246 } else {
3247
3248 in->device = val;
3249 /* If recording is in progress, change the tx device to new device */
3250 if (!in->standby) {
3251 ALOGV("update input routing change");
3252 // inform adm before actual routing to prevent glitches.
3253 if (adev->adm_on_routing_change) {
3254 adev->adm_on_routing_change(adev->adm_data,
3255 in->capture_handle);
3256 }
3257 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003258 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003259 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003260 }
3261 }
3262
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003263 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003264 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003265
3266 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003267 ALOGV("%s: exit: status(%d)", __func__, status);
3268 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003269}
3270
Haynes Mathew George569b7482017-05-08 14:44:27 -07003271static char* in_get_parameters(const struct audio_stream *stream,
3272 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003273{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003274 struct stream_in *in = (struct stream_in *)stream;
3275 struct str_parms *query = str_parms_create_str(keys);
3276 char *str;
3277 struct str_parms *reply = str_parms_create();
3278 bool replied = false;
3279
3280 ALOGV("%s: enter: keys - %s", __func__, keys);
3281 replied |= stream_get_parameter_channels(query, reply,
3282 &in->supported_channel_masks[0]);
3283 replied |= stream_get_parameter_formats(query, reply,
3284 &in->supported_formats[0]);
3285 replied |= stream_get_parameter_rates(query, reply,
3286 &in->supported_sample_rates[0]);
3287 if (replied) {
3288 str = str_parms_to_str(reply);
3289 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003290 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003291 }
3292 str_parms_destroy(query);
3293 str_parms_destroy(reply);
3294 ALOGV("%s: exit: returns - %s", __func__, str);
3295 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003296}
3297
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003298static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003299{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003300 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003301}
3302
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003303static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3304{
3305 if (!stream || !parms)
3306 return;
3307
3308 struct stream_in *in = (struct stream_in *)stream;
3309 struct audio_device *adev = in->dev;
3310
3311 card_status_t status;
3312 int card;
3313 if (parse_snd_card_status(parms, &card, &status) < 0)
3314 return;
3315
3316 pthread_mutex_lock(&adev->lock);
3317 bool valid_cb = (card == adev->snd_card);
3318 pthread_mutex_unlock(&adev->lock);
3319
3320 if (!valid_cb)
3321 return;
3322
3323 lock_input_stream(in);
3324 if (in->card_status != status)
3325 in->card_status = status;
3326 pthread_mutex_unlock(&in->lock);
3327
3328 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3329 use_case_table[in->usecase],
3330 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3331
3332 // a better solution would be to report error back to AF and let
3333 // it put the stream to standby
3334 if (status == CARD_STATUS_OFFLINE)
3335 in_standby(&in->stream.common);
3336
3337 return;
3338}
3339
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003340static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3341 size_t bytes)
3342{
3343 struct stream_in *in = (struct stream_in *)stream;
3344 struct audio_device *adev = in->dev;
3345 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003346 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003347 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003348
Eric Laurenta1478072015-09-21 17:21:52 -07003349 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003350 const size_t frame_size = audio_stream_in_frame_size(stream);
3351 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003352
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003353 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003354 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003355 /* Read from sound trigger HAL */
3356 audio_extn_sound_trigger_read(in, buffer, bytes);
3357 pthread_mutex_unlock(&in->lock);
3358 return bytes;
3359 }
3360
Eric Laurent0e46adf2016-12-16 12:49:24 -08003361 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3362 ret = -ENOSYS;
3363 goto exit;
3364 }
3365
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003366 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003367 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003368 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003369 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003370 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003371 goto exit;
3372 }
3373 in->standby = 0;
3374 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003375
Andy Hungd13f0d32017-06-12 13:58:37 -07003376 // errors that occur here are read errors.
3377 error_code = ERROR_CODE_READ;
3378
Haynes Mathew George03c40102016-01-29 17:57:48 -08003379 //what's the duration requested by the client?
3380 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3381 in->config.rate;
3382 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003383
Haynes Mathew George03c40102016-01-29 17:57:48 -08003384 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003385 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003386 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003387 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003388 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003389 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003390 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003391 if (ret < 0) {
3392 ALOGE("Failed to read w/err %s", strerror(errno));
3393 ret = -errno;
3394 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003395 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3396 if (bytes % 4 == 0) {
3397 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3398 int_buf_stream = buffer;
3399 for (size_t itt=0; itt < bytes/4 ; itt++) {
3400 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003401 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003402 } else {
3403 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3404 ret = -EINVAL;
3405 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003406 }
3407 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003408 }
3409
Haynes Mathew George03c40102016-01-29 17:57:48 -08003410 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003411
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003412 /*
3413 * Instead of writing zeroes here, we could trust the hardware
3414 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003415 * 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 -08003416 */
Andy Hungd13f0d32017-06-12 13:58:37 -07003417 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003418 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07003419 in->frames_muted += frames;
3420 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003421
3422exit:
3423 pthread_mutex_unlock(&in->lock);
3424
3425 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07003426 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003427 in_standby(&in->stream.common);
3428 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003429 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003430 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07003431 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08003432 }
3433 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003434 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003435 }
3436 return bytes;
3437}
3438
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003439static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003440{
3441 return 0;
3442}
3443
Andy Hung6ebe5962016-01-15 17:46:57 -08003444static int in_get_capture_position(const struct audio_stream_in *stream,
3445 int64_t *frames, int64_t *time)
3446{
3447 if (stream == NULL || frames == NULL || time == NULL) {
3448 return -EINVAL;
3449 }
3450 struct stream_in *in = (struct stream_in *)stream;
3451 int ret = -ENOSYS;
3452
3453 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003454 // note: ST sessions do not close the alsa pcm driver synchronously
3455 // on standby. Therefore, we may return an error even though the
3456 // pcm stream is still opened.
3457 if (in->standby) {
3458 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
3459 "%s stream in standby but pcm not NULL for non ST session", __func__);
3460 goto exit;
3461 }
Andy Hung6ebe5962016-01-15 17:46:57 -08003462 if (in->pcm) {
3463 struct timespec timestamp;
3464 unsigned int avail;
3465 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3466 *frames = in->frames_read + avail;
3467 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3468 ret = 0;
3469 }
3470 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003471exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08003472 pthread_mutex_unlock(&in->lock);
3473 return ret;
3474}
3475
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003476static int add_remove_audio_effect(const struct audio_stream *stream,
3477 effect_handle_t effect,
3478 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003479{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003480 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003481 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003482 int status = 0;
3483 effect_descriptor_t desc;
3484
3485 status = (*effect)->get_descriptor(effect, &desc);
3486 if (status != 0)
3487 return status;
3488
Eric Laurenta1478072015-09-21 17:21:52 -07003489 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003490 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003491 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003492 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003493 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003494 in->enable_aec != enable &&
3495 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3496 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003497 if (!enable)
3498 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003499 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3500 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3501 adev->enable_voicerx = enable;
3502 struct audio_usecase *usecase;
3503 struct listnode *node;
3504 list_for_each(node, &adev->usecase_list) {
3505 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07003506 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07003507 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05003508 }
3509 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003510 if (!in->standby)
3511 select_devices(in->dev, in->usecase);
3512 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003513 if (in->enable_ns != enable &&
3514 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3515 in->enable_ns = enable;
3516 if (!in->standby)
3517 select_devices(in->dev, in->usecase);
3518 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003519 pthread_mutex_unlock(&in->dev->lock);
3520 pthread_mutex_unlock(&in->lock);
3521
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003522 return 0;
3523}
3524
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003525static int in_add_audio_effect(const struct audio_stream *stream,
3526 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003527{
Eric Laurent994a6932013-07-17 11:51:42 -07003528 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003529 return add_remove_audio_effect(stream, effect, true);
3530}
3531
3532static int in_remove_audio_effect(const struct audio_stream *stream,
3533 effect_handle_t effect)
3534{
Eric Laurent994a6932013-07-17 11:51:42 -07003535 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003536 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003537}
3538
Eric Laurent0e46adf2016-12-16 12:49:24 -08003539static int in_stop(const struct audio_stream_in* stream)
3540{
3541 struct stream_in *in = (struct stream_in *)stream;
3542 struct audio_device *adev = in->dev;
3543
3544 int ret = -ENOSYS;
3545 ALOGV("%s", __func__);
3546 pthread_mutex_lock(&adev->lock);
3547 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3548 in->capture_started && in->pcm != NULL) {
3549 pcm_stop(in->pcm);
3550 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003551 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003552 }
3553 pthread_mutex_unlock(&adev->lock);
3554 return ret;
3555}
3556
3557static int in_start(const struct audio_stream_in* stream)
3558{
3559 struct stream_in *in = (struct stream_in *)stream;
3560 struct audio_device *adev = in->dev;
3561 int ret = -ENOSYS;
3562
3563 ALOGV("%s in %p", __func__, in);
3564 pthread_mutex_lock(&adev->lock);
3565 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3566 !in->capture_started && in->pcm != NULL) {
3567 if (!in->capture_started) {
3568 ret = start_input_stream(in);
3569 if (ret == 0) {
3570 in->capture_started = true;
3571 }
3572 }
3573 }
3574 pthread_mutex_unlock(&adev->lock);
3575 return ret;
3576}
3577
3578static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3579 int32_t min_size_frames,
3580 struct audio_mmap_buffer_info *info)
3581{
3582 struct stream_in *in = (struct stream_in *)stream;
3583 struct audio_device *adev = in->dev;
3584 int ret = 0;
3585 unsigned int offset1;
3586 unsigned int frames1;
3587 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003588 uint32_t mmap_size;
3589 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003590
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003591 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003592 pthread_mutex_lock(&adev->lock);
3593 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003594
Eric Laurent0e46adf2016-12-16 12:49:24 -08003595 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003596 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003597 ret = -EINVAL;
3598 goto exit;
3599 }
3600 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003601 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003602 ALOGV("%s in %p", __func__, in);
3603 ret = -ENOSYS;
3604 goto exit;
3605 }
3606 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3607 if (in->pcm_device_id < 0) {
3608 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3609 __func__, in->pcm_device_id, in->usecase);
3610 ret = -EINVAL;
3611 goto exit;
3612 }
Phil Burkbc991042017-02-24 08:06:44 -08003613
3614 adjust_mmap_period_count(&in->config, min_size_frames);
3615
Eric Laurent0e46adf2016-12-16 12:49:24 -08003616 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3617 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3618 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3619 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3620 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3621 step = "open";
3622 ret = -ENODEV;
3623 goto exit;
3624 }
3625
3626 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3627 if (ret < 0) {
3628 step = "begin";
3629 goto exit;
3630 }
3631 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003632 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003633 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003634 ret = platform_get_mmap_data_fd(adev->platform,
3635 in->pcm_device_id, 1 /*capture*/,
3636 &info->shared_memory_fd,
3637 &mmap_size);
3638 if (ret < 0) {
3639 // Fall back to non exclusive mode
3640 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3641 } else {
3642 if (mmap_size < buffer_size) {
3643 step = "mmap";
3644 goto exit;
3645 }
3646 // FIXME: indicate exclusive mode support by returning a negative buffer size
3647 info->buffer_size_frames *= -1;
3648 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08003649
Haynes Mathew George96483a22017-03-28 14:52:47 -07003650 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003651
3652 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3653 if (ret < 0) {
3654 step = "commit";
3655 goto exit;
3656 }
3657
Phil Burkbc991042017-02-24 08:06:44 -08003658 in->standby = false;
3659 ret = 0;
3660
Eric Laurent0e46adf2016-12-16 12:49:24 -08003661 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3662 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003663
3664exit:
3665 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003666 if (in->pcm == NULL) {
3667 ALOGE("%s: %s - %d", __func__, step, ret);
3668 } else {
3669 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003670 pcm_close(in->pcm);
3671 in->pcm = NULL;
3672 }
3673 }
3674 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003675 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003676 return ret;
3677}
3678
3679static int in_get_mmap_position(const struct audio_stream_in *stream,
3680 struct audio_mmap_position *position)
3681{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003682 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003683 struct stream_in *in = (struct stream_in *)stream;
3684 ALOGVV("%s", __func__);
3685 if (position == NULL) {
3686 return -EINVAL;
3687 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003688 lock_input_stream(in);
3689 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
3690 in->pcm == NULL) {
3691 ret = -ENOSYS;
3692 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003693 }
3694 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003695 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003696 if (ret < 0) {
3697 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003698 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003699 }
Andy Hungfc044e12017-03-20 09:24:22 -07003700 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003701exit:
3702 pthread_mutex_unlock(&in->lock);
3703 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003704}
3705
3706
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003707static int adev_open_output_stream(struct audio_hw_device *dev,
3708 audio_io_handle_t handle,
3709 audio_devices_t devices,
3710 audio_output_flags_t flags,
3711 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003712 struct audio_stream_out **stream_out,
3713 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003714{
3715 struct audio_device *adev = (struct audio_device *)dev;
3716 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003717 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003718 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
3719 bool is_usb_dev = audio_is_usb_out_device(devices) &&
3720 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003721
Andy Hungd9653bd2017-08-01 19:31:39 -07003722 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
3723 return -ENOSYS;
3724 }
3725
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003726 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
3727 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003728 *stream_out = NULL;
3729 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3730
3731 if (devices == AUDIO_DEVICE_NONE)
3732 devices = AUDIO_DEVICE_OUT_SPEAKER;
3733
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003734 out->flags = flags;
3735 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003736 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003737 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003738 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003739
3740 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003741 if ((is_hdmi || is_usb_dev) &&
3742 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
3743 (flags == AUDIO_OUTPUT_FLAG_NONE ||
3744 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003745 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003746 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003747 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003748 if (config->sample_rate == 0)
3749 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3750 if (config->channel_mask == 0)
3751 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3752 if (config->format == AUDIO_FORMAT_DEFAULT)
3753 config->format = AUDIO_FORMAT_PCM_16_BIT;
3754 } else if (is_usb_dev) {
3755 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
3756 &config->format,
3757 &out->supported_formats[0],
3758 MAX_SUPPORTED_FORMATS,
3759 &config->channel_mask,
3760 &out->supported_channel_masks[0],
3761 MAX_SUPPORTED_CHANNEL_MASKS,
3762 &config->sample_rate,
3763 &out->supported_sample_rates[0],
3764 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003765 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003766 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003767 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003768 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003769 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003770
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003771
Haynes Mathew George569b7482017-05-08 14:44:27 -07003772 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003773 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003774 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003775 if (is_hdmi) {
3776 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3777 out->config = pcm_config_hdmi_multi;
3778 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3779 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3780 out->config = pcm_config_mmap_playback;
3781 out->stream.start = out_start;
3782 out->stream.stop = out_stop;
3783 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3784 out->stream.get_mmap_position = out_get_mmap_position;
3785 } else {
3786 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3787 out->config = pcm_config_hifi;
3788 }
3789
3790 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003791 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003792 if (is_hdmi) {
3793 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
3794 audio_bytes_per_sample(out->format));
3795 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003796 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003797 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003798 pthread_mutex_lock(&adev->lock);
3799 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3800 pthread_mutex_unlock(&adev->lock);
3801
3802 // reject offload during card offline to allow
3803 // fallback to s/w paths
3804 if (offline) {
3805 ret = -ENODEV;
3806 goto error_open;
3807 }
3808
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003809 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3810 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3811 ALOGE("%s: Unsupported Offload information", __func__);
3812 ret = -EINVAL;
3813 goto error_open;
3814 }
3815 if (!is_supported_format(config->offload_info.format)) {
3816 ALOGE("%s: Unsupported audio format", __func__);
3817 ret = -EINVAL;
3818 goto error_open;
3819 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003820 out->sample_rate = config->offload_info.sample_rate;
3821 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
3822 out->channel_mask = config->offload_info.channel_mask;
3823 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
3824 out->channel_mask = config->channel_mask;
3825 else
3826 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3827
3828 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003829
3830 out->compr_config.codec = (struct snd_codec *)
3831 calloc(1, sizeof(struct snd_codec));
3832
3833 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003834
3835 out->stream.set_callback = out_set_callback;
3836 out->stream.pause = out_pause;
3837 out->stream.resume = out_resume;
3838 out->stream.drain = out_drain;
3839 out->stream.flush = out_flush;
3840
3841 out->compr_config.codec->id =
3842 get_snd_codec_id(config->offload_info.format);
3843 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3844 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003845 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003846 out->compr_config.codec->bit_rate =
3847 config->offload_info.bit_rate;
3848 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003849 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003850 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3851
3852 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3853 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003854
3855 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003856 create_offload_callback_thread(out);
3857 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3858 __func__, config->offload_info.version,
3859 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003860 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07003861 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003862 case 0:
3863 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
3864 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07003865 case 8000:
3866 case 16000:
3867 case 48000:
3868 out->sample_rate = config->sample_rate;
3869 break;
3870 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003871 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
3872 config->sample_rate);
3873 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3874 ret = -EINVAL;
3875 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003876 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003877 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
3878 switch (config->channel_mask) {
3879 case AUDIO_CHANNEL_NONE:
3880 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3881 break;
3882 case AUDIO_CHANNEL_OUT_STEREO:
3883 out->channel_mask = config->channel_mask;
3884 break;
3885 default:
3886 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
3887 config->channel_mask);
3888 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3889 ret = -EINVAL;
3890 break;
3891 }
3892 switch (config->format) {
3893 case AUDIO_FORMAT_DEFAULT:
3894 out->format = AUDIO_FORMAT_PCM_16_BIT;
3895 break;
3896 case AUDIO_FORMAT_PCM_16_BIT:
3897 out->format = config->format;
3898 break;
3899 default:
3900 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
3901 config->format);
3902 config->format = AUDIO_FORMAT_PCM_16_BIT;
3903 ret = -EINVAL;
3904 break;
3905 }
3906 if (ret != 0)
3907 goto error_open;
3908
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003909 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3910 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003911 out->config.rate = out->sample_rate;
3912 out->config.channels =
3913 audio_channel_count_from_out_mask(out->channel_mask);
3914 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003915 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003916 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
3917 switch (config->sample_rate) {
3918 case 0:
3919 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3920 break;
3921 case 8000:
3922 case 16000:
3923 case 32000:
3924 case 48000:
3925 out->sample_rate = config->sample_rate;
3926 break;
3927 default:
3928 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
3929 config->sample_rate);
3930 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3931 ret = -EINVAL;
3932 break;
3933 }
Eric Laurentad2dde92017-09-20 18:27:31 -07003934 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003935 switch (config->channel_mask) {
3936 case AUDIO_CHANNEL_NONE:
3937 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3938 break;
3939 case AUDIO_CHANNEL_OUT_STEREO:
3940 out->channel_mask = config->channel_mask;
3941 break;
3942 default:
3943 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
3944 config->channel_mask);
3945 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3946 ret = -EINVAL;
3947 break;
3948 }
3949 switch (config->format) {
3950 case AUDIO_FORMAT_DEFAULT:
3951 out->format = AUDIO_FORMAT_PCM_16_BIT;
3952 break;
3953 case AUDIO_FORMAT_PCM_16_BIT:
3954 out->format = config->format;
3955 break;
3956 default:
3957 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
3958 config->format);
3959 config->format = AUDIO_FORMAT_PCM_16_BIT;
3960 ret = -EINVAL;
3961 break;
3962 }
3963 if (ret != 0)
3964 goto error_open;
3965
vivek mehtaa68fea62017-06-08 19:04:02 -07003966 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07003967 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
3968 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003969 out->config.rate = out->sample_rate;
3970 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07003971 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003972 out->sample_rate,
3973 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07003974 out->config.channels,
3975 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003976 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07003977 out->config.period_size = buffer_size / frame_size;
3978 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
3979 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003980 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003981 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003982 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3983 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003984 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003985 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3986 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003987 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003988 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003989 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003990 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003991 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003992 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3993 out->config = pcm_config_mmap_playback;
3994 out->stream.start = out_start;
3995 out->stream.stop = out_stop;
3996 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3997 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003998 } else {
3999 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4000 out->config = pcm_config_low_latency;
4001 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004002
4003 if (config->sample_rate == 0) {
4004 out->sample_rate = out->config.rate;
4005 } else {
4006 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004007 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004008 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
4009 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
4010 } else {
4011 out->channel_mask = config->channel_mask;
4012 }
4013 if (config->format == AUDIO_FORMAT_DEFAULT)
4014 out->format = audio_format_from_pcm_format(out->config.format);
4015 else if (!audio_is_linear_pcm(config->format)) {
4016 config->format = AUDIO_FORMAT_PCM_16_BIT;
4017 ret = -EINVAL;
4018 goto error_open;
4019 } else {
4020 out->format = config->format;
4021 }
4022
4023 out->config.rate = out->sample_rate;
4024 out->config.channels =
4025 audio_channel_count_from_out_mask(out->channel_mask);
4026 if (out->format != audio_format_from_pcm_format(out->config.format)) {
4027 out->config.format = pcm_format_from_audio_format(out->format);
4028 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004029 }
Kevin Rocard50eff892017-05-02 16:52:05 -07004030
4031 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
4032 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004033 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004034 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
4035 __func__, config->sample_rate, config->format, config->channel_mask);
4036 config->sample_rate = out->sample_rate;
4037 config->format = out->format;
4038 config->channel_mask = out->channel_mask;
4039 ret = -EINVAL;
4040 goto error_open;
4041 }
4042
Andy Hung6fcba9c2014-03-18 11:53:32 -07004043 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
4044 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004045
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004046 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004047 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004048 adev->primary_output = out;
4049 else {
4050 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004051 ret = -EEXIST;
4052 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004053 }
4054 }
4055
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004056 /* Check if this usecase is already existing */
4057 pthread_mutex_lock(&adev->lock);
4058 if (get_usecase_from_list(adev, out->usecase) != NULL) {
4059 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004060 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004061 ret = -EEXIST;
4062 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004063 }
4064 pthread_mutex_unlock(&adev->lock);
4065
4066 out->stream.common.get_sample_rate = out_get_sample_rate;
4067 out->stream.common.set_sample_rate = out_set_sample_rate;
4068 out->stream.common.get_buffer_size = out_get_buffer_size;
4069 out->stream.common.get_channels = out_get_channels;
4070 out->stream.common.get_format = out_get_format;
4071 out->stream.common.set_format = out_set_format;
4072 out->stream.common.standby = out_standby;
4073 out->stream.common.dump = out_dump;
4074 out->stream.common.set_parameters = out_set_parameters;
4075 out->stream.common.get_parameters = out_get_parameters;
4076 out->stream.common.add_audio_effect = out_add_audio_effect;
4077 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4078 out->stream.get_latency = out_get_latency;
4079 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004080#ifdef NO_AUDIO_OUT
4081 out->stream.write = out_write_for_no_output;
4082#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004083 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004084#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004085 out->stream.get_render_position = out_get_render_position;
4086 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004087 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004088
Eric Laurent0e46adf2016-12-16 12:49:24 -08004089 if (out->realtime)
4090 out->af_period_multiplier = af_period_multiplier;
4091 else
4092 out->af_period_multiplier = 1;
4093
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004094 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004095 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004096 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004097
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004098 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004099 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004100 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4101
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004102 config->format = out->stream.common.get_format(&out->stream.common);
4103 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4104 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4105
Andy Hunga452b0a2017-03-15 14:51:15 -07004106 out->error_log = error_log_create(
4107 ERROR_LOG_ENTRIES,
4108 1000000000 /* aggregate consecutive identical errors within one second in ns */);
4109
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004110 /*
4111 By locking output stream before registering, we allow the callback
4112 to update stream's state only after stream's initial state is set to
4113 adev state.
4114 */
4115 lock_output_stream(out);
4116 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4117 pthread_mutex_lock(&adev->lock);
4118 out->card_status = adev->card_status;
4119 pthread_mutex_unlock(&adev->lock);
4120 pthread_mutex_unlock(&out->lock);
4121
vivek mehta4a824772017-06-08 19:05:49 -07004122 stream_app_type_cfg_init(&out->app_type_cfg);
4123
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004124 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004125
Eric Laurent994a6932013-07-17 11:51:42 -07004126 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004127 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004128
4129error_open:
4130 free(out);
4131 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07004132 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004133 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004134}
4135
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004136static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004137 struct audio_stream_out *stream)
4138{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004139 struct stream_out *out = (struct stream_out *)stream;
4140 struct audio_device *adev = out->dev;
4141
Eric Laurent994a6932013-07-17 11:51:42 -07004142 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004143
4144 // must deregister from sndmonitor first to prevent races
4145 // between the callback and close_stream
4146 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004147 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004148 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
4149 destroy_offload_callback_thread(out);
4150
4151 if (out->compr_config.codec != NULL)
4152 free(out->compr_config.codec);
4153 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004154
4155 if (adev->voice_tx_output == out)
4156 adev->voice_tx_output = NULL;
4157
Andy Hunga452b0a2017-03-15 14:51:15 -07004158 error_log_destroy(out->error_log);
4159 out->error_log = NULL;
4160
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004161 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004162 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004163 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004164 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004165 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004166}
4167
4168static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4169{
4170 struct audio_device *adev = (struct audio_device *)dev;
4171 struct str_parms *parms;
4172 char *str;
4173 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004174 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004175 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07004176 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004177
Joe Onorato188b6222016-03-01 11:02:27 -08004178 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004179
4180 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004181
4182 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004183 status = voice_set_parameters(adev, parms);
4184 if (status != 0) {
4185 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004186 }
4187
4188 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4189 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07004190 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004191 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4192 adev->bluetooth_nrec = true;
4193 else
4194 adev->bluetooth_nrec = false;
4195 }
4196
4197 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4198 if (ret >= 0) {
4199 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4200 adev->screen_off = false;
4201 else
4202 adev->screen_off = true;
4203 }
4204
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004205 ret = str_parms_get_int(parms, "rotation", &val);
4206 if (ret >= 0) {
4207 bool reverse_speakers = false;
4208 switch(val) {
4209 // FIXME: note that the code below assumes that the speakers are in the correct placement
4210 // relative to the user when the device is rotated 90deg from its default rotation. This
4211 // assumption is device-specific, not platform-specific like this code.
4212 case 270:
4213 reverse_speakers = true;
4214 break;
4215 case 0:
4216 case 90:
4217 case 180:
4218 break;
4219 default:
4220 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07004221 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004222 }
Eric Laurent03f09432014-03-25 18:09:11 -07004223 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004224 // check and set swap
4225 // - check if orientation changed and speaker active
4226 // - set rotation and cache the rotation value
4227 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004228 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004229 }
4230
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004231 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4232 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004233 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004234 }
4235
David Linee3fe402017-03-13 10:00:42 -07004236 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4237 if (ret >= 0) {
4238 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004239 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004240 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4241 if (ret >= 0) {
4242 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004243 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004244 }
Eric Laurent99dab492017-06-17 15:19:08 -07004245 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004246 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4247 if (ret >= 0) {
4248 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004249 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004250 }
4251 }
4252 }
4253
4254 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4255 if (ret >= 0) {
4256 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004257 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004258 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4259 if (ret >= 0) {
4260 const int card = atoi(value);
4261
Eric Laurent99dab492017-06-17 15:19:08 -07004262 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004263 }
Eric Laurent99dab492017-06-17 15:19:08 -07004264 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004265 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4266 if (ret >= 0) {
4267 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004268 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004269 }
4270 }
4271 }
4272
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004273 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004274done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004275 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004276 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004277 ALOGV("%s: exit with code(%d)", __func__, status);
4278 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004279}
4280
4281static char* adev_get_parameters(const struct audio_hw_device *dev,
4282 const char *keys)
4283{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004284 struct audio_device *adev = (struct audio_device *)dev;
4285 struct str_parms *reply = str_parms_create();
4286 struct str_parms *query = str_parms_create_str(keys);
4287 char *str;
4288
4289 pthread_mutex_lock(&adev->lock);
4290
4291 voice_get_parameters(adev, query, reply);
4292 str = str_parms_to_str(reply);
4293 str_parms_destroy(query);
4294 str_parms_destroy(reply);
4295
4296 pthread_mutex_unlock(&adev->lock);
4297 ALOGV("%s: exit: returns - %s", __func__, str);
4298 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004299}
4300
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004301static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004302{
4303 return 0;
4304}
4305
Haynes Mathew George5191a852013-09-11 14:19:36 -07004306static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4307{
4308 int ret;
4309 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004310
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004311 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4312
Haynes Mathew George5191a852013-09-11 14:19:36 -07004313 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004314 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004315 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004316
Haynes Mathew George5191a852013-09-11 14:19:36 -07004317 return ret;
4318}
4319
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004320static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004321{
4322 return -ENOSYS;
4323}
4324
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004325static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4326 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004327{
4328 return -ENOSYS;
4329}
4330
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004331static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004332{
4333 return -ENOSYS;
4334}
4335
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004336static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004337{
4338 return -ENOSYS;
4339}
4340
4341static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4342{
4343 struct audio_device *adev = (struct audio_device *)dev;
4344
4345 pthread_mutex_lock(&adev->lock);
4346 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004347 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004348 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004349 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4350 voice_is_in_call(adev)) {
4351 voice_stop_call(adev);
4352 adev->current_call_output = NULL;
4353 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004354 }
4355 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004356
4357 audio_extn_extspk_set_mode(adev->extspk, mode);
4358
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004359 return 0;
4360}
4361
4362static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4363{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004364 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004365 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004366
Eric Laurent2bafff12016-03-17 12:17:23 -07004367 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004368 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004369 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4370 ret = audio_extn_hfp_set_mic_mute(adev, state);
4371 } else {
4372 ret = voice_set_mic_mute(adev, state);
4373 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004374 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004375 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004376
4377 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004378}
4379
4380static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4381{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004382 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004383 return 0;
4384}
4385
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004386static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004387 const struct audio_config *config)
4388{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004389 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004390
Eric Laurent74b55762017-07-09 17:04:53 -07004391 /* Don't know if USB HIFI in this context so use true to be conservative */
4392 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4393 true /*is_usb_hifi */) != 0)
4394 return 0;
4395
vivek mehtaa68fea62017-06-08 19:04:02 -07004396 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4397 config->sample_rate, config->format,
4398 channel_count,
4399 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004400}
4401
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004402static bool adev_input_allow_hifi_record(struct audio_device *adev,
4403 audio_devices_t devices,
4404 audio_input_flags_t flags,
4405 audio_source_t source) {
4406 const bool allowed = true;
4407
4408 if (!audio_is_usb_in_device(devices))
4409 return !allowed;
4410
4411 switch (flags) {
4412 case AUDIO_INPUT_FLAG_NONE:
4413 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4414 break;
4415 default:
4416 return !allowed;
4417 }
4418
4419 switch (source) {
4420 case AUDIO_SOURCE_DEFAULT:
4421 case AUDIO_SOURCE_MIC:
4422 case AUDIO_SOURCE_UNPROCESSED:
4423 break;
4424 default:
4425 return !allowed;
4426 }
4427
4428 switch (adev->mode) {
4429 case 0:
4430 break;
4431 default:
4432 return !allowed;
4433 }
4434
4435 return allowed;
4436}
4437
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004438static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004439 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004440 audio_devices_t devices,
4441 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004442 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004443 audio_input_flags_t flags,
4444 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004445 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004446{
4447 struct audio_device *adev = (struct audio_device *)dev;
4448 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004449 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004450 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004451 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004452 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004453 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4454 devices,
4455 flags,
4456 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004457 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004458 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004459
Andy Hungd9653bd2017-08-01 19:31:39 -07004460 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
4461 return -ENOSYS;
4462 }
4463
Eric Laurent74b55762017-07-09 17:04:53 -07004464 if (!(is_usb_dev && may_use_hifi_record)) {
4465 if (config->sample_rate == 0)
4466 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4467 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4468 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4469 if (config->format == AUDIO_FORMAT_DEFAULT)
4470 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004471
Eric Laurent74b55762017-07-09 17:04:53 -07004472 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
4473
4474 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
4475 return -EINVAL;
4476 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004477
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004478 if (audio_extn_tfa_98xx_is_supported() &&
4479 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004480 return -EINVAL;
4481
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004482 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4483
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004484 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004485 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004486
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004487 in->stream.common.get_sample_rate = in_get_sample_rate;
4488 in->stream.common.set_sample_rate = in_set_sample_rate;
4489 in->stream.common.get_buffer_size = in_get_buffer_size;
4490 in->stream.common.get_channels = in_get_channels;
4491 in->stream.common.get_format = in_get_format;
4492 in->stream.common.set_format = in_set_format;
4493 in->stream.common.standby = in_standby;
4494 in->stream.common.dump = in_dump;
4495 in->stream.common.set_parameters = in_set_parameters;
4496 in->stream.common.get_parameters = in_get_parameters;
4497 in->stream.common.add_audio_effect = in_add_audio_effect;
4498 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4499 in->stream.set_gain = in_set_gain;
4500 in->stream.read = in_read;
4501 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08004502 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004503
4504 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004505 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004506 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004507 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004508 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004509 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004510
Haynes Mathew George569b7482017-05-08 14:44:27 -07004511 if (is_usb_dev && may_use_hifi_record) {
4512 /* HiFi record selects an appropriate format, channel, rate combo
4513 depending on sink capabilities*/
4514 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
4515 &config->format,
4516 &in->supported_formats[0],
4517 MAX_SUPPORTED_FORMATS,
4518 &config->channel_mask,
4519 &in->supported_channel_masks[0],
4520 MAX_SUPPORTED_CHANNEL_MASKS,
4521 &config->sample_rate,
4522 &in->supported_sample_rates[0],
4523 MAX_SUPPORTED_SAMPLE_RATES);
4524 if (ret != 0) {
4525 ret = -EINVAL;
4526 goto err_open;
4527 }
Eric Laurent74b55762017-07-09 17:04:53 -07004528 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004529 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07004530 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07004531 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
4532 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
4533 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4534 bool ret_error = false;
4535 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4536 from HAL is 8_24
4537 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4538 8_24 return error indicating supported format is 8_24
4539 *> In case of any other source requesting 24 bit or float return error
4540 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07004541
vivek mehta57ff9b52016-04-28 14:13:08 -07004542 on error flinger will retry with supported format passed
4543 */
4544 if (source != AUDIO_SOURCE_UNPROCESSED) {
4545 config->format = AUDIO_FORMAT_PCM_16_BIT;
4546 ret_error = true;
4547 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
4548 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
4549 ret_error = true;
4550 }
4551
4552 if (ret_error) {
4553 ret = -EINVAL;
4554 goto err_open;
4555 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004556 }
4557
vivek mehta57ff9b52016-04-28 14:13:08 -07004558 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07004559 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07004560
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004561 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004562 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
4563 if (config->sample_rate == 0)
4564 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4565 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4566 config->sample_rate != 8000) {
4567 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4568 ret = -EINVAL;
4569 goto err_open;
4570 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004571
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004572 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4573 config->format = AUDIO_FORMAT_PCM_16_BIT;
4574 ret = -EINVAL;
4575 goto err_open;
4576 }
4577
4578 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4579 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07004580 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004581 } else if (is_usb_dev && may_use_hifi_record) {
4582 in->usecase = USECASE_AUDIO_RECORD_HIFI;
4583 in->config = pcm_config_audio_capture;
4584 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004585 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4586 config->sample_rate,
4587 config->format,
4588 channel_count,
4589 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004590 in->config.period_size = buffer_size / frame_size;
4591 in->config.rate = config->sample_rate;
4592 in->af_period_multiplier = 1;
4593 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004594 } else {
4595 in->usecase = USECASE_AUDIO_RECORD;
4596 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08004597 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004598 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07004599#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004600 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07004601#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08004602 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004603 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08004604 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004605 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004606 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4607 config->sample_rate,
4608 config->format,
4609 channel_count,
4610 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004611 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004612 in->config.rate = config->sample_rate;
4613 in->af_period_multiplier = 1;
4614 } else {
4615 // period size is left untouched for rt mode playback
4616 in->config = pcm_config_audio_capture_rt;
4617 in->af_period_multiplier = af_period_multiplier;
4618 }
4619 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
4620 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004621 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08004622 in->usecase = USECASE_AUDIO_RECORD_MMAP;
4623 in->config = pcm_config_mmap_capture;
4624 in->stream.start = in_start;
4625 in->stream.stop = in_stop;
4626 in->stream.create_mmap_buffer = in_create_mmap_buffer;
4627 in->stream.get_mmap_position = in_get_mmap_position;
4628 in->af_period_multiplier = 1;
4629 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07004630 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07004631 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07004632 (config->sample_rate == 8000 ||
4633 config->sample_rate == 16000 ||
4634 config->sample_rate == 32000 ||
4635 config->sample_rate == 48000) &&
4636 channel_count == 1) {
4637 in->usecase = USECASE_AUDIO_RECORD_VOIP;
4638 in->config = pcm_config_audio_capture;
4639 frame_size = audio_stream_in_frame_size(&in->stream);
4640 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
4641 config->sample_rate,
4642 config->format,
4643 channel_count, false /*is_low_latency*/);
4644 in->config.period_size = buffer_size / frame_size;
4645 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
4646 in->config.rate = config->sample_rate;
4647 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004648 } else {
4649 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004650 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004651 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4652 config->sample_rate,
4653 config->format,
4654 channel_count,
4655 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004656 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004657 in->config.rate = config->sample_rate;
4658 in->af_period_multiplier = 1;
4659 }
4660 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
4661 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004662 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004663
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004664 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07004665 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004666
Andy Hungd13f0d32017-06-12 13:58:37 -07004667 in->error_log = error_log_create(
4668 ERROR_LOG_ENTRIES,
4669 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
4670
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004671 /* This stream could be for sound trigger lab,
4672 get sound trigger pcm if present */
4673 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004674
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004675 lock_input_stream(in);
4676 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
4677 pthread_mutex_lock(&adev->lock);
4678 in->card_status = adev->card_status;
4679 pthread_mutex_unlock(&adev->lock);
4680 pthread_mutex_unlock(&in->lock);
4681
vivek mehta4a824772017-06-08 19:05:49 -07004682 stream_app_type_cfg_init(&in->app_type_cfg);
4683
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004684 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004685 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004686 return 0;
4687
4688err_open:
4689 free(in);
4690 *stream_in = NULL;
4691 return ret;
4692}
4693
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004694static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004695 struct audio_stream_in *stream)
4696{
Andy Hungd13f0d32017-06-12 13:58:37 -07004697 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004698 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004699
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004700 // must deregister from sndmonitor first to prevent races
4701 // between the callback and close_stream
4702 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004703 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07004704
4705 error_log_destroy(in->error_log);
4706 in->error_log = NULL;
4707
Andy Hung0dbb52b2017-08-09 13:51:38 -07004708 pthread_mutex_destroy(&in->pre_lock);
4709 pthread_mutex_destroy(&in->lock);
4710
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004711 free(stream);
4712
4713 return;
4714}
4715
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004716static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004717{
4718 return 0;
4719}
4720
Andy Hung31aca912014-03-20 17:14:59 -07004721/* verifies input and output devices and their capabilities.
4722 *
4723 * This verification is required when enabling extended bit-depth or
4724 * sampling rates, as not all qcom products support it.
4725 *
4726 * Suitable for calling only on initialization such as adev_open().
4727 * It fills the audio_device use_case_table[] array.
4728 *
4729 * Has a side-effect that it needs to configure audio routing / devices
4730 * in order to power up the devices and read the device parameters.
4731 * It does not acquire any hw device lock. Should restore the devices
4732 * back to "normal state" upon completion.
4733 */
4734static int adev_verify_devices(struct audio_device *adev)
4735{
4736 /* enumeration is a bit difficult because one really wants to pull
4737 * the use_case, device id, etc from the hidden pcm_device_table[].
4738 * In this case there are the following use cases and device ids.
4739 *
4740 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
4741 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004742 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07004743 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
4744 * [USECASE_AUDIO_RECORD] = {0, 0},
4745 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
4746 * [USECASE_VOICE_CALL] = {2, 2},
4747 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004748 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07004749 * USECASE_VOICE_CALL omitted, but possible for either input or output.
4750 */
4751
4752 /* should be the usecases enabled in adev_open_input_stream() */
4753 static const int test_in_usecases[] = {
4754 USECASE_AUDIO_RECORD,
4755 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
4756 };
4757 /* should be the usecases enabled in adev_open_output_stream()*/
4758 static const int test_out_usecases[] = {
4759 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
4760 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
4761 };
4762 static const usecase_type_t usecase_type_by_dir[] = {
4763 PCM_PLAYBACK,
4764 PCM_CAPTURE,
4765 };
4766 static const unsigned flags_by_dir[] = {
4767 PCM_OUT,
4768 PCM_IN,
4769 };
4770
4771 size_t i;
4772 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004773 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07004774 char info[512]; /* for possible debug info */
4775
4776 for (dir = 0; dir < 2; ++dir) {
4777 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
4778 const unsigned flags_dir = flags_by_dir[dir];
4779 const size_t testsize =
4780 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
4781 const int *testcases =
4782 dir ? test_in_usecases : test_out_usecases;
4783 const audio_devices_t audio_device =
4784 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
4785
4786 for (i = 0; i < testsize; ++i) {
4787 const audio_usecase_t audio_usecase = testcases[i];
4788 int device_id;
4789 snd_device_t snd_device;
4790 struct pcm_params **pparams;
4791 struct stream_out out;
4792 struct stream_in in;
4793 struct audio_usecase uc_info;
4794 int retval;
4795
4796 pparams = &adev->use_case_table[audio_usecase];
4797 pcm_params_free(*pparams); /* can accept null input */
4798 *pparams = NULL;
4799
4800 /* find the device ID for the use case (signed, for error) */
4801 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
4802 if (device_id < 0)
4803 continue;
4804
4805 /* prepare structures for device probing */
4806 memset(&uc_info, 0, sizeof(uc_info));
4807 uc_info.id = audio_usecase;
4808 uc_info.type = usecase_type;
4809 if (dir) {
4810 adev->active_input = &in;
4811 memset(&in, 0, sizeof(in));
4812 in.device = audio_device;
4813 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4814 uc_info.stream.in = &in;
4815 } else {
4816 adev->active_input = NULL;
4817 }
4818 memset(&out, 0, sizeof(out));
4819 out.devices = audio_device; /* only field needed in select_devices */
4820 uc_info.stream.out = &out;
4821 uc_info.devices = audio_device;
4822 uc_info.in_snd_device = SND_DEVICE_NONE;
4823 uc_info.out_snd_device = SND_DEVICE_NONE;
4824 list_add_tail(&adev->usecase_list, &uc_info.list);
4825
4826 /* select device - similar to start_(in/out)put_stream() */
4827 retval = select_devices(adev, audio_usecase);
4828 if (retval >= 0) {
4829 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4830#if LOG_NDEBUG == 0
4831 if (*pparams) {
4832 ALOGV("%s: (%s) card %d device %d", __func__,
4833 dir ? "input" : "output", card_id, device_id);
4834 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004835 } else {
4836 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4837 }
4838#endif
4839 }
4840
4841 /* deselect device - similar to stop_(in/out)put_stream() */
4842 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004843 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004844 /* 2. Disable the rx device */
4845 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004846 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004847 list_remove(&uc_info.list);
4848 }
4849 }
4850 adev->active_input = NULL; /* restore adev state */
4851 return 0;
4852}
4853
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004854static int adev_close(hw_device_t *device)
4855{
Andy Hung31aca912014-03-20 17:14:59 -07004856 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004857 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004858
4859 if (!adev)
4860 return 0;
4861
4862 pthread_mutex_lock(&adev_init_lock);
4863
4864 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004865 audio_extn_snd_mon_unregister_listener(adev);
4866 audio_extn_tfa_98xx_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004867 audio_route_free(adev->audio_route);
4868 free(adev->snd_dev_ref_cnt);
4869 platform_deinit(adev->platform);
4870 audio_extn_extspk_deinit(adev->extspk);
4871 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004872 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004873 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4874 pcm_params_free(adev->use_case_table[i]);
4875 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004876 if (adev->adm_deinit)
4877 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004878 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004879 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004880 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004881
4882 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004883
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004884 return 0;
4885}
4886
Glenn Kasten4f993392014-05-14 07:30:48 -07004887/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4888 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4889 * just that it _might_ work.
4890 */
4891static int period_size_is_plausible_for_low_latency(int period_size)
4892{
4893 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004894 case 48:
4895 case 96:
4896 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004897 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004898 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004899 case 240:
4900 case 320:
4901 case 480:
4902 return 1;
4903 default:
4904 return 0;
4905 }
4906}
4907
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004908static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4909{
4910 int card;
4911 card_status_t status;
4912
4913 if (!parms)
4914 return;
4915
4916 if (parse_snd_card_status(parms, &card, &status) < 0)
4917 return;
4918
4919 pthread_mutex_lock(&adev->lock);
4920 bool valid_cb = (card == adev->snd_card);
4921 if (valid_cb) {
4922 if (adev->card_status != status) {
4923 adev->card_status = status;
4924 platform_snd_card_update(adev->platform, status);
4925 }
4926 }
4927 pthread_mutex_unlock(&adev->lock);
4928 return;
4929}
4930
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004931static int adev_open(const hw_module_t *module, const char *name,
4932 hw_device_t **device)
4933{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004934 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004935
Eric Laurent2bafff12016-03-17 12:17:23 -07004936 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004937 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004938 pthread_mutex_lock(&adev_init_lock);
4939 if (audio_device_ref_count != 0) {
4940 *device = &adev->device.common;
4941 audio_device_ref_count++;
4942 ALOGV("%s: returning existing instance of adev", __func__);
4943 ALOGV("%s: exit", __func__);
4944 pthread_mutex_unlock(&adev_init_lock);
4945 return 0;
4946 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004947 adev = calloc(1, sizeof(struct audio_device));
4948
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004949 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4950
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004951 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4952 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4953 adev->device.common.module = (struct hw_module_t *)module;
4954 adev->device.common.close = adev_close;
4955
4956 adev->device.init_check = adev_init_check;
4957 adev->device.set_voice_volume = adev_set_voice_volume;
4958 adev->device.set_master_volume = adev_set_master_volume;
4959 adev->device.get_master_volume = adev_get_master_volume;
4960 adev->device.set_master_mute = adev_set_master_mute;
4961 adev->device.get_master_mute = adev_get_master_mute;
4962 adev->device.set_mode = adev_set_mode;
4963 adev->device.set_mic_mute = adev_set_mic_mute;
4964 adev->device.get_mic_mute = adev_get_mic_mute;
4965 adev->device.set_parameters = adev_set_parameters;
4966 adev->device.get_parameters = adev_get_parameters;
4967 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4968 adev->device.open_output_stream = adev_open_output_stream;
4969 adev->device.close_output_stream = adev_close_output_stream;
4970 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004971
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004972 adev->device.close_input_stream = adev_close_input_stream;
4973 adev->device.dump = adev_dump;
4974
4975 /* Set the default route before the PCM stream is opened */
4976 pthread_mutex_lock(&adev->lock);
4977 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004978 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004979 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004980 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004981 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004982 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004983 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004984 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004985 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004986 pthread_mutex_unlock(&adev->lock);
4987
4988 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004989 adev->platform = platform_init(adev);
4990 if (!adev->platform) {
4991 free(adev->snd_dev_ref_cnt);
4992 free(adev);
4993 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4994 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004995 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004996 return -EINVAL;
4997 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05004998 adev->extspk = audio_extn_extspk_init(adev);
4999
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005000 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5001 if (adev->visualizer_lib == NULL) {
5002 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5003 } else {
5004 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5005 adev->visualizer_start_output =
5006 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5007 "visualizer_hal_start_output");
5008 adev->visualizer_stop_output =
5009 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5010 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07005011 }
5012
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005013 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5014 if (adev->offload_effects_lib == NULL) {
5015 ALOGW("%s: DLOPEN failed for %s", __func__,
5016 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5017 } else {
5018 ALOGV("%s: DLOPEN successful for %s", __func__,
5019 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5020 adev->offload_effects_start_output =
5021 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5022 "offload_effects_bundle_hal_start_output");
5023 adev->offload_effects_stop_output =
5024 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5025 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07005026 }
5027
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005028 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5029 if (adev->adm_lib == NULL) {
5030 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5031 } else {
5032 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5033 adev->adm_init = (adm_init_t)
5034 dlsym(adev->adm_lib, "adm_init");
5035 adev->adm_deinit = (adm_deinit_t)
5036 dlsym(adev->adm_lib, "adm_deinit");
5037 adev->adm_register_input_stream = (adm_register_input_stream_t)
5038 dlsym(adev->adm_lib, "adm_register_input_stream");
5039 adev->adm_register_output_stream = (adm_register_output_stream_t)
5040 dlsym(adev->adm_lib, "adm_register_output_stream");
5041 adev->adm_deregister_stream = (adm_deregister_stream_t)
5042 dlsym(adev->adm_lib, "adm_deregister_stream");
5043 adev->adm_request_focus = (adm_request_focus_t)
5044 dlsym(adev->adm_lib, "adm_request_focus");
5045 adev->adm_abandon_focus = (adm_abandon_focus_t)
5046 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08005047 adev->adm_set_config = (adm_set_config_t)
5048 dlsym(adev->adm_lib, "adm_set_config");
5049 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5050 dlsym(adev->adm_lib, "adm_request_focus_v2");
5051 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5052 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5053 adev->adm_on_routing_change = (adm_on_routing_change_t)
5054 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005055 }
5056
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005057 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005058 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005059
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005060 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005061
Andy Hung31aca912014-03-20 17:14:59 -07005062 if (k_enable_extended_precision)
5063 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005064
Glenn Kasten4f993392014-05-14 07:30:48 -07005065 char value[PROPERTY_VALUE_MAX];
5066 int trial;
5067 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5068 trial = atoi(value);
5069 if (period_size_is_plausible_for_low_latency(trial)) {
5070 pcm_config_low_latency.period_size = trial;
5071 pcm_config_low_latency.start_threshold = trial / 4;
5072 pcm_config_low_latency.avail_min = trial / 4;
5073 configured_low_latency_capture_period_size = trial;
5074 }
5075 }
5076 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5077 trial = atoi(value);
5078 if (period_size_is_plausible_for_low_latency(trial)) {
5079 configured_low_latency_capture_period_size = trial;
5080 }
5081 }
5082
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005083 // commented as full set of app type cfg is sent from platform
5084 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005085 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005086
5087 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5088 af_period_multiplier = atoi(value);
5089 if (af_period_multiplier < 0) {
5090 af_period_multiplier = 2;
5091 } else if (af_period_multiplier > 4) {
5092 af_period_multiplier = 4;
5093 }
5094 ALOGV("new period_multiplier = %d", af_period_multiplier);
5095 }
5096
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005097 audio_extn_tfa_98xx_init(adev);
5098
vivek mehta1a9b7c02015-06-25 11:49:38 -07005099 pthread_mutex_unlock(&adev_init_lock);
5100
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005101 if (adev->adm_init)
5102 adev->adm_data = adev->adm_init();
5103
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005104 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005105 audio_extn_snd_mon_init();
5106 pthread_mutex_lock(&adev->lock);
5107 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
5108 adev->card_status = CARD_STATUS_ONLINE;
5109 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005110 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005111
Eric Laurent2bafff12016-03-17 12:17:23 -07005112 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005113 return 0;
5114}
5115
5116static struct hw_module_methods_t hal_module_methods = {
5117 .open = adev_open,
5118};
5119
5120struct audio_module HAL_MODULE_INFO_SYM = {
5121 .common = {
5122 .tag = HARDWARE_MODULE_TAG,
5123 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5124 .hal_api_version = HARDWARE_HAL_API_VERSION,
5125 .id = AUDIO_HARDWARE_MODULE_ID,
5126 .name = "QCOM Audio HAL",
5127 .author = "Code Aurora Forum",
5128 .methods = &hal_module_methods,
5129 },
5130};