blob: 85c886b9a6abd19fbe1738847ab47dd48ce70373 [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);
3449 if (in->pcm) {
3450 struct timespec timestamp;
3451 unsigned int avail;
3452 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3453 *frames = in->frames_read + avail;
3454 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3455 ret = 0;
3456 }
3457 }
3458 pthread_mutex_unlock(&in->lock);
3459 return ret;
3460}
3461
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003462static int add_remove_audio_effect(const struct audio_stream *stream,
3463 effect_handle_t effect,
3464 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003465{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003466 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003467 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003468 int status = 0;
3469 effect_descriptor_t desc;
3470
3471 status = (*effect)->get_descriptor(effect, &desc);
3472 if (status != 0)
3473 return status;
3474
Eric Laurenta1478072015-09-21 17:21:52 -07003475 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003476 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003477 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003478 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003479 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003480 in->enable_aec != enable &&
3481 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3482 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003483 if (!enable)
3484 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003485 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3486 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3487 adev->enable_voicerx = enable;
3488 struct audio_usecase *usecase;
3489 struct listnode *node;
3490 list_for_each(node, &adev->usecase_list) {
3491 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07003492 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07003493 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05003494 }
3495 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003496 if (!in->standby)
3497 select_devices(in->dev, in->usecase);
3498 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003499 if (in->enable_ns != enable &&
3500 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3501 in->enable_ns = enable;
3502 if (!in->standby)
3503 select_devices(in->dev, in->usecase);
3504 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003505 pthread_mutex_unlock(&in->dev->lock);
3506 pthread_mutex_unlock(&in->lock);
3507
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003508 return 0;
3509}
3510
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003511static int in_add_audio_effect(const struct audio_stream *stream,
3512 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003513{
Eric Laurent994a6932013-07-17 11:51:42 -07003514 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003515 return add_remove_audio_effect(stream, effect, true);
3516}
3517
3518static int in_remove_audio_effect(const struct audio_stream *stream,
3519 effect_handle_t effect)
3520{
Eric Laurent994a6932013-07-17 11:51:42 -07003521 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003522 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003523}
3524
Eric Laurent0e46adf2016-12-16 12:49:24 -08003525static int in_stop(const struct audio_stream_in* stream)
3526{
3527 struct stream_in *in = (struct stream_in *)stream;
3528 struct audio_device *adev = in->dev;
3529
3530 int ret = -ENOSYS;
3531 ALOGV("%s", __func__);
3532 pthread_mutex_lock(&adev->lock);
3533 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3534 in->capture_started && in->pcm != NULL) {
3535 pcm_stop(in->pcm);
3536 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003537 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003538 }
3539 pthread_mutex_unlock(&adev->lock);
3540 return ret;
3541}
3542
3543static int in_start(const struct audio_stream_in* stream)
3544{
3545 struct stream_in *in = (struct stream_in *)stream;
3546 struct audio_device *adev = in->dev;
3547 int ret = -ENOSYS;
3548
3549 ALOGV("%s in %p", __func__, in);
3550 pthread_mutex_lock(&adev->lock);
3551 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3552 !in->capture_started && in->pcm != NULL) {
3553 if (!in->capture_started) {
3554 ret = start_input_stream(in);
3555 if (ret == 0) {
3556 in->capture_started = true;
3557 }
3558 }
3559 }
3560 pthread_mutex_unlock(&adev->lock);
3561 return ret;
3562}
3563
3564static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3565 int32_t min_size_frames,
3566 struct audio_mmap_buffer_info *info)
3567{
3568 struct stream_in *in = (struct stream_in *)stream;
3569 struct audio_device *adev = in->dev;
3570 int ret = 0;
3571 unsigned int offset1;
3572 unsigned int frames1;
3573 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003574 uint32_t mmap_size;
3575 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003576
3577 pthread_mutex_lock(&adev->lock);
3578 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003579
Eric Laurent0e46adf2016-12-16 12:49:24 -08003580 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003581 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003582 ret = -EINVAL;
3583 goto exit;
3584 }
3585 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003586 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003587 ALOGV("%s in %p", __func__, in);
3588 ret = -ENOSYS;
3589 goto exit;
3590 }
3591 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3592 if (in->pcm_device_id < 0) {
3593 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3594 __func__, in->pcm_device_id, in->usecase);
3595 ret = -EINVAL;
3596 goto exit;
3597 }
Phil Burkbc991042017-02-24 08:06:44 -08003598
3599 adjust_mmap_period_count(&in->config, min_size_frames);
3600
Eric Laurent0e46adf2016-12-16 12:49:24 -08003601 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3602 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3603 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3604 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3605 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3606 step = "open";
3607 ret = -ENODEV;
3608 goto exit;
3609 }
3610
3611 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3612 if (ret < 0) {
3613 step = "begin";
3614 goto exit;
3615 }
3616 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003617 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003618 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003619 ret = platform_get_mmap_data_fd(adev->platform,
3620 in->pcm_device_id, 1 /*capture*/,
3621 &info->shared_memory_fd,
3622 &mmap_size);
3623 if (ret < 0) {
3624 // Fall back to non exclusive mode
3625 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3626 } else {
3627 if (mmap_size < buffer_size) {
3628 step = "mmap";
3629 goto exit;
3630 }
3631 // FIXME: indicate exclusive mode support by returning a negative buffer size
3632 info->buffer_size_frames *= -1;
3633 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08003634
Haynes Mathew George96483a22017-03-28 14:52:47 -07003635 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003636
3637 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3638 if (ret < 0) {
3639 step = "commit";
3640 goto exit;
3641 }
3642
Phil Burkbc991042017-02-24 08:06:44 -08003643 in->standby = false;
3644 ret = 0;
3645
Eric Laurent0e46adf2016-12-16 12:49:24 -08003646 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3647 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003648
3649exit:
3650 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003651 if (in->pcm == NULL) {
3652 ALOGE("%s: %s - %d", __func__, step, ret);
3653 } else {
3654 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003655 pcm_close(in->pcm);
3656 in->pcm = NULL;
3657 }
3658 }
3659 pthread_mutex_unlock(&adev->lock);
3660 return ret;
3661}
3662
3663static int in_get_mmap_position(const struct audio_stream_in *stream,
3664 struct audio_mmap_position *position)
3665{
3666 struct stream_in *in = (struct stream_in *)stream;
3667 ALOGVV("%s", __func__);
3668 if (position == NULL) {
3669 return -EINVAL;
3670 }
3671 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
3672 return -ENOSYS;
3673 }
3674 if (in->pcm == NULL) {
3675 return -ENOSYS;
3676 }
3677 struct timespec ts = { 0, 0 };
3678 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
3679 if (ret < 0) {
3680 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3681 return ret;
3682 }
Andy Hungfc044e12017-03-20 09:24:22 -07003683 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003684 return 0;
3685}
3686
3687
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003688static int adev_open_output_stream(struct audio_hw_device *dev,
3689 audio_io_handle_t handle,
3690 audio_devices_t devices,
3691 audio_output_flags_t flags,
3692 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003693 struct audio_stream_out **stream_out,
3694 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003695{
3696 struct audio_device *adev = (struct audio_device *)dev;
3697 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003698 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003699 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
3700 bool is_usb_dev = audio_is_usb_out_device(devices) &&
3701 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003702
Andy Hungd9653bd2017-08-01 19:31:39 -07003703 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
3704 return -ENOSYS;
3705 }
3706
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003707 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
3708 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003709 *stream_out = NULL;
3710 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3711
3712 if (devices == AUDIO_DEVICE_NONE)
3713 devices = AUDIO_DEVICE_OUT_SPEAKER;
3714
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003715 out->flags = flags;
3716 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003717 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003718 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003719 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003720
3721 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003722 if ((is_hdmi || is_usb_dev) &&
3723 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
3724 (flags == AUDIO_OUTPUT_FLAG_NONE ||
3725 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003726 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003727 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003728 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003729 if (config->sample_rate == 0)
3730 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3731 if (config->channel_mask == 0)
3732 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3733 if (config->format == AUDIO_FORMAT_DEFAULT)
3734 config->format = AUDIO_FORMAT_PCM_16_BIT;
3735 } else if (is_usb_dev) {
3736 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
3737 &config->format,
3738 &out->supported_formats[0],
3739 MAX_SUPPORTED_FORMATS,
3740 &config->channel_mask,
3741 &out->supported_channel_masks[0],
3742 MAX_SUPPORTED_CHANNEL_MASKS,
3743 &config->sample_rate,
3744 &out->supported_sample_rates[0],
3745 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003746 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003747 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003748 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003749 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003750 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003751
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003752
Haynes Mathew George569b7482017-05-08 14:44:27 -07003753 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003754 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003755 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003756 if (is_hdmi) {
3757 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3758 out->config = pcm_config_hdmi_multi;
3759 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3760 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3761 out->config = pcm_config_mmap_playback;
3762 out->stream.start = out_start;
3763 out->stream.stop = out_stop;
3764 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3765 out->stream.get_mmap_position = out_get_mmap_position;
3766 } else {
3767 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3768 out->config = pcm_config_hifi;
3769 }
3770
3771 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003772 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003773 if (is_hdmi) {
3774 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
3775 audio_bytes_per_sample(out->format));
3776 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003777 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003778 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003779 pthread_mutex_lock(&adev->lock);
3780 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3781 pthread_mutex_unlock(&adev->lock);
3782
3783 // reject offload during card offline to allow
3784 // fallback to s/w paths
3785 if (offline) {
3786 ret = -ENODEV;
3787 goto error_open;
3788 }
3789
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003790 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3791 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3792 ALOGE("%s: Unsupported Offload information", __func__);
3793 ret = -EINVAL;
3794 goto error_open;
3795 }
3796 if (!is_supported_format(config->offload_info.format)) {
3797 ALOGE("%s: Unsupported audio format", __func__);
3798 ret = -EINVAL;
3799 goto error_open;
3800 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003801 out->sample_rate = config->offload_info.sample_rate;
3802 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
3803 out->channel_mask = config->offload_info.channel_mask;
3804 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
3805 out->channel_mask = config->channel_mask;
3806 else
3807 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3808
3809 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003810
3811 out->compr_config.codec = (struct snd_codec *)
3812 calloc(1, sizeof(struct snd_codec));
3813
3814 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003815
3816 out->stream.set_callback = out_set_callback;
3817 out->stream.pause = out_pause;
3818 out->stream.resume = out_resume;
3819 out->stream.drain = out_drain;
3820 out->stream.flush = out_flush;
3821
3822 out->compr_config.codec->id =
3823 get_snd_codec_id(config->offload_info.format);
3824 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3825 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003826 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003827 out->compr_config.codec->bit_rate =
3828 config->offload_info.bit_rate;
3829 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003830 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003831 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3832
3833 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3834 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003835
3836 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003837 create_offload_callback_thread(out);
3838 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3839 __func__, config->offload_info.version,
3840 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003841 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07003842 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003843 case 0:
3844 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
3845 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07003846 case 8000:
3847 case 16000:
3848 case 48000:
3849 out->sample_rate = config->sample_rate;
3850 break;
3851 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003852 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
3853 config->sample_rate);
3854 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3855 ret = -EINVAL;
3856 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003857 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003858 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
3859 switch (config->channel_mask) {
3860 case AUDIO_CHANNEL_NONE:
3861 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3862 break;
3863 case AUDIO_CHANNEL_OUT_STEREO:
3864 out->channel_mask = config->channel_mask;
3865 break;
3866 default:
3867 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
3868 config->channel_mask);
3869 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3870 ret = -EINVAL;
3871 break;
3872 }
3873 switch (config->format) {
3874 case AUDIO_FORMAT_DEFAULT:
3875 out->format = AUDIO_FORMAT_PCM_16_BIT;
3876 break;
3877 case AUDIO_FORMAT_PCM_16_BIT:
3878 out->format = config->format;
3879 break;
3880 default:
3881 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
3882 config->format);
3883 config->format = AUDIO_FORMAT_PCM_16_BIT;
3884 ret = -EINVAL;
3885 break;
3886 }
3887 if (ret != 0)
3888 goto error_open;
3889
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003890 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3891 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003892 out->config.rate = out->sample_rate;
3893 out->config.channels =
3894 audio_channel_count_from_out_mask(out->channel_mask);
3895 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003896 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003897 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
3898 switch (config->sample_rate) {
3899 case 0:
3900 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3901 break;
3902 case 8000:
3903 case 16000:
3904 case 32000:
3905 case 48000:
3906 out->sample_rate = config->sample_rate;
3907 break;
3908 default:
3909 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
3910 config->sample_rate);
3911 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3912 ret = -EINVAL;
3913 break;
3914 }
Eric Laurentad2dde92017-09-20 18:27:31 -07003915 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003916 switch (config->channel_mask) {
3917 case AUDIO_CHANNEL_NONE:
3918 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3919 break;
3920 case AUDIO_CHANNEL_OUT_STEREO:
3921 out->channel_mask = config->channel_mask;
3922 break;
3923 default:
3924 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
3925 config->channel_mask);
3926 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3927 ret = -EINVAL;
3928 break;
3929 }
3930 switch (config->format) {
3931 case AUDIO_FORMAT_DEFAULT:
3932 out->format = AUDIO_FORMAT_PCM_16_BIT;
3933 break;
3934 case AUDIO_FORMAT_PCM_16_BIT:
3935 out->format = config->format;
3936 break;
3937 default:
3938 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
3939 config->format);
3940 config->format = AUDIO_FORMAT_PCM_16_BIT;
3941 ret = -EINVAL;
3942 break;
3943 }
3944 if (ret != 0)
3945 goto error_open;
3946
vivek mehtaa68fea62017-06-08 19:04:02 -07003947 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07003948 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
3949 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003950 out->config.rate = out->sample_rate;
3951 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07003952 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003953 out->sample_rate,
3954 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07003955 out->config.channels,
3956 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003957 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07003958 out->config.period_size = buffer_size / frame_size;
3959 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
3960 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003961 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003962 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003963 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3964 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003965 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003966 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3967 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003968 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003969 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003970 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003971 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003972 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003973 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3974 out->config = pcm_config_mmap_playback;
3975 out->stream.start = out_start;
3976 out->stream.stop = out_stop;
3977 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3978 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003979 } else {
3980 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3981 out->config = pcm_config_low_latency;
3982 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003983
3984 if (config->sample_rate == 0) {
3985 out->sample_rate = out->config.rate;
3986 } else {
3987 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003988 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003989 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
3990 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
3991 } else {
3992 out->channel_mask = config->channel_mask;
3993 }
3994 if (config->format == AUDIO_FORMAT_DEFAULT)
3995 out->format = audio_format_from_pcm_format(out->config.format);
3996 else if (!audio_is_linear_pcm(config->format)) {
3997 config->format = AUDIO_FORMAT_PCM_16_BIT;
3998 ret = -EINVAL;
3999 goto error_open;
4000 } else {
4001 out->format = config->format;
4002 }
4003
4004 out->config.rate = out->sample_rate;
4005 out->config.channels =
4006 audio_channel_count_from_out_mask(out->channel_mask);
4007 if (out->format != audio_format_from_pcm_format(out->config.format)) {
4008 out->config.format = pcm_format_from_audio_format(out->format);
4009 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004010 }
Kevin Rocard50eff892017-05-02 16:52:05 -07004011
4012 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
4013 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004014 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004015 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
4016 __func__, config->sample_rate, config->format, config->channel_mask);
4017 config->sample_rate = out->sample_rate;
4018 config->format = out->format;
4019 config->channel_mask = out->channel_mask;
4020 ret = -EINVAL;
4021 goto error_open;
4022 }
4023
Andy Hung6fcba9c2014-03-18 11:53:32 -07004024 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
4025 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004026
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004027 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004028 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004029 adev->primary_output = out;
4030 else {
4031 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004032 ret = -EEXIST;
4033 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004034 }
4035 }
4036
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004037 /* Check if this usecase is already existing */
4038 pthread_mutex_lock(&adev->lock);
4039 if (get_usecase_from_list(adev, out->usecase) != NULL) {
4040 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004041 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004042 ret = -EEXIST;
4043 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004044 }
4045 pthread_mutex_unlock(&adev->lock);
4046
4047 out->stream.common.get_sample_rate = out_get_sample_rate;
4048 out->stream.common.set_sample_rate = out_set_sample_rate;
4049 out->stream.common.get_buffer_size = out_get_buffer_size;
4050 out->stream.common.get_channels = out_get_channels;
4051 out->stream.common.get_format = out_get_format;
4052 out->stream.common.set_format = out_set_format;
4053 out->stream.common.standby = out_standby;
4054 out->stream.common.dump = out_dump;
4055 out->stream.common.set_parameters = out_set_parameters;
4056 out->stream.common.get_parameters = out_get_parameters;
4057 out->stream.common.add_audio_effect = out_add_audio_effect;
4058 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4059 out->stream.get_latency = out_get_latency;
4060 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004061#ifdef NO_AUDIO_OUT
4062 out->stream.write = out_write_for_no_output;
4063#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004064 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004065#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004066 out->stream.get_render_position = out_get_render_position;
4067 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004068 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004069
Eric Laurent0e46adf2016-12-16 12:49:24 -08004070 if (out->realtime)
4071 out->af_period_multiplier = af_period_multiplier;
4072 else
4073 out->af_period_multiplier = 1;
4074
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004075 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004076 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004077 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004079 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004080 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004081 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4082
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004083 config->format = out->stream.common.get_format(&out->stream.common);
4084 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4085 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4086
Andy Hunga452b0a2017-03-15 14:51:15 -07004087 out->error_log = error_log_create(
4088 ERROR_LOG_ENTRIES,
4089 1000000000 /* aggregate consecutive identical errors within one second in ns */);
4090
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004091 /*
4092 By locking output stream before registering, we allow the callback
4093 to update stream's state only after stream's initial state is set to
4094 adev state.
4095 */
4096 lock_output_stream(out);
4097 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4098 pthread_mutex_lock(&adev->lock);
4099 out->card_status = adev->card_status;
4100 pthread_mutex_unlock(&adev->lock);
4101 pthread_mutex_unlock(&out->lock);
4102
vivek mehta4a824772017-06-08 19:05:49 -07004103 stream_app_type_cfg_init(&out->app_type_cfg);
4104
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004105 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004106
Eric Laurent994a6932013-07-17 11:51:42 -07004107 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004108 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004109
4110error_open:
4111 free(out);
4112 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07004113 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004114 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004115}
4116
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004117static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004118 struct audio_stream_out *stream)
4119{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004120 struct stream_out *out = (struct stream_out *)stream;
4121 struct audio_device *adev = out->dev;
4122
Eric Laurent994a6932013-07-17 11:51:42 -07004123 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004124
4125 // must deregister from sndmonitor first to prevent races
4126 // between the callback and close_stream
4127 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004128 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004129 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
4130 destroy_offload_callback_thread(out);
4131
4132 if (out->compr_config.codec != NULL)
4133 free(out->compr_config.codec);
4134 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004135
4136 if (adev->voice_tx_output == out)
4137 adev->voice_tx_output = NULL;
4138
Andy Hunga452b0a2017-03-15 14:51:15 -07004139 error_log_destroy(out->error_log);
4140 out->error_log = NULL;
4141
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004142 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004143 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004144 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004145 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004146 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004147}
4148
4149static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4150{
4151 struct audio_device *adev = (struct audio_device *)dev;
4152 struct str_parms *parms;
4153 char *str;
4154 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004155 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004156 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07004157 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004158
Joe Onorato188b6222016-03-01 11:02:27 -08004159 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004160
4161 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004162
4163 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004164 status = voice_set_parameters(adev, parms);
4165 if (status != 0) {
4166 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004167 }
4168
4169 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4170 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07004171 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004172 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4173 adev->bluetooth_nrec = true;
4174 else
4175 adev->bluetooth_nrec = false;
4176 }
4177
4178 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4179 if (ret >= 0) {
4180 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4181 adev->screen_off = false;
4182 else
4183 adev->screen_off = true;
4184 }
4185
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004186 ret = str_parms_get_int(parms, "rotation", &val);
4187 if (ret >= 0) {
4188 bool reverse_speakers = false;
4189 switch(val) {
4190 // FIXME: note that the code below assumes that the speakers are in the correct placement
4191 // relative to the user when the device is rotated 90deg from its default rotation. This
4192 // assumption is device-specific, not platform-specific like this code.
4193 case 270:
4194 reverse_speakers = true;
4195 break;
4196 case 0:
4197 case 90:
4198 case 180:
4199 break;
4200 default:
4201 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07004202 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004203 }
Eric Laurent03f09432014-03-25 18:09:11 -07004204 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004205 // check and set swap
4206 // - check if orientation changed and speaker active
4207 // - set rotation and cache the rotation value
4208 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004209 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004210 }
4211
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004212 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4213 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004214 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004215 }
4216
David Linee3fe402017-03-13 10:00:42 -07004217 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4218 if (ret >= 0) {
4219 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004220 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004221 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4222 if (ret >= 0) {
4223 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004224 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004225 }
Eric Laurent99dab492017-06-17 15:19:08 -07004226 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004227 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4228 if (ret >= 0) {
4229 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004230 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004231 }
4232 }
4233 }
4234
4235 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4236 if (ret >= 0) {
4237 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004238 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004239 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4240 if (ret >= 0) {
4241 const int card = atoi(value);
4242
Eric Laurent99dab492017-06-17 15:19:08 -07004243 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004244 }
Eric Laurent99dab492017-06-17 15:19:08 -07004245 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004246 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4247 if (ret >= 0) {
4248 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004249 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004250 }
4251 }
4252 }
4253
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004254 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004255done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004256 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004257 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004258 ALOGV("%s: exit with code(%d)", __func__, status);
4259 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004260}
4261
4262static char* adev_get_parameters(const struct audio_hw_device *dev,
4263 const char *keys)
4264{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004265 struct audio_device *adev = (struct audio_device *)dev;
4266 struct str_parms *reply = str_parms_create();
4267 struct str_parms *query = str_parms_create_str(keys);
4268 char *str;
4269
4270 pthread_mutex_lock(&adev->lock);
4271
4272 voice_get_parameters(adev, query, reply);
4273 str = str_parms_to_str(reply);
4274 str_parms_destroy(query);
4275 str_parms_destroy(reply);
4276
4277 pthread_mutex_unlock(&adev->lock);
4278 ALOGV("%s: exit: returns - %s", __func__, str);
4279 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004280}
4281
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004282static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004283{
4284 return 0;
4285}
4286
Haynes Mathew George5191a852013-09-11 14:19:36 -07004287static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4288{
4289 int ret;
4290 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004291
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004292 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4293
Haynes Mathew George5191a852013-09-11 14:19:36 -07004294 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004295 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004296 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004297
Haynes Mathew George5191a852013-09-11 14:19:36 -07004298 return ret;
4299}
4300
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004301static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004302{
4303 return -ENOSYS;
4304}
4305
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004306static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4307 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004308{
4309 return -ENOSYS;
4310}
4311
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004312static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004313{
4314 return -ENOSYS;
4315}
4316
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004317static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004318{
4319 return -ENOSYS;
4320}
4321
4322static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4323{
4324 struct audio_device *adev = (struct audio_device *)dev;
4325
4326 pthread_mutex_lock(&adev->lock);
4327 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004328 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004329 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004330 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4331 voice_is_in_call(adev)) {
4332 voice_stop_call(adev);
4333 adev->current_call_output = NULL;
4334 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004335 }
4336 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004337
4338 audio_extn_extspk_set_mode(adev->extspk, mode);
4339
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004340 return 0;
4341}
4342
4343static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4344{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004345 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004346 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004347
Eric Laurent2bafff12016-03-17 12:17:23 -07004348 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004349 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004350 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4351 ret = audio_extn_hfp_set_mic_mute(adev, state);
4352 } else {
4353 ret = voice_set_mic_mute(adev, state);
4354 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004355 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004356 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004357
4358 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004359}
4360
4361static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4362{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004363 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004364 return 0;
4365}
4366
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004367static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004368 const struct audio_config *config)
4369{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004370 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004371
Eric Laurent74b55762017-07-09 17:04:53 -07004372 /* Don't know if USB HIFI in this context so use true to be conservative */
4373 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4374 true /*is_usb_hifi */) != 0)
4375 return 0;
4376
vivek mehtaa68fea62017-06-08 19:04:02 -07004377 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4378 config->sample_rate, config->format,
4379 channel_count,
4380 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004381}
4382
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004383static bool adev_input_allow_hifi_record(struct audio_device *adev,
4384 audio_devices_t devices,
4385 audio_input_flags_t flags,
4386 audio_source_t source) {
4387 const bool allowed = true;
4388
4389 if (!audio_is_usb_in_device(devices))
4390 return !allowed;
4391
4392 switch (flags) {
4393 case AUDIO_INPUT_FLAG_NONE:
4394 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4395 break;
4396 default:
4397 return !allowed;
4398 }
4399
4400 switch (source) {
4401 case AUDIO_SOURCE_DEFAULT:
4402 case AUDIO_SOURCE_MIC:
4403 case AUDIO_SOURCE_UNPROCESSED:
4404 break;
4405 default:
4406 return !allowed;
4407 }
4408
4409 switch (adev->mode) {
4410 case 0:
4411 break;
4412 default:
4413 return !allowed;
4414 }
4415
4416 return allowed;
4417}
4418
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004419static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004420 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004421 audio_devices_t devices,
4422 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004423 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004424 audio_input_flags_t flags,
4425 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004426 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004427{
4428 struct audio_device *adev = (struct audio_device *)dev;
4429 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004430 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004431 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004432 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004433 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004434 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4435 devices,
4436 flags,
4437 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004438 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004439 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004440
Andy Hungd9653bd2017-08-01 19:31:39 -07004441 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
4442 return -ENOSYS;
4443 }
4444
Eric Laurent74b55762017-07-09 17:04:53 -07004445 if (!(is_usb_dev && may_use_hifi_record)) {
4446 if (config->sample_rate == 0)
4447 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4448 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4449 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4450 if (config->format == AUDIO_FORMAT_DEFAULT)
4451 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004452
Eric Laurent74b55762017-07-09 17:04:53 -07004453 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
4454
4455 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
4456 return -EINVAL;
4457 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004458
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004459 if (audio_extn_tfa_98xx_is_supported() &&
4460 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004461 return -EINVAL;
4462
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004463 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4464
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004465 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004466 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004467
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004468 in->stream.common.get_sample_rate = in_get_sample_rate;
4469 in->stream.common.set_sample_rate = in_set_sample_rate;
4470 in->stream.common.get_buffer_size = in_get_buffer_size;
4471 in->stream.common.get_channels = in_get_channels;
4472 in->stream.common.get_format = in_get_format;
4473 in->stream.common.set_format = in_set_format;
4474 in->stream.common.standby = in_standby;
4475 in->stream.common.dump = in_dump;
4476 in->stream.common.set_parameters = in_set_parameters;
4477 in->stream.common.get_parameters = in_get_parameters;
4478 in->stream.common.add_audio_effect = in_add_audio_effect;
4479 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4480 in->stream.set_gain = in_set_gain;
4481 in->stream.read = in_read;
4482 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08004483 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004484
4485 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004486 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004487 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004488 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004489 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004490 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004491
Haynes Mathew George569b7482017-05-08 14:44:27 -07004492 if (is_usb_dev && may_use_hifi_record) {
4493 /* HiFi record selects an appropriate format, channel, rate combo
4494 depending on sink capabilities*/
4495 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
4496 &config->format,
4497 &in->supported_formats[0],
4498 MAX_SUPPORTED_FORMATS,
4499 &config->channel_mask,
4500 &in->supported_channel_masks[0],
4501 MAX_SUPPORTED_CHANNEL_MASKS,
4502 &config->sample_rate,
4503 &in->supported_sample_rates[0],
4504 MAX_SUPPORTED_SAMPLE_RATES);
4505 if (ret != 0) {
4506 ret = -EINVAL;
4507 goto err_open;
4508 }
Eric Laurent74b55762017-07-09 17:04:53 -07004509 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004510 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07004511 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07004512 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
4513 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
4514 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4515 bool ret_error = false;
4516 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4517 from HAL is 8_24
4518 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4519 8_24 return error indicating supported format is 8_24
4520 *> In case of any other source requesting 24 bit or float return error
4521 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07004522
vivek mehta57ff9b52016-04-28 14:13:08 -07004523 on error flinger will retry with supported format passed
4524 */
4525 if (source != AUDIO_SOURCE_UNPROCESSED) {
4526 config->format = AUDIO_FORMAT_PCM_16_BIT;
4527 ret_error = true;
4528 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
4529 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
4530 ret_error = true;
4531 }
4532
4533 if (ret_error) {
4534 ret = -EINVAL;
4535 goto err_open;
4536 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004537 }
4538
vivek mehta57ff9b52016-04-28 14:13:08 -07004539 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07004540 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07004541
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004542 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004543 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
4544 if (config->sample_rate == 0)
4545 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4546 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4547 config->sample_rate != 8000) {
4548 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4549 ret = -EINVAL;
4550 goto err_open;
4551 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004552
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004553 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4554 config->format = AUDIO_FORMAT_PCM_16_BIT;
4555 ret = -EINVAL;
4556 goto err_open;
4557 }
4558
4559 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4560 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07004561 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004562 } else if (is_usb_dev && may_use_hifi_record) {
4563 in->usecase = USECASE_AUDIO_RECORD_HIFI;
4564 in->config = pcm_config_audio_capture;
4565 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004566 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4567 config->sample_rate,
4568 config->format,
4569 channel_count,
4570 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004571 in->config.period_size = buffer_size / frame_size;
4572 in->config.rate = config->sample_rate;
4573 in->af_period_multiplier = 1;
4574 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004575 } else {
4576 in->usecase = USECASE_AUDIO_RECORD;
4577 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08004578 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004579 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07004580#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004581 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07004582#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08004583 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004584 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08004585 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004586 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004587 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4588 config->sample_rate,
4589 config->format,
4590 channel_count,
4591 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004592 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004593 in->config.rate = config->sample_rate;
4594 in->af_period_multiplier = 1;
4595 } else {
4596 // period size is left untouched for rt mode playback
4597 in->config = pcm_config_audio_capture_rt;
4598 in->af_period_multiplier = af_period_multiplier;
4599 }
4600 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
4601 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004602 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08004603 in->usecase = USECASE_AUDIO_RECORD_MMAP;
4604 in->config = pcm_config_mmap_capture;
4605 in->stream.start = in_start;
4606 in->stream.stop = in_stop;
4607 in->stream.create_mmap_buffer = in_create_mmap_buffer;
4608 in->stream.get_mmap_position = in_get_mmap_position;
4609 in->af_period_multiplier = 1;
4610 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07004611 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07004612 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07004613 (config->sample_rate == 8000 ||
4614 config->sample_rate == 16000 ||
4615 config->sample_rate == 32000 ||
4616 config->sample_rate == 48000) &&
4617 channel_count == 1) {
4618 in->usecase = USECASE_AUDIO_RECORD_VOIP;
4619 in->config = pcm_config_audio_capture;
4620 frame_size = audio_stream_in_frame_size(&in->stream);
4621 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
4622 config->sample_rate,
4623 config->format,
4624 channel_count, false /*is_low_latency*/);
4625 in->config.period_size = buffer_size / frame_size;
4626 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
4627 in->config.rate = config->sample_rate;
4628 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004629 } else {
4630 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004631 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004632 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4633 config->sample_rate,
4634 config->format,
4635 channel_count,
4636 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004637 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004638 in->config.rate = config->sample_rate;
4639 in->af_period_multiplier = 1;
4640 }
4641 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
4642 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004643 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004644
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004645 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07004646 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004647
Andy Hungd13f0d32017-06-12 13:58:37 -07004648 in->error_log = error_log_create(
4649 ERROR_LOG_ENTRIES,
4650 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
4651
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004652 /* This stream could be for sound trigger lab,
4653 get sound trigger pcm if present */
4654 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004655
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004656 lock_input_stream(in);
4657 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
4658 pthread_mutex_lock(&adev->lock);
4659 in->card_status = adev->card_status;
4660 pthread_mutex_unlock(&adev->lock);
4661 pthread_mutex_unlock(&in->lock);
4662
vivek mehta4a824772017-06-08 19:05:49 -07004663 stream_app_type_cfg_init(&in->app_type_cfg);
4664
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004665 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004666 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004667 return 0;
4668
4669err_open:
4670 free(in);
4671 *stream_in = NULL;
4672 return ret;
4673}
4674
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004675static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004676 struct audio_stream_in *stream)
4677{
Andy Hungd13f0d32017-06-12 13:58:37 -07004678 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004679 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004680
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004681 // must deregister from sndmonitor first to prevent races
4682 // between the callback and close_stream
4683 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004684 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07004685
4686 error_log_destroy(in->error_log);
4687 in->error_log = NULL;
4688
Andy Hung0dbb52b2017-08-09 13:51:38 -07004689 pthread_mutex_destroy(&in->pre_lock);
4690 pthread_mutex_destroy(&in->lock);
4691
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004692 free(stream);
4693
4694 return;
4695}
4696
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004697static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004698{
4699 return 0;
4700}
4701
Andy Hung31aca912014-03-20 17:14:59 -07004702/* verifies input and output devices and their capabilities.
4703 *
4704 * This verification is required when enabling extended bit-depth or
4705 * sampling rates, as not all qcom products support it.
4706 *
4707 * Suitable for calling only on initialization such as adev_open().
4708 * It fills the audio_device use_case_table[] array.
4709 *
4710 * Has a side-effect that it needs to configure audio routing / devices
4711 * in order to power up the devices and read the device parameters.
4712 * It does not acquire any hw device lock. Should restore the devices
4713 * back to "normal state" upon completion.
4714 */
4715static int adev_verify_devices(struct audio_device *adev)
4716{
4717 /* enumeration is a bit difficult because one really wants to pull
4718 * the use_case, device id, etc from the hidden pcm_device_table[].
4719 * In this case there are the following use cases and device ids.
4720 *
4721 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
4722 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004723 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07004724 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
4725 * [USECASE_AUDIO_RECORD] = {0, 0},
4726 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
4727 * [USECASE_VOICE_CALL] = {2, 2},
4728 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004729 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07004730 * USECASE_VOICE_CALL omitted, but possible for either input or output.
4731 */
4732
4733 /* should be the usecases enabled in adev_open_input_stream() */
4734 static const int test_in_usecases[] = {
4735 USECASE_AUDIO_RECORD,
4736 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
4737 };
4738 /* should be the usecases enabled in adev_open_output_stream()*/
4739 static const int test_out_usecases[] = {
4740 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
4741 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
4742 };
4743 static const usecase_type_t usecase_type_by_dir[] = {
4744 PCM_PLAYBACK,
4745 PCM_CAPTURE,
4746 };
4747 static const unsigned flags_by_dir[] = {
4748 PCM_OUT,
4749 PCM_IN,
4750 };
4751
4752 size_t i;
4753 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004754 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07004755 char info[512]; /* for possible debug info */
4756
4757 for (dir = 0; dir < 2; ++dir) {
4758 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
4759 const unsigned flags_dir = flags_by_dir[dir];
4760 const size_t testsize =
4761 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
4762 const int *testcases =
4763 dir ? test_in_usecases : test_out_usecases;
4764 const audio_devices_t audio_device =
4765 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
4766
4767 for (i = 0; i < testsize; ++i) {
4768 const audio_usecase_t audio_usecase = testcases[i];
4769 int device_id;
4770 snd_device_t snd_device;
4771 struct pcm_params **pparams;
4772 struct stream_out out;
4773 struct stream_in in;
4774 struct audio_usecase uc_info;
4775 int retval;
4776
4777 pparams = &adev->use_case_table[audio_usecase];
4778 pcm_params_free(*pparams); /* can accept null input */
4779 *pparams = NULL;
4780
4781 /* find the device ID for the use case (signed, for error) */
4782 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
4783 if (device_id < 0)
4784 continue;
4785
4786 /* prepare structures for device probing */
4787 memset(&uc_info, 0, sizeof(uc_info));
4788 uc_info.id = audio_usecase;
4789 uc_info.type = usecase_type;
4790 if (dir) {
4791 adev->active_input = &in;
4792 memset(&in, 0, sizeof(in));
4793 in.device = audio_device;
4794 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4795 uc_info.stream.in = &in;
4796 } else {
4797 adev->active_input = NULL;
4798 }
4799 memset(&out, 0, sizeof(out));
4800 out.devices = audio_device; /* only field needed in select_devices */
4801 uc_info.stream.out = &out;
4802 uc_info.devices = audio_device;
4803 uc_info.in_snd_device = SND_DEVICE_NONE;
4804 uc_info.out_snd_device = SND_DEVICE_NONE;
4805 list_add_tail(&adev->usecase_list, &uc_info.list);
4806
4807 /* select device - similar to start_(in/out)put_stream() */
4808 retval = select_devices(adev, audio_usecase);
4809 if (retval >= 0) {
4810 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4811#if LOG_NDEBUG == 0
4812 if (*pparams) {
4813 ALOGV("%s: (%s) card %d device %d", __func__,
4814 dir ? "input" : "output", card_id, device_id);
4815 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004816 } else {
4817 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4818 }
4819#endif
4820 }
4821
4822 /* deselect device - similar to stop_(in/out)put_stream() */
4823 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004824 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004825 /* 2. Disable the rx device */
4826 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004827 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004828 list_remove(&uc_info.list);
4829 }
4830 }
4831 adev->active_input = NULL; /* restore adev state */
4832 return 0;
4833}
4834
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004835static int adev_close(hw_device_t *device)
4836{
Andy Hung31aca912014-03-20 17:14:59 -07004837 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004838 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004839
4840 if (!adev)
4841 return 0;
4842
4843 pthread_mutex_lock(&adev_init_lock);
4844
4845 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004846 audio_extn_snd_mon_unregister_listener(adev);
4847 audio_extn_tfa_98xx_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004848 audio_route_free(adev->audio_route);
4849 free(adev->snd_dev_ref_cnt);
4850 platform_deinit(adev->platform);
4851 audio_extn_extspk_deinit(adev->extspk);
4852 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004853 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004854 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4855 pcm_params_free(adev->use_case_table[i]);
4856 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004857 if (adev->adm_deinit)
4858 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004859 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004860 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004861 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004862
4863 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004864
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004865 return 0;
4866}
4867
Glenn Kasten4f993392014-05-14 07:30:48 -07004868/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4869 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4870 * just that it _might_ work.
4871 */
4872static int period_size_is_plausible_for_low_latency(int period_size)
4873{
4874 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004875 case 48:
4876 case 96:
4877 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004878 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004879 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004880 case 240:
4881 case 320:
4882 case 480:
4883 return 1;
4884 default:
4885 return 0;
4886 }
4887}
4888
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004889static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4890{
4891 int card;
4892 card_status_t status;
4893
4894 if (!parms)
4895 return;
4896
4897 if (parse_snd_card_status(parms, &card, &status) < 0)
4898 return;
4899
4900 pthread_mutex_lock(&adev->lock);
4901 bool valid_cb = (card == adev->snd_card);
4902 if (valid_cb) {
4903 if (adev->card_status != status) {
4904 adev->card_status = status;
4905 platform_snd_card_update(adev->platform, status);
4906 }
4907 }
4908 pthread_mutex_unlock(&adev->lock);
4909 return;
4910}
4911
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004912static int adev_open(const hw_module_t *module, const char *name,
4913 hw_device_t **device)
4914{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004915 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004916
Eric Laurent2bafff12016-03-17 12:17:23 -07004917 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004918 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004919 pthread_mutex_lock(&adev_init_lock);
4920 if (audio_device_ref_count != 0) {
4921 *device = &adev->device.common;
4922 audio_device_ref_count++;
4923 ALOGV("%s: returning existing instance of adev", __func__);
4924 ALOGV("%s: exit", __func__);
4925 pthread_mutex_unlock(&adev_init_lock);
4926 return 0;
4927 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004928 adev = calloc(1, sizeof(struct audio_device));
4929
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004930 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4931
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004932 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4933 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4934 adev->device.common.module = (struct hw_module_t *)module;
4935 adev->device.common.close = adev_close;
4936
4937 adev->device.init_check = adev_init_check;
4938 adev->device.set_voice_volume = adev_set_voice_volume;
4939 adev->device.set_master_volume = adev_set_master_volume;
4940 adev->device.get_master_volume = adev_get_master_volume;
4941 adev->device.set_master_mute = adev_set_master_mute;
4942 adev->device.get_master_mute = adev_get_master_mute;
4943 adev->device.set_mode = adev_set_mode;
4944 adev->device.set_mic_mute = adev_set_mic_mute;
4945 adev->device.get_mic_mute = adev_get_mic_mute;
4946 adev->device.set_parameters = adev_set_parameters;
4947 adev->device.get_parameters = adev_get_parameters;
4948 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4949 adev->device.open_output_stream = adev_open_output_stream;
4950 adev->device.close_output_stream = adev_close_output_stream;
4951 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004952
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004953 adev->device.close_input_stream = adev_close_input_stream;
4954 adev->device.dump = adev_dump;
4955
4956 /* Set the default route before the PCM stream is opened */
4957 pthread_mutex_lock(&adev->lock);
4958 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004959 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004960 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004961 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004962 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004963 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004964 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004965 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004966 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004967 pthread_mutex_unlock(&adev->lock);
4968
4969 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004970 adev->platform = platform_init(adev);
4971 if (!adev->platform) {
4972 free(adev->snd_dev_ref_cnt);
4973 free(adev);
4974 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4975 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004976 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004977 return -EINVAL;
4978 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05004979 adev->extspk = audio_extn_extspk_init(adev);
4980
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004981 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4982 if (adev->visualizer_lib == NULL) {
4983 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4984 } else {
4985 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4986 adev->visualizer_start_output =
4987 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4988 "visualizer_hal_start_output");
4989 adev->visualizer_stop_output =
4990 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4991 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07004992 }
4993
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004994 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4995 if (adev->offload_effects_lib == NULL) {
4996 ALOGW("%s: DLOPEN failed for %s", __func__,
4997 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4998 } else {
4999 ALOGV("%s: DLOPEN successful for %s", __func__,
5000 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5001 adev->offload_effects_start_output =
5002 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5003 "offload_effects_bundle_hal_start_output");
5004 adev->offload_effects_stop_output =
5005 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5006 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07005007 }
5008
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005009 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5010 if (adev->adm_lib == NULL) {
5011 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5012 } else {
5013 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5014 adev->adm_init = (adm_init_t)
5015 dlsym(adev->adm_lib, "adm_init");
5016 adev->adm_deinit = (adm_deinit_t)
5017 dlsym(adev->adm_lib, "adm_deinit");
5018 adev->adm_register_input_stream = (adm_register_input_stream_t)
5019 dlsym(adev->adm_lib, "adm_register_input_stream");
5020 adev->adm_register_output_stream = (adm_register_output_stream_t)
5021 dlsym(adev->adm_lib, "adm_register_output_stream");
5022 adev->adm_deregister_stream = (adm_deregister_stream_t)
5023 dlsym(adev->adm_lib, "adm_deregister_stream");
5024 adev->adm_request_focus = (adm_request_focus_t)
5025 dlsym(adev->adm_lib, "adm_request_focus");
5026 adev->adm_abandon_focus = (adm_abandon_focus_t)
5027 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08005028 adev->adm_set_config = (adm_set_config_t)
5029 dlsym(adev->adm_lib, "adm_set_config");
5030 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5031 dlsym(adev->adm_lib, "adm_request_focus_v2");
5032 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5033 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5034 adev->adm_on_routing_change = (adm_on_routing_change_t)
5035 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005036 }
5037
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005038 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005039 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005040
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005041 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005042
Andy Hung31aca912014-03-20 17:14:59 -07005043 if (k_enable_extended_precision)
5044 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005045
Glenn Kasten4f993392014-05-14 07:30:48 -07005046 char value[PROPERTY_VALUE_MAX];
5047 int trial;
5048 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5049 trial = atoi(value);
5050 if (period_size_is_plausible_for_low_latency(trial)) {
5051 pcm_config_low_latency.period_size = trial;
5052 pcm_config_low_latency.start_threshold = trial / 4;
5053 pcm_config_low_latency.avail_min = trial / 4;
5054 configured_low_latency_capture_period_size = trial;
5055 }
5056 }
5057 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5058 trial = atoi(value);
5059 if (period_size_is_plausible_for_low_latency(trial)) {
5060 configured_low_latency_capture_period_size = trial;
5061 }
5062 }
5063
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005064 // commented as full set of app type cfg is sent from platform
5065 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005066 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005067
5068 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5069 af_period_multiplier = atoi(value);
5070 if (af_period_multiplier < 0) {
5071 af_period_multiplier = 2;
5072 } else if (af_period_multiplier > 4) {
5073 af_period_multiplier = 4;
5074 }
5075 ALOGV("new period_multiplier = %d", af_period_multiplier);
5076 }
5077
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005078 audio_extn_tfa_98xx_init(adev);
5079
vivek mehta1a9b7c02015-06-25 11:49:38 -07005080 pthread_mutex_unlock(&adev_init_lock);
5081
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005082 if (adev->adm_init)
5083 adev->adm_data = adev->adm_init();
5084
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005085 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005086 audio_extn_snd_mon_init();
5087 pthread_mutex_lock(&adev->lock);
5088 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
5089 adev->card_status = CARD_STATUS_ONLINE;
5090 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005091 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005092
Eric Laurent2bafff12016-03-17 12:17:23 -07005093 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005094 return 0;
5095}
5096
5097static struct hw_module_methods_t hal_module_methods = {
5098 .open = adev_open,
5099};
5100
5101struct audio_module HAL_MODULE_INFO_SYM = {
5102 .common = {
5103 .tag = HARDWARE_MODULE_TAG,
5104 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5105 .hal_api_version = HARDWARE_HAL_API_VERSION,
5106 .id = AUDIO_HARDWARE_MODULE_ID,
5107 .name = "QCOM Audio HAL",
5108 .author = "Code Aurora Forum",
5109 .methods = &hal_module_methods,
5110 },
5111};