blob: dba1555a7e3f8be3320032271fc415395a00b725 [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__);
2990 pthread_mutex_lock(&adev->lock);
2991
2992 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002993 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002994 ret = -EINVAL;
2995 goto exit;
2996 }
2997 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08002998 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002999 ret = -ENOSYS;
3000 goto exit;
3001 }
3002 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3003 if (out->pcm_device_id < 0) {
3004 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3005 __func__, out->pcm_device_id, out->usecase);
3006 ret = -EINVAL;
3007 goto exit;
3008 }
Phil Burkbc991042017-02-24 08:06:44 -08003009
3010 adjust_mmap_period_count(&out->config, min_size_frames);
3011
Eric Laurent0e46adf2016-12-16 12:49:24 -08003012 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3013 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3014 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3015 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3016 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3017 step = "open";
3018 ret = -ENODEV;
3019 goto exit;
3020 }
3021 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3022 if (ret < 0) {
3023 step = "begin";
3024 goto exit;
3025 }
3026 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003027 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003028 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003029 ret = platform_get_mmap_data_fd(adev->platform,
3030 out->pcm_device_id, 0 /*playback*/,
3031 &info->shared_memory_fd,
3032 &mmap_size);
3033 if (ret < 0) {
3034 // Fall back to non exclusive mode
3035 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3036 } else {
3037 if (mmap_size < buffer_size) {
3038 step = "mmap";
3039 goto exit;
3040 }
3041 // FIXME: indicate exclusive mode support by returning a negative buffer size
3042 info->buffer_size_frames *= -1;
3043 }
3044 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003045
3046 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3047 if (ret < 0) {
3048 step = "commit";
3049 goto exit;
3050 }
Phil Burkbc991042017-02-24 08:06:44 -08003051
3052 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003053 ret = 0;
3054
3055 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3056 __func__, info->shared_memory_address, info->buffer_size_frames);
3057
3058exit:
3059 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003060 if (out->pcm == NULL) {
3061 ALOGE("%s: %s - %d", __func__, step, ret);
3062 } else {
3063 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003064 pcm_close(out->pcm);
3065 out->pcm = NULL;
3066 }
3067 }
3068 pthread_mutex_unlock(&adev->lock);
3069 return ret;
3070}
3071
3072static int out_get_mmap_position(const struct audio_stream_out *stream,
3073 struct audio_mmap_position *position)
3074{
3075 struct stream_out *out = (struct stream_out *)stream;
3076 ALOGVV("%s", __func__);
3077 if (position == NULL) {
3078 return -EINVAL;
3079 }
3080 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
3081 return -ENOSYS;
3082 }
3083 if (out->pcm == NULL) {
3084 return -ENOSYS;
3085 }
3086
3087 struct timespec ts = { 0, 0 };
3088 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
3089 if (ret < 0) {
3090 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
3091 return ret;
3092 }
Andy Hungfc044e12017-03-20 09:24:22 -07003093 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003094 return 0;
3095}
3096
3097
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003098/** audio_stream_in implementation **/
3099static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3100{
3101 struct stream_in *in = (struct stream_in *)stream;
3102
3103 return in->config.rate;
3104}
3105
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003106static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003107{
3108 return -ENOSYS;
3109}
3110
3111static size_t in_get_buffer_size(const struct audio_stream *stream)
3112{
3113 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003114 return in->config.period_size * in->af_period_multiplier *
3115 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003116}
3117
3118static uint32_t in_get_channels(const struct audio_stream *stream)
3119{
3120 struct stream_in *in = (struct stream_in *)stream;
3121
3122 return in->channel_mask;
3123}
3124
vivek mehta4ed66e62016-04-15 23:33:34 -07003125static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003126{
vivek mehta4ed66e62016-04-15 23:33:34 -07003127 struct stream_in *in = (struct stream_in *)stream;
3128 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003129}
3130
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003131static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003132{
3133 return -ENOSYS;
3134}
3135
3136static int in_standby(struct audio_stream *stream)
3137{
3138 struct stream_in *in = (struct stream_in *)stream;
3139 struct audio_device *adev = in->dev;
3140 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003141 bool do_stop = true;
3142
Eric Laurent994a6932013-07-17 11:51:42 -07003143 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003144
3145 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003146
3147 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003148 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003149 audio_extn_sound_trigger_stop_lab(in);
3150 in->standby = true;
3151 }
3152
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003153 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003154 if (adev->adm_deregister_stream)
3155 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3156
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003157 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003158 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003159 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003160 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003161 in->capture_started = false;
3162 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003163 if (in->pcm) {
3164 pcm_close(in->pcm);
3165 in->pcm = NULL;
3166 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003167 adev->enable_voicerx = false;
3168 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003169 if (do_stop) {
3170 status = stop_input_stream(in);
3171 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003172 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003173 }
3174 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003175 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003176 return status;
3177}
3178
Andy Hungd13f0d32017-06-12 13:58:37 -07003179static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003180{
Andy Hungd13f0d32017-06-12 13:58:37 -07003181 struct stream_in *in = (struct stream_in *)stream;
3182
3183 // We try to get the lock for consistency,
3184 // but it isn't necessary for these variables.
3185 // If we're not in standby, we may be blocked on a read.
3186 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3187 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3188 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3189 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3190
3191 if (locked) {
3192 pthread_mutex_unlock(&in->lock);
3193 }
3194
3195 // dump error info
3196 (void)error_log_dump(
3197 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003198 return 0;
3199}
3200
3201static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3202{
3203 struct stream_in *in = (struct stream_in *)stream;
3204 struct audio_device *adev = in->dev;
3205 struct str_parms *parms;
3206 char *str;
3207 char value[32];
3208 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003209 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003210
Eric Laurent994a6932013-07-17 11:51:42 -07003211 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003212 parms = str_parms_create_str(kvpairs);
3213
3214 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3215
Eric Laurenta1478072015-09-21 17:21:52 -07003216 lock_input_stream(in);
3217
Eric Laurent150dbfe2013-02-27 14:31:02 -08003218 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003219 if (ret >= 0) {
3220 val = atoi(value);
3221 /* no audio source uses val == 0 */
3222 if ((in->source != val) && (val != 0)) {
3223 in->source = val;
3224 }
3225 }
3226
3227 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003228
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003229 if (ret >= 0) {
3230 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003231 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003232
3233 // Workaround: If routing to an non existing usb device, fail gracefully
3234 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003235 int card;
3236 if (audio_is_usb_in_device(val) &&
3237 (card = get_alive_usb_card(parms)) >= 0) {
3238
3239 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003240 status = -ENOSYS;
3241 } else {
3242
3243 in->device = val;
3244 /* If recording is in progress, change the tx device to new device */
3245 if (!in->standby) {
3246 ALOGV("update input routing change");
3247 // inform adm before actual routing to prevent glitches.
3248 if (adev->adm_on_routing_change) {
3249 adev->adm_on_routing_change(adev->adm_data,
3250 in->capture_handle);
3251 }
3252 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003253 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003254 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003255 }
3256 }
3257
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003258 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003259 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003260
3261 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003262 ALOGV("%s: exit: status(%d)", __func__, status);
3263 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003264}
3265
Haynes Mathew George569b7482017-05-08 14:44:27 -07003266static char* in_get_parameters(const struct audio_stream *stream,
3267 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003268{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003269 struct stream_in *in = (struct stream_in *)stream;
3270 struct str_parms *query = str_parms_create_str(keys);
3271 char *str;
3272 struct str_parms *reply = str_parms_create();
3273 bool replied = false;
3274
3275 ALOGV("%s: enter: keys - %s", __func__, keys);
3276 replied |= stream_get_parameter_channels(query, reply,
3277 &in->supported_channel_masks[0]);
3278 replied |= stream_get_parameter_formats(query, reply,
3279 &in->supported_formats[0]);
3280 replied |= stream_get_parameter_rates(query, reply,
3281 &in->supported_sample_rates[0]);
3282 if (replied) {
3283 str = str_parms_to_str(reply);
3284 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003285 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003286 }
3287 str_parms_destroy(query);
3288 str_parms_destroy(reply);
3289 ALOGV("%s: exit: returns - %s", __func__, str);
3290 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003291}
3292
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003293static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003294{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003295 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003296}
3297
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003298static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3299{
3300 if (!stream || !parms)
3301 return;
3302
3303 struct stream_in *in = (struct stream_in *)stream;
3304 struct audio_device *adev = in->dev;
3305
3306 card_status_t status;
3307 int card;
3308 if (parse_snd_card_status(parms, &card, &status) < 0)
3309 return;
3310
3311 pthread_mutex_lock(&adev->lock);
3312 bool valid_cb = (card == adev->snd_card);
3313 pthread_mutex_unlock(&adev->lock);
3314
3315 if (!valid_cb)
3316 return;
3317
3318 lock_input_stream(in);
3319 if (in->card_status != status)
3320 in->card_status = status;
3321 pthread_mutex_unlock(&in->lock);
3322
3323 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3324 use_case_table[in->usecase],
3325 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3326
3327 // a better solution would be to report error back to AF and let
3328 // it put the stream to standby
3329 if (status == CARD_STATUS_OFFLINE)
3330 in_standby(&in->stream.common);
3331
3332 return;
3333}
3334
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003335static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3336 size_t bytes)
3337{
3338 struct stream_in *in = (struct stream_in *)stream;
3339 struct audio_device *adev = in->dev;
3340 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003341 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003342 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003343
Eric Laurenta1478072015-09-21 17:21:52 -07003344 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003345 const size_t frame_size = audio_stream_in_frame_size(stream);
3346 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003347
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003348 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003349 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003350 /* Read from sound trigger HAL */
3351 audio_extn_sound_trigger_read(in, buffer, bytes);
3352 pthread_mutex_unlock(&in->lock);
3353 return bytes;
3354 }
3355
Eric Laurent0e46adf2016-12-16 12:49:24 -08003356 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3357 ret = -ENOSYS;
3358 goto exit;
3359 }
3360
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003361 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003362 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003363 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003364 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003365 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003366 goto exit;
3367 }
3368 in->standby = 0;
3369 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003370
Andy Hungd13f0d32017-06-12 13:58:37 -07003371 // errors that occur here are read errors.
3372 error_code = ERROR_CODE_READ;
3373
Haynes Mathew George03c40102016-01-29 17:57:48 -08003374 //what's the duration requested by the client?
3375 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3376 in->config.rate;
3377 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003378
Haynes Mathew George03c40102016-01-29 17:57:48 -08003379 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003380 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003381 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003382 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003383 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003384 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003385 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003386 if (ret < 0) {
3387 ALOGE("Failed to read w/err %s", strerror(errno));
3388 ret = -errno;
3389 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003390 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3391 if (bytes % 4 == 0) {
3392 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3393 int_buf_stream = buffer;
3394 for (size_t itt=0; itt < bytes/4 ; itt++) {
3395 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003396 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003397 } else {
3398 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3399 ret = -EINVAL;
3400 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003401 }
3402 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003403 }
3404
Haynes Mathew George03c40102016-01-29 17:57:48 -08003405 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003406
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003407 /*
3408 * Instead of writing zeroes here, we could trust the hardware
3409 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003410 * 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 -08003411 */
Andy Hungd13f0d32017-06-12 13:58:37 -07003412 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003413 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07003414 in->frames_muted += frames;
3415 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003416
3417exit:
3418 pthread_mutex_unlock(&in->lock);
3419
3420 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07003421 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003422 in_standby(&in->stream.common);
3423 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003424 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003425 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07003426 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08003427 }
3428 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003429 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003430 }
3431 return bytes;
3432}
3433
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003434static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003435{
3436 return 0;
3437}
3438
Andy Hung6ebe5962016-01-15 17:46:57 -08003439static int in_get_capture_position(const struct audio_stream_in *stream,
3440 int64_t *frames, int64_t *time)
3441{
3442 if (stream == NULL || frames == NULL || time == NULL) {
3443 return -EINVAL;
3444 }
3445 struct stream_in *in = (struct stream_in *)stream;
3446 int ret = -ENOSYS;
3447
3448 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003449 // note: ST sessions do not close the alsa pcm driver synchronously
3450 // on standby. Therefore, we may return an error even though the
3451 // pcm stream is still opened.
3452 if (in->standby) {
3453 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
3454 "%s stream in standby but pcm not NULL for non ST session", __func__);
3455 goto exit;
3456 }
Andy Hung6ebe5962016-01-15 17:46:57 -08003457 if (in->pcm) {
3458 struct timespec timestamp;
3459 unsigned int avail;
3460 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3461 *frames = in->frames_read + avail;
3462 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3463 ret = 0;
3464 }
3465 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003466exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08003467 pthread_mutex_unlock(&in->lock);
3468 return ret;
3469}
3470
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003471static int add_remove_audio_effect(const struct audio_stream *stream,
3472 effect_handle_t effect,
3473 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003474{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003475 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003476 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003477 int status = 0;
3478 effect_descriptor_t desc;
3479
3480 status = (*effect)->get_descriptor(effect, &desc);
3481 if (status != 0)
3482 return status;
3483
Eric Laurenta1478072015-09-21 17:21:52 -07003484 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003485 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003486 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003487 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003488 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003489 in->enable_aec != enable &&
3490 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3491 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003492 if (!enable)
3493 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003494 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3495 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3496 adev->enable_voicerx = enable;
3497 struct audio_usecase *usecase;
3498 struct listnode *node;
3499 list_for_each(node, &adev->usecase_list) {
3500 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07003501 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07003502 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05003503 }
3504 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003505 if (!in->standby)
3506 select_devices(in->dev, in->usecase);
3507 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003508 if (in->enable_ns != enable &&
3509 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3510 in->enable_ns = enable;
3511 if (!in->standby)
3512 select_devices(in->dev, in->usecase);
3513 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003514 pthread_mutex_unlock(&in->dev->lock);
3515 pthread_mutex_unlock(&in->lock);
3516
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003517 return 0;
3518}
3519
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003520static int in_add_audio_effect(const struct audio_stream *stream,
3521 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003522{
Eric Laurent994a6932013-07-17 11:51:42 -07003523 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003524 return add_remove_audio_effect(stream, effect, true);
3525}
3526
3527static int in_remove_audio_effect(const struct audio_stream *stream,
3528 effect_handle_t effect)
3529{
Eric Laurent994a6932013-07-17 11:51:42 -07003530 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003531 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003532}
3533
Eric Laurent0e46adf2016-12-16 12:49:24 -08003534static int in_stop(const struct audio_stream_in* stream)
3535{
3536 struct stream_in *in = (struct stream_in *)stream;
3537 struct audio_device *adev = in->dev;
3538
3539 int ret = -ENOSYS;
3540 ALOGV("%s", __func__);
3541 pthread_mutex_lock(&adev->lock);
3542 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3543 in->capture_started && in->pcm != NULL) {
3544 pcm_stop(in->pcm);
3545 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003546 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003547 }
3548 pthread_mutex_unlock(&adev->lock);
3549 return ret;
3550}
3551
3552static int in_start(const struct audio_stream_in* stream)
3553{
3554 struct stream_in *in = (struct stream_in *)stream;
3555 struct audio_device *adev = in->dev;
3556 int ret = -ENOSYS;
3557
3558 ALOGV("%s in %p", __func__, in);
3559 pthread_mutex_lock(&adev->lock);
3560 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3561 !in->capture_started && in->pcm != NULL) {
3562 if (!in->capture_started) {
3563 ret = start_input_stream(in);
3564 if (ret == 0) {
3565 in->capture_started = true;
3566 }
3567 }
3568 }
3569 pthread_mutex_unlock(&adev->lock);
3570 return ret;
3571}
3572
3573static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3574 int32_t min_size_frames,
3575 struct audio_mmap_buffer_info *info)
3576{
3577 struct stream_in *in = (struct stream_in *)stream;
3578 struct audio_device *adev = in->dev;
3579 int ret = 0;
3580 unsigned int offset1;
3581 unsigned int frames1;
3582 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003583 uint32_t mmap_size;
3584 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003585
3586 pthread_mutex_lock(&adev->lock);
3587 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003588
Eric Laurent0e46adf2016-12-16 12:49:24 -08003589 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003590 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003591 ret = -EINVAL;
3592 goto exit;
3593 }
3594 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003595 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003596 ALOGV("%s in %p", __func__, in);
3597 ret = -ENOSYS;
3598 goto exit;
3599 }
3600 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3601 if (in->pcm_device_id < 0) {
3602 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3603 __func__, in->pcm_device_id, in->usecase);
3604 ret = -EINVAL;
3605 goto exit;
3606 }
Phil Burkbc991042017-02-24 08:06:44 -08003607
3608 adjust_mmap_period_count(&in->config, min_size_frames);
3609
Eric Laurent0e46adf2016-12-16 12:49:24 -08003610 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3611 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3612 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3613 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3614 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3615 step = "open";
3616 ret = -ENODEV;
3617 goto exit;
3618 }
3619
3620 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3621 if (ret < 0) {
3622 step = "begin";
3623 goto exit;
3624 }
3625 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003626 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003627 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003628 ret = platform_get_mmap_data_fd(adev->platform,
3629 in->pcm_device_id, 1 /*capture*/,
3630 &info->shared_memory_fd,
3631 &mmap_size);
3632 if (ret < 0) {
3633 // Fall back to non exclusive mode
3634 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3635 } else {
3636 if (mmap_size < buffer_size) {
3637 step = "mmap";
3638 goto exit;
3639 }
3640 // FIXME: indicate exclusive mode support by returning a negative buffer size
3641 info->buffer_size_frames *= -1;
3642 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08003643
Haynes Mathew George96483a22017-03-28 14:52:47 -07003644 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003645
3646 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3647 if (ret < 0) {
3648 step = "commit";
3649 goto exit;
3650 }
3651
Phil Burkbc991042017-02-24 08:06:44 -08003652 in->standby = false;
3653 ret = 0;
3654
Eric Laurent0e46adf2016-12-16 12:49:24 -08003655 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3656 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003657
3658exit:
3659 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003660 if (in->pcm == NULL) {
3661 ALOGE("%s: %s - %d", __func__, step, ret);
3662 } else {
3663 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003664 pcm_close(in->pcm);
3665 in->pcm = NULL;
3666 }
3667 }
3668 pthread_mutex_unlock(&adev->lock);
3669 return ret;
3670}
3671
3672static int in_get_mmap_position(const struct audio_stream_in *stream,
3673 struct audio_mmap_position *position)
3674{
3675 struct stream_in *in = (struct stream_in *)stream;
3676 ALOGVV("%s", __func__);
3677 if (position == NULL) {
3678 return -EINVAL;
3679 }
3680 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
3681 return -ENOSYS;
3682 }
3683 if (in->pcm == NULL) {
3684 return -ENOSYS;
3685 }
3686 struct timespec ts = { 0, 0 };
3687 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
3688 if (ret < 0) {
3689 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3690 return ret;
3691 }
Andy Hungfc044e12017-03-20 09:24:22 -07003692 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003693 return 0;
3694}
3695
3696
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003697static int adev_open_output_stream(struct audio_hw_device *dev,
3698 audio_io_handle_t handle,
3699 audio_devices_t devices,
3700 audio_output_flags_t flags,
3701 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003702 struct audio_stream_out **stream_out,
3703 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003704{
3705 struct audio_device *adev = (struct audio_device *)dev;
3706 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003707 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003708 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
3709 bool is_usb_dev = audio_is_usb_out_device(devices) &&
3710 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003711
Andy Hungd9653bd2017-08-01 19:31:39 -07003712 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
3713 return -ENOSYS;
3714 }
3715
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003716 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
3717 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003718 *stream_out = NULL;
3719 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3720
3721 if (devices == AUDIO_DEVICE_NONE)
3722 devices = AUDIO_DEVICE_OUT_SPEAKER;
3723
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003724 out->flags = flags;
3725 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003726 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003727 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003728 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003729
3730 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003731 if ((is_hdmi || is_usb_dev) &&
3732 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
3733 (flags == AUDIO_OUTPUT_FLAG_NONE ||
3734 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003735 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003736 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003737 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003738 if (config->sample_rate == 0)
3739 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3740 if (config->channel_mask == 0)
3741 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3742 if (config->format == AUDIO_FORMAT_DEFAULT)
3743 config->format = AUDIO_FORMAT_PCM_16_BIT;
3744 } else if (is_usb_dev) {
3745 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
3746 &config->format,
3747 &out->supported_formats[0],
3748 MAX_SUPPORTED_FORMATS,
3749 &config->channel_mask,
3750 &out->supported_channel_masks[0],
3751 MAX_SUPPORTED_CHANNEL_MASKS,
3752 &config->sample_rate,
3753 &out->supported_sample_rates[0],
3754 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003755 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003756 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003757 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003758 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003759 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003760
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003761
Haynes Mathew George569b7482017-05-08 14:44:27 -07003762 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003763 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003764 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003765 if (is_hdmi) {
3766 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3767 out->config = pcm_config_hdmi_multi;
3768 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3769 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3770 out->config = pcm_config_mmap_playback;
3771 out->stream.start = out_start;
3772 out->stream.stop = out_stop;
3773 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3774 out->stream.get_mmap_position = out_get_mmap_position;
3775 } else {
3776 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3777 out->config = pcm_config_hifi;
3778 }
3779
3780 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003781 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003782 if (is_hdmi) {
3783 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
3784 audio_bytes_per_sample(out->format));
3785 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003786 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003787 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003788 pthread_mutex_lock(&adev->lock);
3789 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3790 pthread_mutex_unlock(&adev->lock);
3791
3792 // reject offload during card offline to allow
3793 // fallback to s/w paths
3794 if (offline) {
3795 ret = -ENODEV;
3796 goto error_open;
3797 }
3798
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003799 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3800 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3801 ALOGE("%s: Unsupported Offload information", __func__);
3802 ret = -EINVAL;
3803 goto error_open;
3804 }
3805 if (!is_supported_format(config->offload_info.format)) {
3806 ALOGE("%s: Unsupported audio format", __func__);
3807 ret = -EINVAL;
3808 goto error_open;
3809 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003810 out->sample_rate = config->offload_info.sample_rate;
3811 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
3812 out->channel_mask = config->offload_info.channel_mask;
3813 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
3814 out->channel_mask = config->channel_mask;
3815 else
3816 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3817
3818 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003819
3820 out->compr_config.codec = (struct snd_codec *)
3821 calloc(1, sizeof(struct snd_codec));
3822
3823 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003824
3825 out->stream.set_callback = out_set_callback;
3826 out->stream.pause = out_pause;
3827 out->stream.resume = out_resume;
3828 out->stream.drain = out_drain;
3829 out->stream.flush = out_flush;
3830
3831 out->compr_config.codec->id =
3832 get_snd_codec_id(config->offload_info.format);
3833 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3834 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003835 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003836 out->compr_config.codec->bit_rate =
3837 config->offload_info.bit_rate;
3838 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003839 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003840 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3841
3842 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3843 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003844
3845 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003846 create_offload_callback_thread(out);
3847 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3848 __func__, config->offload_info.version,
3849 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003850 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07003851 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003852 case 0:
3853 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
3854 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07003855 case 8000:
3856 case 16000:
3857 case 48000:
3858 out->sample_rate = config->sample_rate;
3859 break;
3860 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003861 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
3862 config->sample_rate);
3863 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3864 ret = -EINVAL;
3865 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003866 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003867 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
3868 switch (config->channel_mask) {
3869 case AUDIO_CHANNEL_NONE:
3870 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3871 break;
3872 case AUDIO_CHANNEL_OUT_STEREO:
3873 out->channel_mask = config->channel_mask;
3874 break;
3875 default:
3876 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
3877 config->channel_mask);
3878 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3879 ret = -EINVAL;
3880 break;
3881 }
3882 switch (config->format) {
3883 case AUDIO_FORMAT_DEFAULT:
3884 out->format = AUDIO_FORMAT_PCM_16_BIT;
3885 break;
3886 case AUDIO_FORMAT_PCM_16_BIT:
3887 out->format = config->format;
3888 break;
3889 default:
3890 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
3891 config->format);
3892 config->format = AUDIO_FORMAT_PCM_16_BIT;
3893 ret = -EINVAL;
3894 break;
3895 }
3896 if (ret != 0)
3897 goto error_open;
3898
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003899 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3900 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003901 out->config.rate = out->sample_rate;
3902 out->config.channels =
3903 audio_channel_count_from_out_mask(out->channel_mask);
3904 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003905 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003906 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
3907 switch (config->sample_rate) {
3908 case 0:
3909 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3910 break;
3911 case 8000:
3912 case 16000:
3913 case 32000:
3914 case 48000:
3915 out->sample_rate = config->sample_rate;
3916 break;
3917 default:
3918 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
3919 config->sample_rate);
3920 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3921 ret = -EINVAL;
3922 break;
3923 }
Eric Laurentad2dde92017-09-20 18:27:31 -07003924 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003925 switch (config->channel_mask) {
3926 case AUDIO_CHANNEL_NONE:
3927 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3928 break;
3929 case AUDIO_CHANNEL_OUT_STEREO:
3930 out->channel_mask = config->channel_mask;
3931 break;
3932 default:
3933 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
3934 config->channel_mask);
3935 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3936 ret = -EINVAL;
3937 break;
3938 }
3939 switch (config->format) {
3940 case AUDIO_FORMAT_DEFAULT:
3941 out->format = AUDIO_FORMAT_PCM_16_BIT;
3942 break;
3943 case AUDIO_FORMAT_PCM_16_BIT:
3944 out->format = config->format;
3945 break;
3946 default:
3947 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
3948 config->format);
3949 config->format = AUDIO_FORMAT_PCM_16_BIT;
3950 ret = -EINVAL;
3951 break;
3952 }
3953 if (ret != 0)
3954 goto error_open;
3955
vivek mehtaa68fea62017-06-08 19:04:02 -07003956 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07003957 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
3958 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003959 out->config.rate = out->sample_rate;
3960 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07003961 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003962 out->sample_rate,
3963 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07003964 out->config.channels,
3965 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003966 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07003967 out->config.period_size = buffer_size / frame_size;
3968 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
3969 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003970 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003971 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003972 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3973 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003974 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003975 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3976 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003977 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003978 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003979 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003980 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003981 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003982 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3983 out->config = pcm_config_mmap_playback;
3984 out->stream.start = out_start;
3985 out->stream.stop = out_stop;
3986 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3987 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003988 } else {
3989 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3990 out->config = pcm_config_low_latency;
3991 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003992
3993 if (config->sample_rate == 0) {
3994 out->sample_rate = out->config.rate;
3995 } else {
3996 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003997 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003998 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
3999 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
4000 } else {
4001 out->channel_mask = config->channel_mask;
4002 }
4003 if (config->format == AUDIO_FORMAT_DEFAULT)
4004 out->format = audio_format_from_pcm_format(out->config.format);
4005 else if (!audio_is_linear_pcm(config->format)) {
4006 config->format = AUDIO_FORMAT_PCM_16_BIT;
4007 ret = -EINVAL;
4008 goto error_open;
4009 } else {
4010 out->format = config->format;
4011 }
4012
4013 out->config.rate = out->sample_rate;
4014 out->config.channels =
4015 audio_channel_count_from_out_mask(out->channel_mask);
4016 if (out->format != audio_format_from_pcm_format(out->config.format)) {
4017 out->config.format = pcm_format_from_audio_format(out->format);
4018 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004019 }
Kevin Rocard50eff892017-05-02 16:52:05 -07004020
4021 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
4022 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004023 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004024 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
4025 __func__, config->sample_rate, config->format, config->channel_mask);
4026 config->sample_rate = out->sample_rate;
4027 config->format = out->format;
4028 config->channel_mask = out->channel_mask;
4029 ret = -EINVAL;
4030 goto error_open;
4031 }
4032
Andy Hung6fcba9c2014-03-18 11:53:32 -07004033 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
4034 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004035
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004036 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004037 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004038 adev->primary_output = out;
4039 else {
4040 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004041 ret = -EEXIST;
4042 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004043 }
4044 }
4045
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004046 /* Check if this usecase is already existing */
4047 pthread_mutex_lock(&adev->lock);
4048 if (get_usecase_from_list(adev, out->usecase) != NULL) {
4049 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004050 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004051 ret = -EEXIST;
4052 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004053 }
4054 pthread_mutex_unlock(&adev->lock);
4055
4056 out->stream.common.get_sample_rate = out_get_sample_rate;
4057 out->stream.common.set_sample_rate = out_set_sample_rate;
4058 out->stream.common.get_buffer_size = out_get_buffer_size;
4059 out->stream.common.get_channels = out_get_channels;
4060 out->stream.common.get_format = out_get_format;
4061 out->stream.common.set_format = out_set_format;
4062 out->stream.common.standby = out_standby;
4063 out->stream.common.dump = out_dump;
4064 out->stream.common.set_parameters = out_set_parameters;
4065 out->stream.common.get_parameters = out_get_parameters;
4066 out->stream.common.add_audio_effect = out_add_audio_effect;
4067 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4068 out->stream.get_latency = out_get_latency;
4069 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004070#ifdef NO_AUDIO_OUT
4071 out->stream.write = out_write_for_no_output;
4072#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004073 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004074#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004075 out->stream.get_render_position = out_get_render_position;
4076 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004077 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004078
Eric Laurent0e46adf2016-12-16 12:49:24 -08004079 if (out->realtime)
4080 out->af_period_multiplier = af_period_multiplier;
4081 else
4082 out->af_period_multiplier = 1;
4083
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004084 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004085 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004086 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004087
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004088 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004089 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004090 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4091
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004092 config->format = out->stream.common.get_format(&out->stream.common);
4093 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4094 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4095
Andy Hunga452b0a2017-03-15 14:51:15 -07004096 out->error_log = error_log_create(
4097 ERROR_LOG_ENTRIES,
4098 1000000000 /* aggregate consecutive identical errors within one second in ns */);
4099
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004100 /*
4101 By locking output stream before registering, we allow the callback
4102 to update stream's state only after stream's initial state is set to
4103 adev state.
4104 */
4105 lock_output_stream(out);
4106 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4107 pthread_mutex_lock(&adev->lock);
4108 out->card_status = adev->card_status;
4109 pthread_mutex_unlock(&adev->lock);
4110 pthread_mutex_unlock(&out->lock);
4111
vivek mehta4a824772017-06-08 19:05:49 -07004112 stream_app_type_cfg_init(&out->app_type_cfg);
4113
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004114 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004115
Eric Laurent994a6932013-07-17 11:51:42 -07004116 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004117 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004118
4119error_open:
4120 free(out);
4121 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07004122 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004123 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004124}
4125
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004126static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004127 struct audio_stream_out *stream)
4128{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004129 struct stream_out *out = (struct stream_out *)stream;
4130 struct audio_device *adev = out->dev;
4131
Eric Laurent994a6932013-07-17 11:51:42 -07004132 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004133
4134 // must deregister from sndmonitor first to prevent races
4135 // between the callback and close_stream
4136 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004137 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004138 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
4139 destroy_offload_callback_thread(out);
4140
4141 if (out->compr_config.codec != NULL)
4142 free(out->compr_config.codec);
4143 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004144
4145 if (adev->voice_tx_output == out)
4146 adev->voice_tx_output = NULL;
4147
Andy Hunga452b0a2017-03-15 14:51:15 -07004148 error_log_destroy(out->error_log);
4149 out->error_log = NULL;
4150
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004151 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004152 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004153 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004154 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004155 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004156}
4157
4158static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4159{
4160 struct audio_device *adev = (struct audio_device *)dev;
4161 struct str_parms *parms;
4162 char *str;
4163 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004164 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004165 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07004166 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004167
Joe Onorato188b6222016-03-01 11:02:27 -08004168 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004169
4170 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004171
4172 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004173 status = voice_set_parameters(adev, parms);
4174 if (status != 0) {
4175 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004176 }
4177
4178 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4179 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07004180 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004181 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4182 adev->bluetooth_nrec = true;
4183 else
4184 adev->bluetooth_nrec = false;
4185 }
4186
4187 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4188 if (ret >= 0) {
4189 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4190 adev->screen_off = false;
4191 else
4192 adev->screen_off = true;
4193 }
4194
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004195 ret = str_parms_get_int(parms, "rotation", &val);
4196 if (ret >= 0) {
4197 bool reverse_speakers = false;
4198 switch(val) {
4199 // FIXME: note that the code below assumes that the speakers are in the correct placement
4200 // relative to the user when the device is rotated 90deg from its default rotation. This
4201 // assumption is device-specific, not platform-specific like this code.
4202 case 270:
4203 reverse_speakers = true;
4204 break;
4205 case 0:
4206 case 90:
4207 case 180:
4208 break;
4209 default:
4210 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07004211 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004212 }
Eric Laurent03f09432014-03-25 18:09:11 -07004213 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004214 // check and set swap
4215 // - check if orientation changed and speaker active
4216 // - set rotation and cache the rotation value
4217 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004218 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004219 }
4220
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004221 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4222 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004223 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004224 }
4225
David Linee3fe402017-03-13 10:00:42 -07004226 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4227 if (ret >= 0) {
4228 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004229 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004230 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4231 if (ret >= 0) {
4232 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004233 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004234 }
Eric Laurent99dab492017-06-17 15:19:08 -07004235 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004236 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4237 if (ret >= 0) {
4238 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004239 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004240 }
4241 }
4242 }
4243
4244 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4245 if (ret >= 0) {
4246 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004247 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004248 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4249 if (ret >= 0) {
4250 const int card = atoi(value);
4251
Eric Laurent99dab492017-06-17 15:19:08 -07004252 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004253 }
Eric Laurent99dab492017-06-17 15:19:08 -07004254 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004255 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4256 if (ret >= 0) {
4257 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004258 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004259 }
4260 }
4261 }
4262
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004263 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004264done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004265 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004266 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004267 ALOGV("%s: exit with code(%d)", __func__, status);
4268 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004269}
4270
4271static char* adev_get_parameters(const struct audio_hw_device *dev,
4272 const char *keys)
4273{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004274 struct audio_device *adev = (struct audio_device *)dev;
4275 struct str_parms *reply = str_parms_create();
4276 struct str_parms *query = str_parms_create_str(keys);
4277 char *str;
4278
4279 pthread_mutex_lock(&adev->lock);
4280
4281 voice_get_parameters(adev, query, reply);
4282 str = str_parms_to_str(reply);
4283 str_parms_destroy(query);
4284 str_parms_destroy(reply);
4285
4286 pthread_mutex_unlock(&adev->lock);
4287 ALOGV("%s: exit: returns - %s", __func__, str);
4288 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004289}
4290
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004291static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004292{
4293 return 0;
4294}
4295
Haynes Mathew George5191a852013-09-11 14:19:36 -07004296static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4297{
4298 int ret;
4299 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004300
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004301 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4302
Haynes Mathew George5191a852013-09-11 14:19:36 -07004303 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004304 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004305 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004306
Haynes Mathew George5191a852013-09-11 14:19:36 -07004307 return ret;
4308}
4309
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004310static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004311{
4312 return -ENOSYS;
4313}
4314
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004315static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4316 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004317{
4318 return -ENOSYS;
4319}
4320
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004321static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004322{
4323 return -ENOSYS;
4324}
4325
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004326static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004327{
4328 return -ENOSYS;
4329}
4330
4331static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4332{
4333 struct audio_device *adev = (struct audio_device *)dev;
4334
4335 pthread_mutex_lock(&adev->lock);
4336 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004337 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004338 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004339 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4340 voice_is_in_call(adev)) {
4341 voice_stop_call(adev);
4342 adev->current_call_output = NULL;
4343 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004344 }
4345 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004346
4347 audio_extn_extspk_set_mode(adev->extspk, mode);
4348
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004349 return 0;
4350}
4351
4352static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4353{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004354 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004355 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004356
Eric Laurent2bafff12016-03-17 12:17:23 -07004357 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004358 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004359 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4360 ret = audio_extn_hfp_set_mic_mute(adev, state);
4361 } else {
4362 ret = voice_set_mic_mute(adev, state);
4363 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004364 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004365 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004366
4367 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004368}
4369
4370static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4371{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004372 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004373 return 0;
4374}
4375
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004376static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004377 const struct audio_config *config)
4378{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004379 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004380
Eric Laurent74b55762017-07-09 17:04:53 -07004381 /* Don't know if USB HIFI in this context so use true to be conservative */
4382 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4383 true /*is_usb_hifi */) != 0)
4384 return 0;
4385
vivek mehtaa68fea62017-06-08 19:04:02 -07004386 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4387 config->sample_rate, config->format,
4388 channel_count,
4389 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004390}
4391
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004392static bool adev_input_allow_hifi_record(struct audio_device *adev,
4393 audio_devices_t devices,
4394 audio_input_flags_t flags,
4395 audio_source_t source) {
4396 const bool allowed = true;
4397
4398 if (!audio_is_usb_in_device(devices))
4399 return !allowed;
4400
4401 switch (flags) {
4402 case AUDIO_INPUT_FLAG_NONE:
4403 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4404 break;
4405 default:
4406 return !allowed;
4407 }
4408
4409 switch (source) {
4410 case AUDIO_SOURCE_DEFAULT:
4411 case AUDIO_SOURCE_MIC:
4412 case AUDIO_SOURCE_UNPROCESSED:
4413 break;
4414 default:
4415 return !allowed;
4416 }
4417
4418 switch (adev->mode) {
4419 case 0:
4420 break;
4421 default:
4422 return !allowed;
4423 }
4424
4425 return allowed;
4426}
4427
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004428static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004429 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004430 audio_devices_t devices,
4431 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004432 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004433 audio_input_flags_t flags,
4434 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004435 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004436{
4437 struct audio_device *adev = (struct audio_device *)dev;
4438 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004439 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004440 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004441 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004442 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004443 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4444 devices,
4445 flags,
4446 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004447 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004448 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004449
Andy Hungd9653bd2017-08-01 19:31:39 -07004450 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
4451 return -ENOSYS;
4452 }
4453
Eric Laurent74b55762017-07-09 17:04:53 -07004454 if (!(is_usb_dev && may_use_hifi_record)) {
4455 if (config->sample_rate == 0)
4456 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4457 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4458 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4459 if (config->format == AUDIO_FORMAT_DEFAULT)
4460 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004461
Eric Laurent74b55762017-07-09 17:04:53 -07004462 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
4463
4464 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
4465 return -EINVAL;
4466 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004467
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004468 if (audio_extn_tfa_98xx_is_supported() &&
4469 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004470 return -EINVAL;
4471
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004472 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4473
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004474 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004475 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004476
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004477 in->stream.common.get_sample_rate = in_get_sample_rate;
4478 in->stream.common.set_sample_rate = in_set_sample_rate;
4479 in->stream.common.get_buffer_size = in_get_buffer_size;
4480 in->stream.common.get_channels = in_get_channels;
4481 in->stream.common.get_format = in_get_format;
4482 in->stream.common.set_format = in_set_format;
4483 in->stream.common.standby = in_standby;
4484 in->stream.common.dump = in_dump;
4485 in->stream.common.set_parameters = in_set_parameters;
4486 in->stream.common.get_parameters = in_get_parameters;
4487 in->stream.common.add_audio_effect = in_add_audio_effect;
4488 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4489 in->stream.set_gain = in_set_gain;
4490 in->stream.read = in_read;
4491 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08004492 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004493
4494 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004495 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004496 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004497 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004498 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004499 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004500
Haynes Mathew George569b7482017-05-08 14:44:27 -07004501 if (is_usb_dev && may_use_hifi_record) {
4502 /* HiFi record selects an appropriate format, channel, rate combo
4503 depending on sink capabilities*/
4504 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
4505 &config->format,
4506 &in->supported_formats[0],
4507 MAX_SUPPORTED_FORMATS,
4508 &config->channel_mask,
4509 &in->supported_channel_masks[0],
4510 MAX_SUPPORTED_CHANNEL_MASKS,
4511 &config->sample_rate,
4512 &in->supported_sample_rates[0],
4513 MAX_SUPPORTED_SAMPLE_RATES);
4514 if (ret != 0) {
4515 ret = -EINVAL;
4516 goto err_open;
4517 }
Eric Laurent74b55762017-07-09 17:04:53 -07004518 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004519 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07004520 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07004521 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
4522 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
4523 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4524 bool ret_error = false;
4525 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4526 from HAL is 8_24
4527 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4528 8_24 return error indicating supported format is 8_24
4529 *> In case of any other source requesting 24 bit or float return error
4530 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07004531
vivek mehta57ff9b52016-04-28 14:13:08 -07004532 on error flinger will retry with supported format passed
4533 */
4534 if (source != AUDIO_SOURCE_UNPROCESSED) {
4535 config->format = AUDIO_FORMAT_PCM_16_BIT;
4536 ret_error = true;
4537 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
4538 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
4539 ret_error = true;
4540 }
4541
4542 if (ret_error) {
4543 ret = -EINVAL;
4544 goto err_open;
4545 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004546 }
4547
vivek mehta57ff9b52016-04-28 14:13:08 -07004548 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07004549 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07004550
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004551 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004552 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
4553 if (config->sample_rate == 0)
4554 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4555 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4556 config->sample_rate != 8000) {
4557 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4558 ret = -EINVAL;
4559 goto err_open;
4560 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004561
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004562 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4563 config->format = AUDIO_FORMAT_PCM_16_BIT;
4564 ret = -EINVAL;
4565 goto err_open;
4566 }
4567
4568 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4569 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07004570 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004571 } else if (is_usb_dev && may_use_hifi_record) {
4572 in->usecase = USECASE_AUDIO_RECORD_HIFI;
4573 in->config = pcm_config_audio_capture;
4574 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004575 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4576 config->sample_rate,
4577 config->format,
4578 channel_count,
4579 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004580 in->config.period_size = buffer_size / frame_size;
4581 in->config.rate = config->sample_rate;
4582 in->af_period_multiplier = 1;
4583 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004584 } else {
4585 in->usecase = USECASE_AUDIO_RECORD;
4586 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08004587 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004588 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07004589#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004590 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07004591#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08004592 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004593 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08004594 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004595 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004596 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4597 config->sample_rate,
4598 config->format,
4599 channel_count,
4600 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004601 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004602 in->config.rate = config->sample_rate;
4603 in->af_period_multiplier = 1;
4604 } else {
4605 // period size is left untouched for rt mode playback
4606 in->config = pcm_config_audio_capture_rt;
4607 in->af_period_multiplier = af_period_multiplier;
4608 }
4609 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
4610 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004611 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08004612 in->usecase = USECASE_AUDIO_RECORD_MMAP;
4613 in->config = pcm_config_mmap_capture;
4614 in->stream.start = in_start;
4615 in->stream.stop = in_stop;
4616 in->stream.create_mmap_buffer = in_create_mmap_buffer;
4617 in->stream.get_mmap_position = in_get_mmap_position;
4618 in->af_period_multiplier = 1;
4619 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07004620 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07004621 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07004622 (config->sample_rate == 8000 ||
4623 config->sample_rate == 16000 ||
4624 config->sample_rate == 32000 ||
4625 config->sample_rate == 48000) &&
4626 channel_count == 1) {
4627 in->usecase = USECASE_AUDIO_RECORD_VOIP;
4628 in->config = pcm_config_audio_capture;
4629 frame_size = audio_stream_in_frame_size(&in->stream);
4630 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
4631 config->sample_rate,
4632 config->format,
4633 channel_count, false /*is_low_latency*/);
4634 in->config.period_size = buffer_size / frame_size;
4635 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
4636 in->config.rate = config->sample_rate;
4637 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004638 } else {
4639 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004640 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004641 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4642 config->sample_rate,
4643 config->format,
4644 channel_count,
4645 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004646 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004647 in->config.rate = config->sample_rate;
4648 in->af_period_multiplier = 1;
4649 }
4650 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
4651 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004652 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004653
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004654 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07004655 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004656
Andy Hungd13f0d32017-06-12 13:58:37 -07004657 in->error_log = error_log_create(
4658 ERROR_LOG_ENTRIES,
4659 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
4660
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004661 /* This stream could be for sound trigger lab,
4662 get sound trigger pcm if present */
4663 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004664
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004665 lock_input_stream(in);
4666 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
4667 pthread_mutex_lock(&adev->lock);
4668 in->card_status = adev->card_status;
4669 pthread_mutex_unlock(&adev->lock);
4670 pthread_mutex_unlock(&in->lock);
4671
vivek mehta4a824772017-06-08 19:05:49 -07004672 stream_app_type_cfg_init(&in->app_type_cfg);
4673
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004674 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004675 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004676 return 0;
4677
4678err_open:
4679 free(in);
4680 *stream_in = NULL;
4681 return ret;
4682}
4683
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004684static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004685 struct audio_stream_in *stream)
4686{
Andy Hungd13f0d32017-06-12 13:58:37 -07004687 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004688 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004689
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004690 // must deregister from sndmonitor first to prevent races
4691 // between the callback and close_stream
4692 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004693 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07004694
4695 error_log_destroy(in->error_log);
4696 in->error_log = NULL;
4697
Andy Hung0dbb52b2017-08-09 13:51:38 -07004698 pthread_mutex_destroy(&in->pre_lock);
4699 pthread_mutex_destroy(&in->lock);
4700
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004701 free(stream);
4702
4703 return;
4704}
4705
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004706static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004707{
4708 return 0;
4709}
4710
Andy Hung31aca912014-03-20 17:14:59 -07004711/* verifies input and output devices and their capabilities.
4712 *
4713 * This verification is required when enabling extended bit-depth or
4714 * sampling rates, as not all qcom products support it.
4715 *
4716 * Suitable for calling only on initialization such as adev_open().
4717 * It fills the audio_device use_case_table[] array.
4718 *
4719 * Has a side-effect that it needs to configure audio routing / devices
4720 * in order to power up the devices and read the device parameters.
4721 * It does not acquire any hw device lock. Should restore the devices
4722 * back to "normal state" upon completion.
4723 */
4724static int adev_verify_devices(struct audio_device *adev)
4725{
4726 /* enumeration is a bit difficult because one really wants to pull
4727 * the use_case, device id, etc from the hidden pcm_device_table[].
4728 * In this case there are the following use cases and device ids.
4729 *
4730 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
4731 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004732 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07004733 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
4734 * [USECASE_AUDIO_RECORD] = {0, 0},
4735 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
4736 * [USECASE_VOICE_CALL] = {2, 2},
4737 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004738 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07004739 * USECASE_VOICE_CALL omitted, but possible for either input or output.
4740 */
4741
4742 /* should be the usecases enabled in adev_open_input_stream() */
4743 static const int test_in_usecases[] = {
4744 USECASE_AUDIO_RECORD,
4745 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
4746 };
4747 /* should be the usecases enabled in adev_open_output_stream()*/
4748 static const int test_out_usecases[] = {
4749 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
4750 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
4751 };
4752 static const usecase_type_t usecase_type_by_dir[] = {
4753 PCM_PLAYBACK,
4754 PCM_CAPTURE,
4755 };
4756 static const unsigned flags_by_dir[] = {
4757 PCM_OUT,
4758 PCM_IN,
4759 };
4760
4761 size_t i;
4762 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004763 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07004764 char info[512]; /* for possible debug info */
4765
4766 for (dir = 0; dir < 2; ++dir) {
4767 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
4768 const unsigned flags_dir = flags_by_dir[dir];
4769 const size_t testsize =
4770 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
4771 const int *testcases =
4772 dir ? test_in_usecases : test_out_usecases;
4773 const audio_devices_t audio_device =
4774 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
4775
4776 for (i = 0; i < testsize; ++i) {
4777 const audio_usecase_t audio_usecase = testcases[i];
4778 int device_id;
4779 snd_device_t snd_device;
4780 struct pcm_params **pparams;
4781 struct stream_out out;
4782 struct stream_in in;
4783 struct audio_usecase uc_info;
4784 int retval;
4785
4786 pparams = &adev->use_case_table[audio_usecase];
4787 pcm_params_free(*pparams); /* can accept null input */
4788 *pparams = NULL;
4789
4790 /* find the device ID for the use case (signed, for error) */
4791 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
4792 if (device_id < 0)
4793 continue;
4794
4795 /* prepare structures for device probing */
4796 memset(&uc_info, 0, sizeof(uc_info));
4797 uc_info.id = audio_usecase;
4798 uc_info.type = usecase_type;
4799 if (dir) {
4800 adev->active_input = &in;
4801 memset(&in, 0, sizeof(in));
4802 in.device = audio_device;
4803 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4804 uc_info.stream.in = &in;
4805 } else {
4806 adev->active_input = NULL;
4807 }
4808 memset(&out, 0, sizeof(out));
4809 out.devices = audio_device; /* only field needed in select_devices */
4810 uc_info.stream.out = &out;
4811 uc_info.devices = audio_device;
4812 uc_info.in_snd_device = SND_DEVICE_NONE;
4813 uc_info.out_snd_device = SND_DEVICE_NONE;
4814 list_add_tail(&adev->usecase_list, &uc_info.list);
4815
4816 /* select device - similar to start_(in/out)put_stream() */
4817 retval = select_devices(adev, audio_usecase);
4818 if (retval >= 0) {
4819 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4820#if LOG_NDEBUG == 0
4821 if (*pparams) {
4822 ALOGV("%s: (%s) card %d device %d", __func__,
4823 dir ? "input" : "output", card_id, device_id);
4824 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004825 } else {
4826 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4827 }
4828#endif
4829 }
4830
4831 /* deselect device - similar to stop_(in/out)put_stream() */
4832 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004833 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004834 /* 2. Disable the rx device */
4835 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004836 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004837 list_remove(&uc_info.list);
4838 }
4839 }
4840 adev->active_input = NULL; /* restore adev state */
4841 return 0;
4842}
4843
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004844static int adev_close(hw_device_t *device)
4845{
Andy Hung31aca912014-03-20 17:14:59 -07004846 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004847 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004848
4849 if (!adev)
4850 return 0;
4851
4852 pthread_mutex_lock(&adev_init_lock);
4853
4854 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004855 audio_extn_snd_mon_unregister_listener(adev);
4856 audio_extn_tfa_98xx_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004857 audio_route_free(adev->audio_route);
4858 free(adev->snd_dev_ref_cnt);
4859 platform_deinit(adev->platform);
4860 audio_extn_extspk_deinit(adev->extspk);
4861 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004862 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004863 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4864 pcm_params_free(adev->use_case_table[i]);
4865 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004866 if (adev->adm_deinit)
4867 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004868 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004869 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004870 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004871
4872 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004873
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004874 return 0;
4875}
4876
Glenn Kasten4f993392014-05-14 07:30:48 -07004877/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4878 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4879 * just that it _might_ work.
4880 */
4881static int period_size_is_plausible_for_low_latency(int period_size)
4882{
4883 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004884 case 48:
4885 case 96:
4886 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004887 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004888 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004889 case 240:
4890 case 320:
4891 case 480:
4892 return 1;
4893 default:
4894 return 0;
4895 }
4896}
4897
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004898static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4899{
4900 int card;
4901 card_status_t status;
4902
4903 if (!parms)
4904 return;
4905
4906 if (parse_snd_card_status(parms, &card, &status) < 0)
4907 return;
4908
4909 pthread_mutex_lock(&adev->lock);
4910 bool valid_cb = (card == adev->snd_card);
4911 if (valid_cb) {
4912 if (adev->card_status != status) {
4913 adev->card_status = status;
4914 platform_snd_card_update(adev->platform, status);
4915 }
4916 }
4917 pthread_mutex_unlock(&adev->lock);
4918 return;
4919}
4920
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004921static int adev_open(const hw_module_t *module, const char *name,
4922 hw_device_t **device)
4923{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004924 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004925
Eric Laurent2bafff12016-03-17 12:17:23 -07004926 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004927 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004928 pthread_mutex_lock(&adev_init_lock);
4929 if (audio_device_ref_count != 0) {
4930 *device = &adev->device.common;
4931 audio_device_ref_count++;
4932 ALOGV("%s: returning existing instance of adev", __func__);
4933 ALOGV("%s: exit", __func__);
4934 pthread_mutex_unlock(&adev_init_lock);
4935 return 0;
4936 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004937 adev = calloc(1, sizeof(struct audio_device));
4938
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004939 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4940
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004941 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4942 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4943 adev->device.common.module = (struct hw_module_t *)module;
4944 adev->device.common.close = adev_close;
4945
4946 adev->device.init_check = adev_init_check;
4947 adev->device.set_voice_volume = adev_set_voice_volume;
4948 adev->device.set_master_volume = adev_set_master_volume;
4949 adev->device.get_master_volume = adev_get_master_volume;
4950 adev->device.set_master_mute = adev_set_master_mute;
4951 adev->device.get_master_mute = adev_get_master_mute;
4952 adev->device.set_mode = adev_set_mode;
4953 adev->device.set_mic_mute = adev_set_mic_mute;
4954 adev->device.get_mic_mute = adev_get_mic_mute;
4955 adev->device.set_parameters = adev_set_parameters;
4956 adev->device.get_parameters = adev_get_parameters;
4957 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4958 adev->device.open_output_stream = adev_open_output_stream;
4959 adev->device.close_output_stream = adev_close_output_stream;
4960 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004961
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004962 adev->device.close_input_stream = adev_close_input_stream;
4963 adev->device.dump = adev_dump;
4964
4965 /* Set the default route before the PCM stream is opened */
4966 pthread_mutex_lock(&adev->lock);
4967 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004968 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004969 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004970 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004971 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004972 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004973 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004974 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004975 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004976 pthread_mutex_unlock(&adev->lock);
4977
4978 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004979 adev->platform = platform_init(adev);
4980 if (!adev->platform) {
4981 free(adev->snd_dev_ref_cnt);
4982 free(adev);
4983 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4984 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004985 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004986 return -EINVAL;
4987 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05004988 adev->extspk = audio_extn_extspk_init(adev);
4989
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004990 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4991 if (adev->visualizer_lib == NULL) {
4992 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4993 } else {
4994 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4995 adev->visualizer_start_output =
4996 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4997 "visualizer_hal_start_output");
4998 adev->visualizer_stop_output =
4999 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5000 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07005001 }
5002
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005003 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5004 if (adev->offload_effects_lib == NULL) {
5005 ALOGW("%s: DLOPEN failed for %s", __func__,
5006 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5007 } else {
5008 ALOGV("%s: DLOPEN successful for %s", __func__,
5009 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5010 adev->offload_effects_start_output =
5011 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5012 "offload_effects_bundle_hal_start_output");
5013 adev->offload_effects_stop_output =
5014 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5015 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07005016 }
5017
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005018 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5019 if (adev->adm_lib == NULL) {
5020 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5021 } else {
5022 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5023 adev->adm_init = (adm_init_t)
5024 dlsym(adev->adm_lib, "adm_init");
5025 adev->adm_deinit = (adm_deinit_t)
5026 dlsym(adev->adm_lib, "adm_deinit");
5027 adev->adm_register_input_stream = (adm_register_input_stream_t)
5028 dlsym(adev->adm_lib, "adm_register_input_stream");
5029 adev->adm_register_output_stream = (adm_register_output_stream_t)
5030 dlsym(adev->adm_lib, "adm_register_output_stream");
5031 adev->adm_deregister_stream = (adm_deregister_stream_t)
5032 dlsym(adev->adm_lib, "adm_deregister_stream");
5033 adev->adm_request_focus = (adm_request_focus_t)
5034 dlsym(adev->adm_lib, "adm_request_focus");
5035 adev->adm_abandon_focus = (adm_abandon_focus_t)
5036 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08005037 adev->adm_set_config = (adm_set_config_t)
5038 dlsym(adev->adm_lib, "adm_set_config");
5039 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5040 dlsym(adev->adm_lib, "adm_request_focus_v2");
5041 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5042 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5043 adev->adm_on_routing_change = (adm_on_routing_change_t)
5044 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005045 }
5046
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005047 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005048 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005049
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005050 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005051
Andy Hung31aca912014-03-20 17:14:59 -07005052 if (k_enable_extended_precision)
5053 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005054
Glenn Kasten4f993392014-05-14 07:30:48 -07005055 char value[PROPERTY_VALUE_MAX];
5056 int trial;
5057 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5058 trial = atoi(value);
5059 if (period_size_is_plausible_for_low_latency(trial)) {
5060 pcm_config_low_latency.period_size = trial;
5061 pcm_config_low_latency.start_threshold = trial / 4;
5062 pcm_config_low_latency.avail_min = trial / 4;
5063 configured_low_latency_capture_period_size = trial;
5064 }
5065 }
5066 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5067 trial = atoi(value);
5068 if (period_size_is_plausible_for_low_latency(trial)) {
5069 configured_low_latency_capture_period_size = trial;
5070 }
5071 }
5072
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005073 // commented as full set of app type cfg is sent from platform
5074 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005075 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005076
5077 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5078 af_period_multiplier = atoi(value);
5079 if (af_period_multiplier < 0) {
5080 af_period_multiplier = 2;
5081 } else if (af_period_multiplier > 4) {
5082 af_period_multiplier = 4;
5083 }
5084 ALOGV("new period_multiplier = %d", af_period_multiplier);
5085 }
5086
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005087 audio_extn_tfa_98xx_init(adev);
5088
vivek mehta1a9b7c02015-06-25 11:49:38 -07005089 pthread_mutex_unlock(&adev_init_lock);
5090
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005091 if (adev->adm_init)
5092 adev->adm_data = adev->adm_init();
5093
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005094 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005095 audio_extn_snd_mon_init();
5096 pthread_mutex_lock(&adev->lock);
5097 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
5098 adev->card_status = CARD_STATUS_ONLINE;
5099 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005100 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005101
Eric Laurent2bafff12016-03-17 12:17:23 -07005102 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005103 return 0;
5104}
5105
5106static struct hw_module_methods_t hal_module_methods = {
5107 .open = adev_open,
5108};
5109
5110struct audio_module HAL_MODULE_INFO_SYM = {
5111 .common = {
5112 .tag = HARDWARE_MODULE_TAG,
5113 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5114 .hal_api_version = HARDWARE_HAL_API_VERSION,
5115 .id = AUDIO_HARDWARE_MODULE_ID,
5116 .name = "QCOM Audio HAL",
5117 .author = "Code Aurora Forum",
5118 .methods = &hal_module_methods,
5119 },
5120};