blob: 47d7a0e0d33c647b213a723d83cf6b304e935a6c [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) {
Andy Hung6c1afb12017-12-22 11:34:41 -08001030 // start from 2 channels as framework currently doesn't support mono.
1031 // TODO: consider only supporting channel index masks beyond stereo here.
1032 for (channel_count = FCC_2;
1033 channel_count <= channels && num_masks < max_masks;
1034 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001035 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1036 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001037 for (channel_count = FCC_2;
1038 channel_count <= channels && num_masks < max_masks;
1039 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001040 supported_channel_masks[num_masks++] =
1041 audio_channel_mask_for_index_assignment_from_count(channel_count);
1042 }
1043 } else {
1044 // For capture we report all supported channel masks from 1 channel up.
1045 channel_count = MIN_CHANNEL_COUNT;
1046 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1047 // indexed mask
1048 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1049 supported_channel_masks[num_masks++] =
1050 audio_channel_in_mask_from_count(channel_count);
1051 }
1052 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001053#ifdef NDEBUG
1054 for (size_t i = 0; i < num_masks; ++i) {
1055 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1056 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
1057 }
1058#endif
Eric Laurent74b55762017-07-09 17:04:53 -07001059 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001060}
1061
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001062static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001063 audio_format_t *supported_formats,
1064 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001065{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001066 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001067 switch (bitwidth) {
1068 case 24:
1069 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001070 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001071 break;
1072 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001073 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001074 break;
1075 case 16:
1076 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001077 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001078 break;
1079 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001080 ALOGV("%s: %s supported format %d", __func__,
1081 is_playback ? "P" : "C", bitwidth);
1082 return 1;
1083}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001084
Haynes Mathew George569b7482017-05-08 14:44:27 -07001085static int read_usb_sup_params_and_compare(bool is_playback,
1086 audio_format_t *format,
1087 audio_format_t *supported_formats,
1088 uint32_t max_formats,
1089 audio_channel_mask_t *mask,
1090 audio_channel_mask_t *supported_channel_masks,
1091 uint32_t max_masks,
1092 uint32_t *rate,
1093 uint32_t *supported_sample_rates,
1094 uint32_t max_rates) {
1095 int ret = 0;
1096 int num_formats;
1097 int num_masks;
1098 int num_rates;
1099 int i;
1100
1101 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1102 max_formats);
1103 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1104 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001105
Haynes Mathew George569b7482017-05-08 14:44:27 -07001106 num_rates = read_usb_sup_sample_rates(is_playback,
1107 supported_sample_rates, max_rates);
1108
1109#define LUT(table, len, what, dflt) \
1110 for (i=0; i<len && (table[i] != what); i++); \
1111 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1112
1113 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1114 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1115 LUT(supported_sample_rates, num_rates, *rate, 0);
1116
1117#undef LUT
1118 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001119}
1120
Andy Hungd9653bd2017-08-01 19:31:39 -07001121static bool is_usb_ready(struct audio_device *adev, bool is_playback)
1122{
1123 // Check if usb is ready.
1124 // The usb device may have been removed quickly after insertion and hence
1125 // no longer available. This will show up as empty channel masks, or rates.
1126
1127 pthread_mutex_lock(&adev->lock);
1128 uint32_t supported_sample_rate;
1129
1130 // we consider usb ready if we can fetch at least one sample rate.
1131 const bool ready = read_usb_sup_sample_rates(
1132 is_playback, &supported_sample_rate, 1 /* max_rates */) > 0;
1133 pthread_mutex_unlock(&adev->lock);
1134 return ready;
1135}
1136
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001137static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1138{
1139 struct audio_usecase *usecase;
1140 struct listnode *node;
1141
1142 list_for_each(node, &adev->usecase_list) {
1143 usecase = node_to_item(node, struct audio_usecase, list);
1144 if (usecase->type == VOICE_CALL) {
1145 ALOGV("%s: usecase id %d", __func__, usecase->id);
1146 return usecase->id;
1147 }
1148 }
1149 return USECASE_INVALID;
1150}
1151
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001152struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1153 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001154{
1155 struct audio_usecase *usecase;
1156 struct listnode *node;
1157
1158 list_for_each(node, &adev->usecase_list) {
1159 usecase = node_to_item(node, struct audio_usecase, list);
1160 if (usecase->id == uc_id)
1161 return usecase;
1162 }
1163 return NULL;
1164}
1165
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001166int select_devices(struct audio_device *adev,
1167 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001168{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001169 snd_device_t out_snd_device = SND_DEVICE_NONE;
1170 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001171 struct audio_usecase *usecase = NULL;
1172 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001173 struct audio_usecase *hfp_usecase = NULL;
1174 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001175 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001176 int status = 0;
Eric Laurentf4520b02017-09-20 18:31:58 -07001177 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1178 USECASE_AUDIO_PLAYBACK_VOIP);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001179
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001180 usecase = get_usecase_from_list(adev, uc_id);
1181 if (usecase == NULL) {
1182 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1183 return -EINVAL;
1184 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001185
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001186 if ((usecase->type == VOICE_CALL) ||
1187 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001188 out_snd_device = platform_get_output_snd_device(adev->platform,
1189 usecase->stream.out->devices);
1190 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001191 usecase->devices = usecase->stream.out->devices;
1192 } else {
1193 /*
1194 * If the voice call is active, use the sound devices of voice call usecase
1195 * so that it would not result any device switch. All the usecases will
1196 * be switched to new device when select_devices() is called for voice call
1197 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001198 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001199 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001200 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001201 vc_usecase = get_usecase_from_list(adev,
1202 get_voice_usecase_id_from_list(adev));
1203 if ((vc_usecase != NULL) &&
1204 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1205 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001206 in_snd_device = vc_usecase->in_snd_device;
1207 out_snd_device = vc_usecase->out_snd_device;
1208 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001209 } else if (audio_extn_hfp_is_active(adev)) {
1210 hfp_ucid = audio_extn_hfp_get_usecase();
1211 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1212 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1213 in_snd_device = hfp_usecase->in_snd_device;
1214 out_snd_device = hfp_usecase->out_snd_device;
1215 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001216 }
1217 if (usecase->type == PCM_PLAYBACK) {
1218 usecase->devices = usecase->stream.out->devices;
1219 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001220 if (out_snd_device == SND_DEVICE_NONE) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001221 struct stream_out *voip_out = adev->primary_output;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001222
Eric Laurentb23d5282013-05-14 15:27:20 -07001223 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001224 usecase->stream.out->devices);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001225
1226 if (voip_usecase)
1227 voip_out = voip_usecase->stream.out;
1228
1229 if (usecase->stream.out == voip_out &&
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001230 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001231 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001232 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001233 select_devices(adev, adev->active_input->usecase);
1234 }
1235 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001236 } else if (usecase->type == PCM_CAPTURE) {
1237 usecase->devices = usecase->stream.in->device;
1238 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001239 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001240 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001241 if (adev->active_input &&
1242 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1243 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001244
1245 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1246 USECASE_AUDIO_PLAYBACK_VOIP);
1247
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001248 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001249 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1250 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001251 } else if (voip_usecase) {
1252 out_device = voip_usecase->stream.out->devices;
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001253 } else if (adev->primary_output) {
1254 out_device = adev->primary_output->devices;
1255 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001256 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001257 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001258 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001259 }
1260 }
1261
1262 if (out_snd_device == usecase->out_snd_device &&
1263 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001264 return 0;
1265 }
1266
Eric Laurent2bafff12016-03-17 12:17:23 -07001267 if (out_snd_device != SND_DEVICE_NONE &&
1268 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1269 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1270 __func__,
1271 use_case_table[uc_id],
1272 adev->last_logged_snd_device[uc_id][0],
1273 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1274 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1275 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1276 -1,
1277 out_snd_device,
1278 platform_get_snd_device_name(out_snd_device),
1279 platform_get_snd_device_acdb_id(out_snd_device));
1280 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1281 }
1282 if (in_snd_device != SND_DEVICE_NONE &&
1283 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1284 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1285 __func__,
1286 use_case_table[uc_id],
1287 adev->last_logged_snd_device[uc_id][1],
1288 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1289 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1290 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1291 -1,
1292 in_snd_device,
1293 platform_get_snd_device_name(in_snd_device),
1294 platform_get_snd_device_acdb_id(in_snd_device));
1295 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1296 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001297
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001298 /*
1299 * Limitation: While in call, to do a device switch we need to disable
1300 * and enable both RX and TX devices though one of them is same as current
1301 * device.
1302 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001303 if ((usecase->type == VOICE_CALL) &&
1304 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1305 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001306 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001307 /* Disable sidetone only if voice call already exists */
1308 if (voice_is_call_state_active(adev))
1309 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001310 }
1311
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001312 /* Disable current sound devices */
1313 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001314 disable_audio_route(adev, usecase);
1315 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001316 }
1317
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001318 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001319 disable_audio_route(adev, usecase);
1320 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001321 }
1322
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001323 /* Applicable only on the targets that has external modem.
1324 * New device information should be sent to modem before enabling
1325 * the devices to reduce in-call device switch time.
1326 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001327 if ((usecase->type == VOICE_CALL) &&
1328 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1329 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001330 status = platform_switch_voice_call_enable_device_config(adev->platform,
1331 out_snd_device,
1332 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001333 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001334
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001335 /* Enable new sound devices */
1336 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001337 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Eric Laurent99dab492017-06-17 15:19:08 -07001338 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001339 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001340 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001341 }
1342
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001343 if (in_snd_device != SND_DEVICE_NONE) {
1344 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001345 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001346 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001347
Eric Laurentb23d5282013-05-14 15:27:20 -07001348 if (usecase->type == VOICE_CALL)
1349 status = platform_switch_voice_call_device_post(adev->platform,
1350 out_snd_device,
1351 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001352
sangwoo170731f2013-06-08 15:36:36 +09001353 usecase->in_snd_device = in_snd_device;
1354 usecase->out_snd_device = out_snd_device;
1355
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001356 audio_extn_tfa_98xx_set_mode();
1357
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001358 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001359
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001360 /* Applicable only on the targets that has external modem.
1361 * Enable device command should be sent to modem only after
1362 * enabling voice call mixer controls
1363 */
vivek mehta765eb642015-08-07 19:46:06 -07001364 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001365 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1366 out_snd_device,
1367 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001368 /* Enable sidetone only if voice call already exists */
1369 if (voice_is_call_state_active(adev))
1370 voice_set_sidetone(adev, out_snd_device, true);
1371 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001372
Eric Laurentf4520b02017-09-20 18:31:58 -07001373 if (usecase == voip_usecase) {
1374 struct stream_out *voip_out = voip_usecase->stream.out;
1375 audio_extn_utils_send_app_type_gain(adev,
1376 voip_out->app_type_cfg.app_type,
1377 &voip_out->app_type_cfg.gain[0]);
1378 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001379 return status;
1380}
1381
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001382static int stop_input_stream(struct stream_in *in)
1383{
1384 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001385 struct audio_usecase *uc_info;
1386 struct audio_device *adev = in->dev;
1387
Eric Laurent994a6932013-07-17 11:51:42 -07001388 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001389 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001390
1391 if (adev->active_input) {
1392 if (adev->active_input->usecase == in->usecase) {
1393 adev->active_input = NULL;
1394 } else {
1395 ALOGW("%s adev->active_input->usecase %s, v/s in->usecase %s",
1396 __func__,
1397 use_case_table[adev->active_input->usecase],
1398 use_case_table[in->usecase]);
1399 }
1400 }
1401
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001402 uc_info = get_usecase_from_list(adev, in->usecase);
1403 if (uc_info == NULL) {
1404 ALOGE("%s: Could not find the usecase (%d) in the list",
1405 __func__, in->usecase);
1406 return -EINVAL;
1407 }
1408
vivek mehta781065c2017-04-04 12:55:01 -07001409 /* Close in-call recording streams */
1410 voice_check_and_stop_incall_rec_usecase(adev, in);
1411
Eric Laurent150dbfe2013-02-27 14:31:02 -08001412 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001413 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001414
1415 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001416 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001417
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001418 list_remove(&uc_info->list);
1419 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001420
Eric Laurent994a6932013-07-17 11:51:42 -07001421 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001422 return ret;
1423}
1424
1425int start_input_stream(struct stream_in *in)
1426{
1427 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001428 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001429 struct audio_usecase *uc_info;
1430 struct audio_device *adev = in->dev;
1431
Eric Laurent994a6932013-07-17 11:51:42 -07001432 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001433
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001434 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1435 return -EIO;
1436
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001437 if (in->card_status == CARD_STATUS_OFFLINE ||
1438 adev->card_status == CARD_STATUS_OFFLINE) {
1439 ALOGW("in->card_status or adev->card_status offline, try again");
1440 ret = -EAGAIN;
1441 goto error_config;
1442 }
1443
vivek mehta781065c2017-04-04 12:55:01 -07001444 /* Check if source matches incall recording usecase criteria */
1445 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1446 if (ret)
1447 goto error_config;
1448 else
1449 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1450
Eric Laurentb23d5282013-05-14 15:27:20 -07001451 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001452 if (in->pcm_device_id < 0) {
1453 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1454 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001455 ret = -EINVAL;
1456 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001457 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001458
1459 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001460 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1461 uc_info->id = in->usecase;
1462 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001463 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001464 uc_info->devices = in->device;
1465 uc_info->in_snd_device = SND_DEVICE_NONE;
1466 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001467
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001468 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001469
Wei Wangf4837d52017-11-21 14:51:20 -08001470 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001471 audio_extn_perf_lock_acquire();
1472
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001473 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001474
Eric Laurent0e46adf2016-12-16 12:49:24 -08001475 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001476 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001477 ALOGE("%s: pcm stream not ready", __func__);
1478 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001479 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001480 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001481 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001482 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1483 goto error_open;
1484 }
1485 } else {
1486 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1487 unsigned int pcm_open_retry_count = 0;
1488
1489 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1490 flags |= PCM_MMAP | PCM_NOIRQ;
1491 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1492 } else if (in->realtime) {
1493 flags |= PCM_MMAP | PCM_NOIRQ;
1494 }
1495
1496 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1497 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1498
1499 while (1) {
1500 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1501 flags, &in->config);
1502 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1503 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1504 if (in->pcm != NULL) {
1505 pcm_close(in->pcm);
1506 in->pcm = NULL;
1507 }
1508 if (pcm_open_retry_count-- == 0) {
1509 ret = -EIO;
1510 goto error_open;
1511 }
1512 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1513 continue;
1514 }
1515 break;
1516 }
1517
1518 ALOGV("%s: pcm_prepare", __func__);
1519 ret = pcm_prepare(in->pcm);
1520 if (ret < 0) {
1521 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001522 pcm_close(in->pcm);
1523 in->pcm = NULL;
1524 goto error_open;
1525 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001526 if (in->realtime) {
1527 ret = pcm_start(in->pcm);
1528 if (ret < 0) {
1529 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1530 pcm_close(in->pcm);
1531 in->pcm = NULL;
1532 goto error_open;
1533 }
1534 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001535 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001536 register_in_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001537 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001538 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001539 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001540
Eric Laurent0e46adf2016-12-16 12:49:24 -08001541 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001542
1543error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001544 stop_input_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001545 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001546 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001547
1548error_config:
1549 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001550 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001551 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001552}
1553
Eric Laurenta1478072015-09-21 17:21:52 -07001554void lock_input_stream(struct stream_in *in)
1555{
1556 pthread_mutex_lock(&in->pre_lock);
1557 pthread_mutex_lock(&in->lock);
1558 pthread_mutex_unlock(&in->pre_lock);
1559}
1560
1561void lock_output_stream(struct stream_out *out)
1562{
1563 pthread_mutex_lock(&out->pre_lock);
1564 pthread_mutex_lock(&out->lock);
1565 pthread_mutex_unlock(&out->pre_lock);
1566}
1567
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001568/* must be called with out->lock locked */
1569static int send_offload_cmd_l(struct stream_out* out, int command)
1570{
1571 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1572
1573 ALOGVV("%s %d", __func__, command);
1574
1575 cmd->cmd = command;
1576 list_add_tail(&out->offload_cmd_list, &cmd->node);
1577 pthread_cond_signal(&out->offload_cond);
1578 return 0;
1579}
1580
1581/* must be called iwth out->lock locked */
1582static void stop_compressed_output_l(struct stream_out *out)
1583{
1584 out->offload_state = OFFLOAD_STATE_IDLE;
1585 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001586 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001587 if (out->compr != NULL) {
1588 compress_stop(out->compr);
1589 while (out->offload_thread_blocked) {
1590 pthread_cond_wait(&out->cond, &out->lock);
1591 }
1592 }
1593}
1594
1595static void *offload_thread_loop(void *context)
1596{
1597 struct stream_out *out = (struct stream_out *) context;
1598 struct listnode *item;
1599
1600 out->offload_state = OFFLOAD_STATE_IDLE;
1601 out->playback_started = 0;
1602
1603 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1604 set_sched_policy(0, SP_FOREGROUND);
1605 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1606
1607 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001608 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001609 for (;;) {
1610 struct offload_cmd *cmd = NULL;
1611 stream_callback_event_t event;
1612 bool send_callback = false;
1613
1614 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1615 __func__, list_empty(&out->offload_cmd_list),
1616 out->offload_state);
1617 if (list_empty(&out->offload_cmd_list)) {
1618 ALOGV("%s SLEEPING", __func__);
1619 pthread_cond_wait(&out->offload_cond, &out->lock);
1620 ALOGV("%s RUNNING", __func__);
1621 continue;
1622 }
1623
1624 item = list_head(&out->offload_cmd_list);
1625 cmd = node_to_item(item, struct offload_cmd, node);
1626 list_remove(item);
1627
1628 ALOGVV("%s STATE %d CMD %d out->compr %p",
1629 __func__, out->offload_state, cmd->cmd, out->compr);
1630
1631 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1632 free(cmd);
1633 break;
1634 }
1635
1636 if (out->compr == NULL) {
1637 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001638 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001639 pthread_cond_signal(&out->cond);
1640 continue;
1641 }
1642 out->offload_thread_blocked = true;
1643 pthread_mutex_unlock(&out->lock);
1644 send_callback = false;
1645 switch(cmd->cmd) {
1646 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1647 compress_wait(out->compr, -1);
1648 send_callback = true;
1649 event = STREAM_CBK_EVENT_WRITE_READY;
1650 break;
1651 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001652 compress_next_track(out->compr);
1653 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001654 send_callback = true;
1655 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001656 /* Resend the metadata for next iteration */
1657 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001658 break;
1659 case OFFLOAD_CMD_DRAIN:
1660 compress_drain(out->compr);
1661 send_callback = true;
1662 event = STREAM_CBK_EVENT_DRAIN_READY;
1663 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001664 case OFFLOAD_CMD_ERROR:
1665 send_callback = true;
1666 event = STREAM_CBK_EVENT_ERROR;
1667 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001668 default:
1669 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1670 break;
1671 }
Eric Laurenta1478072015-09-21 17:21:52 -07001672 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001673 out->offload_thread_blocked = false;
1674 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001675 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001676 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001677 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001678 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001679 free(cmd);
1680 }
1681
1682 pthread_cond_signal(&out->cond);
1683 while (!list_empty(&out->offload_cmd_list)) {
1684 item = list_head(&out->offload_cmd_list);
1685 list_remove(item);
1686 free(node_to_item(item, struct offload_cmd, node));
1687 }
1688 pthread_mutex_unlock(&out->lock);
1689
1690 return NULL;
1691}
1692
1693static int create_offload_callback_thread(struct stream_out *out)
1694{
1695 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1696 list_init(&out->offload_cmd_list);
1697 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1698 offload_thread_loop, out);
1699 return 0;
1700}
1701
1702static int destroy_offload_callback_thread(struct stream_out *out)
1703{
Eric Laurenta1478072015-09-21 17:21:52 -07001704 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001705 stop_compressed_output_l(out);
1706 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1707
1708 pthread_mutex_unlock(&out->lock);
1709 pthread_join(out->offload_thread, (void **) NULL);
1710 pthread_cond_destroy(&out->offload_cond);
1711
1712 return 0;
1713}
1714
Eric Laurent07eeafd2013-10-06 12:52:49 -07001715static bool allow_hdmi_channel_config(struct audio_device *adev)
1716{
1717 struct listnode *node;
1718 struct audio_usecase *usecase;
1719 bool ret = true;
1720
1721 list_for_each(node, &adev->usecase_list) {
1722 usecase = node_to_item(node, struct audio_usecase, list);
1723 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1724 /*
1725 * If voice call is already existing, do not proceed further to avoid
1726 * disabling/enabling both RX and TX devices, CSD calls, etc.
1727 * Once the voice call done, the HDMI channels can be configured to
1728 * max channels of remaining use cases.
1729 */
1730 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001731 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001732 __func__);
1733 ret = false;
1734 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001735 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1736 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001737 "no change in HDMI channels", __func__);
1738 ret = false;
1739 break;
1740 }
1741 }
1742 }
1743 return ret;
1744}
1745
1746static int check_and_set_hdmi_channels(struct audio_device *adev,
1747 unsigned int channels)
1748{
1749 struct listnode *node;
1750 struct audio_usecase *usecase;
1751
1752 /* Check if change in HDMI channel config is allowed */
1753 if (!allow_hdmi_channel_config(adev))
1754 return 0;
1755
1756 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001757 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001758 return 0;
1759 }
1760
1761 platform_set_hdmi_channels(adev->platform, channels);
1762 adev->cur_hdmi_channels = channels;
1763
1764 /*
1765 * Deroute all the playback streams routed to HDMI so that
1766 * the back end is deactivated. Note that backend will not
1767 * be deactivated if any one stream is connected to it.
1768 */
1769 list_for_each(node, &adev->usecase_list) {
1770 usecase = node_to_item(node, struct audio_usecase, list);
1771 if (usecase->type == PCM_PLAYBACK &&
1772 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001773 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001774 }
1775 }
1776
1777 /*
1778 * Enable all the streams disabled above. Now the HDMI backend
1779 * will be activated with new channel configuration
1780 */
1781 list_for_each(node, &adev->usecase_list) {
1782 usecase = node_to_item(node, struct audio_usecase, list);
1783 if (usecase->type == PCM_PLAYBACK &&
1784 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001785 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001786 }
1787 }
1788
1789 return 0;
1790}
1791
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001792static int stop_output_stream(struct stream_out *out)
1793{
1794 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001795 struct audio_usecase *uc_info;
1796 struct audio_device *adev = out->dev;
1797
Eric Laurent994a6932013-07-17 11:51:42 -07001798 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001799 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001800 uc_info = get_usecase_from_list(adev, out->usecase);
1801 if (uc_info == NULL) {
1802 ALOGE("%s: Could not find the usecase (%d) in the list",
1803 __func__, out->usecase);
1804 return -EINVAL;
1805 }
1806
Haynes Mathew George41f86652014-06-17 14:22:15 -07001807 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1808 if (adev->visualizer_stop_output != NULL)
1809 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1810 if (adev->offload_effects_stop_output != NULL)
1811 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08001812 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
1813 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
1814 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07001815 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001816
Eric Laurent150dbfe2013-02-27 14:31:02 -08001817 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001818 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001819
1820 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001821 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001822
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001823 list_remove(&uc_info->list);
1824 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001825
Eric Laurent0499d4f2014-08-25 22:39:29 -05001826 audio_extn_extspk_update(adev->extspk);
1827
Eric Laurent07eeafd2013-10-06 12:52:49 -07001828 /* Must be called after removing the usecase from list */
1829 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1830 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07001831 else if (out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
1832 struct listnode *node;
1833 struct audio_usecase *usecase;
1834 list_for_each(node, &adev->usecase_list) {
1835 usecase = node_to_item(node, struct audio_usecase, list);
1836 if (usecase->devices & AUDIO_DEVICE_OUT_SPEAKER)
1837 select_devices(adev, usecase->id);
1838 }
1839 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001840
Eric Laurent994a6932013-07-17 11:51:42 -07001841 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001842 return ret;
1843}
1844
1845int start_output_stream(struct stream_out *out)
1846{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001847 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001848 struct audio_usecase *uc_info;
1849 struct audio_device *adev = out->dev;
1850
Eric Laurent994a6932013-07-17 11:51:42 -07001851 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001852 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001853
1854 if (out->card_status == CARD_STATUS_OFFLINE ||
1855 adev->card_status == CARD_STATUS_OFFLINE) {
1856 ALOGW("out->card_status or adev->card_status offline, try again");
1857 ret = -EAGAIN;
1858 goto error_config;
1859 }
1860
Eric Laurentb23d5282013-05-14 15:27:20 -07001861 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001862 if (out->pcm_device_id < 0) {
1863 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1864 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001865 ret = -EINVAL;
1866 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001867 }
1868
1869 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1870 uc_info->id = out->usecase;
1871 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001872 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001873 uc_info->devices = out->devices;
1874 uc_info->in_snd_device = SND_DEVICE_NONE;
1875 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001876
Eric Laurent07eeafd2013-10-06 12:52:49 -07001877 /* This must be called before adding this usecase to the list */
1878 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1879 check_and_set_hdmi_channels(adev, out->config.channels);
1880
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001881 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001882
Wei Wangf4837d52017-11-21 14:51:20 -08001883 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001884 audio_extn_perf_lock_acquire();
1885
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001886 select_devices(adev, out->usecase);
1887
Eric Laurent0499d4f2014-08-25 22:39:29 -05001888 audio_extn_extspk_update(adev->extspk);
1889
Andy Hung31aca912014-03-20 17:14:59 -07001890 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001891 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001892 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1893 out->pcm = NULL;
1894 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1895 COMPRESS_IN, &out->compr_config);
1896 if (out->compr && !is_compress_ready(out->compr)) {
1897 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1898 compress_close(out->compr);
1899 out->compr = NULL;
1900 ret = -EIO;
1901 goto error_open;
1902 }
1903 if (out->offload_callback)
1904 compress_nonblock(out->compr, out->non_blocking);
1905
1906 if (adev->visualizer_start_output != NULL)
1907 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1908 if (adev->offload_effects_start_output != NULL)
1909 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
1910 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001911 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001912 ALOGE("%s: pcm stream not ready", __func__);
1913 goto error_open;
1914 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001915 ret = pcm_start(out->pcm);
1916 if (ret < 0) {
1917 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1918 goto error_open;
1919 }
1920 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07001921 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001922 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001923
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001924 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1925 flags |= PCM_MMAP | PCM_NOIRQ;
1926 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001927 } else if (out->realtime) {
1928 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07001929 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001930
1931 while (1) {
1932 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1933 flags, &out->config);
1934 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1935 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1936 if (out->pcm != NULL) {
1937 pcm_close(out->pcm);
1938 out->pcm = NULL;
1939 }
1940 if (pcm_open_retry_count-- == 0) {
1941 ret = -EIO;
1942 goto error_open;
1943 }
1944 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1945 continue;
1946 }
1947 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001948 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001949 ALOGV("%s: pcm_prepare", __func__);
1950 if (pcm_is_ready(out->pcm)) {
1951 ret = pcm_prepare(out->pcm);
1952 if (ret < 0) {
1953 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1954 pcm_close(out->pcm);
1955 out->pcm = NULL;
1956 goto error_open;
1957 }
1958 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001959 if (out->realtime) {
1960 ret = pcm_start(out->pcm);
1961 if (ret < 0) {
1962 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1963 pcm_close(out->pcm);
1964 out->pcm = NULL;
1965 goto error_open;
1966 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001967 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001968 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001969 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08001970 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001971 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001972 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07001973
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08001974 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
1975 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
1976 audio_low_latency_hint_start();
1977 }
1978
vivek mehtae59cfb22017-06-16 15:57:11 -07001979 // consider a scenario where on pause lower layers are tear down.
1980 // so on resume, swap mixer control need to be sent only when
1981 // backend is active, hence rather than sending from enable device
1982 // sending it from start of streamtream
1983
1984 platform_set_swap_channels(adev, true);
1985
Eric Laurent994a6932013-07-17 11:51:42 -07001986 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001987 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001988error_open:
Wei Wangf4837d52017-11-21 14:51:20 -08001989 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001990 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001991 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001992error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001993 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001994}
1995
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001996static int check_input_parameters(uint32_t sample_rate,
1997 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07001998 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001999{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002000 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2001 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002002 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2003 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002004 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2005 return -EINVAL;
2006 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002007
Eric Laurent74b55762017-07-09 17:04:53 -07002008 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2009 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002010 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002011 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002012 return -EINVAL;
2013 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002014
2015 switch (sample_rate) {
2016 case 8000:
2017 case 11025:
2018 case 12000:
2019 case 16000:
2020 case 22050:
2021 case 24000:
2022 case 32000:
2023 case 44100:
2024 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002025 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002026 break;
2027 default:
vivek mehtadae44712015-07-27 14:13:18 -07002028 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002029 return -EINVAL;
2030 }
2031
2032 return 0;
2033}
2034
vivek mehtaa68fea62017-06-08 19:04:02 -07002035static size_t get_stream_buffer_size(size_t duration_ms,
2036 uint32_t sample_rate,
2037 audio_format_t format,
2038 int channel_count,
2039 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002040{
2041 size_t size = 0;
2042
vivek mehtaa68fea62017-06-08 19:04:02 -07002043 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002044 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002045 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002046
2047 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002048
Glenn Kasten4f993392014-05-14 07:30:48 -07002049 /* make sure the size is multiple of 32 bytes
2050 * At 48 kHz mono 16-bit PCM:
2051 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2052 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2053 */
2054 size += 0x1f;
2055 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002056
2057 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002058}
2059
2060static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2061{
2062 struct stream_out *out = (struct stream_out *)stream;
2063
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002064 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002065}
2066
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002067static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002068{
2069 return -ENOSYS;
2070}
2071
2072static size_t out_get_buffer_size(const struct audio_stream *stream)
2073{
2074 struct stream_out *out = (struct stream_out *)stream;
2075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002076 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2077 return out->compr_config.fragment_size;
2078 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002079 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002080 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002081}
2082
2083static uint32_t out_get_channels(const struct audio_stream *stream)
2084{
2085 struct stream_out *out = (struct stream_out *)stream;
2086
2087 return out->channel_mask;
2088}
2089
2090static audio_format_t out_get_format(const struct audio_stream *stream)
2091{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002092 struct stream_out *out = (struct stream_out *)stream;
2093
2094 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002095}
2096
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002097static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002098{
2099 return -ENOSYS;
2100}
2101
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002102/* must be called with out->lock locked */
2103static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002104{
2105 struct stream_out *out = (struct stream_out *)stream;
2106 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002107 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002108
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002109 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002110 if (adev->adm_deregister_stream)
2111 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002112 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002113 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002114 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2115 if (out->pcm) {
2116 pcm_close(out->pcm);
2117 out->pcm = NULL;
2118 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002119 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002120 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002121 out->playback_started = false;
2122 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002123 } else {
2124 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002125 out->gapless_mdata.encoder_delay = 0;
2126 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002127 if (out->compr != NULL) {
2128 compress_close(out->compr);
2129 out->compr = NULL;
2130 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002131 }
Phil Burkbc991042017-02-24 08:06:44 -08002132 if (do_stop) {
2133 stop_output_stream(out);
2134 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002135 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002136 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002137 return 0;
2138}
2139
2140static int out_standby(struct audio_stream *stream)
2141{
2142 struct stream_out *out = (struct stream_out *)stream;
2143
2144 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2145 out->usecase, use_case_table[out->usecase]);
2146
2147 lock_output_stream(out);
2148 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002149 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002150 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002151 return 0;
2152}
2153
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002154static int out_on_error(struct audio_stream *stream)
2155{
2156 struct stream_out *out = (struct stream_out *)stream;
2157 struct audio_device *adev = out->dev;
2158 bool do_standby = false;
2159
2160 lock_output_stream(out);
2161 if (!out->standby) {
2162 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2163 stop_compressed_output_l(out);
2164 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2165 } else
2166 do_standby = true;
2167 }
2168 pthread_mutex_unlock(&out->lock);
2169
2170 if (do_standby)
2171 return out_standby(&out->stream.common);
2172
2173 return 0;
2174}
2175
Andy Hung7401c7c2016-09-21 12:41:21 -07002176static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002177{
Andy Hung7401c7c2016-09-21 12:41:21 -07002178 struct stream_out *out = (struct stream_out *)stream;
2179
2180 // We try to get the lock for consistency,
2181 // but it isn't necessary for these variables.
2182 // If we're not in standby, we may be blocked on a write.
2183 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2184 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2185 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2186
2187 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002188 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002189 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002190
2191 // dump error info
2192 (void)error_log_dump(
2193 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002194
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002195 return 0;
2196}
2197
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002198static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2199{
2200 int ret = 0;
2201 char value[32];
2202 struct compr_gapless_mdata tmp_mdata;
2203
2204 if (!out || !parms) {
2205 return -EINVAL;
2206 }
2207
2208 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2209 if (ret >= 0) {
2210 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2211 } else {
2212 return -EINVAL;
2213 }
2214
2215 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2216 if (ret >= 0) {
2217 tmp_mdata.encoder_padding = atoi(value);
2218 } else {
2219 return -EINVAL;
2220 }
2221
2222 out->gapless_mdata = tmp_mdata;
2223 out->send_new_metadata = 1;
2224 ALOGV("%s new encoder delay %u and padding %u", __func__,
2225 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2226
2227 return 0;
2228}
2229
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002230static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2231{
2232 return out == adev->primary_output || out == adev->voice_tx_output;
2233}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002234
Kevin Rocard1e02c882017-08-09 15:26:07 -07002235static int get_alive_usb_card(struct str_parms* parms) {
2236 int card;
2237 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2238 !audio_extn_usb_alive(card)) {
2239 return card;
2240 }
2241 return -ENODEV;
2242}
2243
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002244static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2245{
2246 struct stream_out *out = (struct stream_out *)stream;
2247 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002248 struct audio_usecase *usecase;
2249 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002250 struct str_parms *parms;
2251 char value[32];
2252 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002253 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002254 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002255
Eric Laurent2e140aa2016-06-30 17:14:46 -07002256 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002257 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002258 parms = str_parms_create_str(kvpairs);
2259 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2260 if (ret >= 0) {
2261 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002262
Eric Laurenta1478072015-09-21 17:21:52 -07002263 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002264
2265 // The usb driver needs to be closed after usb device disconnection
2266 // otherwise audio is no longer played on the new usb devices.
2267 // By forcing the stream in standby, the usb stack refcount drops to 0
2268 // and the driver is closed.
2269 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD && val == AUDIO_DEVICE_NONE &&
2270 audio_is_usb_out_device(out->devices)) {
2271 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2272 out_standby_l(&out->stream.common);
2273 }
2274
Eric Laurent150dbfe2013-02-27 14:31:02 -08002275 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002276
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002277 /*
2278 * When HDMI cable is unplugged the music playback is paused and
2279 * the policy manager sends routing=0. But the audioflinger
2280 * continues to write data until standby time (3sec).
2281 * As the HDMI core is turned off, the write gets blocked.
2282 * Avoid this by routing audio to speaker until standby.
2283 */
2284 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2285 val == AUDIO_DEVICE_NONE) {
2286 val = AUDIO_DEVICE_OUT_SPEAKER;
2287 }
2288
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002289 audio_devices_t new_dev = val;
2290
2291 // Workaround: If routing to an non existing usb device, fail gracefully
2292 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002293 int card;
2294 if (audio_is_usb_out_device(new_dev) &&
2295 (card = get_alive_usb_card(parms)) >= 0) {
2296
2297 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002298 pthread_mutex_unlock(&adev->lock);
2299 pthread_mutex_unlock(&out->lock);
2300 status = -ENOSYS;
2301 goto routing_fail;
2302 }
2303
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002304 /*
2305 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002306 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002307 * the select_devices(). But how do we undo this?
2308 *
2309 * For example, music playback is active on headset (deep-buffer usecase)
2310 * and if we go to ringtones and select a ringtone, low-latency usecase
2311 * will be started on headset+speaker. As we can't enable headset+speaker
2312 * and headset devices at the same time, select_devices() switches the music
2313 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2314 * So when the ringtone playback is completed, how do we undo the same?
2315 *
2316 * We are relying on the out_set_parameters() call on deep-buffer output,
2317 * once the ringtone playback is ended.
2318 * NOTE: We should not check if the current devices are same as new devices.
2319 * Because select_devices() must be called to switch back the music
2320 * playback to headset.
2321 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002322 if (new_dev != AUDIO_DEVICE_NONE) {
2323 bool same_dev = out->devices == new_dev;
2324 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002325
Eric Laurenta7657192014-10-09 21:09:33 -07002326 if (output_drives_call(adev, out)) {
2327 if (!voice_is_in_call(adev)) {
2328 if (adev->mode == AUDIO_MODE_IN_CALL) {
2329 adev->current_call_output = out;
2330 ret = voice_start_call(adev);
2331 }
2332 } else {
2333 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002334 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002335 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002336 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002337
2338 if (!out->standby) {
2339 if (!same_dev) {
2340 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002341 // inform adm before actual routing to prevent glitches.
2342 if (adev->adm_on_routing_change) {
2343 adev->adm_on_routing_change(adev->adm_data,
2344 out->handle);
2345 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002346 }
2347 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002348 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002349
2350 // on device switch force swap, lower functions will make sure
2351 // to check if swap is allowed or not.
2352
2353 if (!same_dev)
2354 platform_set_swap_channels(adev, true);
vivek mehta0d3637a2016-07-24 09:32:02 -07002355 }
2356
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002357 }
2358
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002359 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002360 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002361
2362 /*handles device and call state changes*/
2363 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002364 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002365 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002366
2367 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2368 parse_compress_metadata(out, parms);
2369 }
2370
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002371 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002372 ALOGV("%s: exit: code(%d)", __func__, status);
2373 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002374}
2375
Haynes Mathew George569b7482017-05-08 14:44:27 -07002376static bool stream_get_parameter_channels(struct str_parms *query,
2377 struct str_parms *reply,
2378 audio_channel_mask_t *supported_channel_masks) {
2379 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002380 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002381 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002382 size_t i, j;
2383
2384 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2385 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002386 value[0] = '\0';
2387 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002388 while (supported_channel_masks[i] != 0) {
2389 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2390 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002391 if (!first) {
2392 strcat(value, "|");
2393 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002394 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002395 first = false;
2396 break;
2397 }
2398 }
2399 i++;
2400 }
2401 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002402 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002403 return ret >= 0;
2404}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002405
Haynes Mathew George569b7482017-05-08 14:44:27 -07002406static bool stream_get_parameter_formats(struct str_parms *query,
2407 struct str_parms *reply,
2408 audio_format_t *supported_formats) {
2409 int ret = -1;
2410 char value[256];
2411 int i;
2412
2413 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2414 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002415 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002416 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002417 case AUDIO_FORMAT_PCM_16_BIT:
2418 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2419 break;
2420 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2421 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2422 break;
2423 case AUDIO_FORMAT_PCM_32_BIT:
2424 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2425 break;
2426 default:
2427 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002428 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002429 break;
2430 }
2431 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002432 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002433 return ret >= 0;
2434}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002435
Haynes Mathew George569b7482017-05-08 14:44:27 -07002436static bool stream_get_parameter_rates(struct str_parms *query,
2437 struct str_parms *reply,
2438 uint32_t *supported_sample_rates) {
2439
2440 int i;
2441 char value[256];
2442 int ret = -1;
2443 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2444 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002445 value[0] = '\0';
2446 i=0;
2447 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002448 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002449 int avail = sizeof(value) - cursor;
2450 ret = snprintf(value + cursor, avail, "%s%d",
2451 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002452 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002453 if (ret < 0 || ret >= avail) {
2454 // if cursor is at the last element of the array
2455 // overwrite with \0 is duplicate work as
2456 // snprintf already put a \0 in place.
2457 // else
2458 // we had space to write the '|' at value[cursor]
2459 // (which will be overwritten) or no space to fill
2460 // the first element (=> cursor == 0)
2461 value[cursor] = '\0';
2462 break;
2463 }
2464 cursor += ret;
2465 ++i;
2466 }
2467 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2468 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002469 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002470 return ret >= 0;
2471}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002472
Haynes Mathew George569b7482017-05-08 14:44:27 -07002473static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2474{
2475 struct stream_out *out = (struct stream_out *)stream;
2476 struct str_parms *query = str_parms_create_str(keys);
2477 char *str;
2478 struct str_parms *reply = str_parms_create();
2479 bool replied = false;
2480 ALOGV("%s: enter: keys - %s", __func__, keys);
2481
2482 replied |= stream_get_parameter_channels(query, reply,
2483 &out->supported_channel_masks[0]);
2484 replied |= stream_get_parameter_formats(query, reply,
2485 &out->supported_formats[0]);
2486 replied |= stream_get_parameter_rates(query, reply,
2487 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002488 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002489 str = str_parms_to_str(reply);
2490 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002491 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002492 }
2493 str_parms_destroy(query);
2494 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002495 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002496 return str;
2497}
2498
2499static uint32_t out_get_latency(const struct audio_stream_out *stream)
2500{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002501 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002502 struct stream_out *out = (struct stream_out *)stream;
2503
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002504 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2505 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002506 else if ((out->realtime) ||
2507 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002508 // since the buffer won't be filled up faster than realtime,
2509 // return a smaller number
2510 period_ms = (out->af_period_multiplier * out->config.period_size *
2511 1000) / (out->config.rate);
2512 hw_delay = platform_render_latency(out->usecase)/1000;
2513 return period_ms + hw_delay;
2514 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002515
2516 return (out->config.period_count * out->config.period_size * 1000) /
2517 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002518}
2519
2520static int out_set_volume(struct audio_stream_out *stream, float left,
2521 float right)
2522{
Eric Laurenta9024de2013-04-04 09:19:12 -07002523 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002524 int volume[2];
2525
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002526 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002527 /* only take left channel into account: the API is for stereo anyway */
2528 out->muted = (left == 0.0f);
2529 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002530 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2531 const char *mixer_ctl_name = "Compress Playback Volume";
2532 struct audio_device *adev = out->dev;
2533 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002534 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2535 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002536 /* try with the control based on device id */
2537 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2538 PCM_PLAYBACK);
2539 char ctl_name[128] = {0};
2540 snprintf(ctl_name, sizeof(ctl_name),
2541 "Compress Playback %d Volume", pcm_device_id);
2542 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2543 if (!ctl) {
2544 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2545 return -EINVAL;
2546 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002547 }
2548 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2549 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2550 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2551 return 0;
vivek mehtaa68fea62017-06-08 19:04:02 -07002552 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002553 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2554 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2555 if (!out->standby) {
2556 // if in standby, cached volume will be sent after stream is opened
2557 audio_extn_utils_send_app_type_gain(out->dev,
2558 out->app_type_cfg.app_type,
2559 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002560 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002561 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002562 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002563
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002564 return -ENOSYS;
2565}
2566
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002567// note: this call is safe only if the stream_cb is
2568// removed first in close_output_stream (as is done now).
2569static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2570{
2571 if (!stream || !parms)
2572 return;
2573
2574 struct stream_out *out = (struct stream_out *)stream;
2575 struct audio_device *adev = out->dev;
2576
2577 card_status_t status;
2578 int card;
2579 if (parse_snd_card_status(parms, &card, &status) < 0)
2580 return;
2581
2582 pthread_mutex_lock(&adev->lock);
2583 bool valid_cb = (card == adev->snd_card);
2584 pthread_mutex_unlock(&adev->lock);
2585
2586 if (!valid_cb)
2587 return;
2588
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002589 lock_output_stream(out);
2590 if (out->card_status != status)
2591 out->card_status = status;
2592 pthread_mutex_unlock(&out->lock);
2593
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002594 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2595 use_case_table[out->usecase],
2596 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2597
2598 if (status == CARD_STATUS_OFFLINE)
2599 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002600
2601 return;
2602}
2603
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002604#ifdef NO_AUDIO_OUT
2605static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002606 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002607{
2608 struct stream_out *out = (struct stream_out *)stream;
2609
2610 /* No Output device supported other than BT for playback.
2611 * Sleep for the amount of buffer duration
2612 */
Eric Laurenta1478072015-09-21 17:21:52 -07002613 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002614 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2615 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002616 out_get_sample_rate(&out->stream.common));
2617 pthread_mutex_unlock(&out->lock);
2618 return bytes;
2619}
2620#endif
2621
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002622static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2623 size_t bytes)
2624{
2625 struct stream_out *out = (struct stream_out *)stream;
2626 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002627 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002628 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002629
Eric Laurenta1478072015-09-21 17:21:52 -07002630 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002631 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07002632 const size_t frame_size = audio_stream_out_frame_size(stream);
2633 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002634
Eric Laurent0e46adf2016-12-16 12:49:24 -08002635 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2636 error_code = ERROR_CODE_WRITE;
2637 goto exit;
2638 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002639 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002640 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002641 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002642 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07002643
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002644 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002645 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002646 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07002647 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002648 goto exit;
2649 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002650
vivek mehta40125092017-08-21 18:48:51 -07002651 // after standby always force set last known cal step
2652 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
2653 ALOGD("%s: retry previous failed cal level set", __func__);
2654 send_gain_dep_calibration_l();
2655 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002656 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002657
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002658 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002659 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002660 if (out->send_new_metadata) {
2661 ALOGVV("send new gapless metadata");
2662 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2663 out->send_new_metadata = 0;
2664 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002665 unsigned int avail;
2666 struct timespec tstamp;
2667 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2668 /* Do not limit write size if the available frames count is unknown */
2669 if (ret != 0) {
2670 avail = bytes;
2671 }
2672 if (avail == 0) {
2673 ret = 0;
2674 } else {
2675 if (avail > bytes) {
2676 avail = bytes;
2677 }
2678 ret = compress_write(out->compr, buffer, avail);
2679 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2680 __func__, avail, ret);
2681 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002682
Eric Laurent6e895242013-09-05 16:10:57 -07002683 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002684 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2685 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002686 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002687 compress_start(out->compr);
2688 out->playback_started = 1;
2689 out->offload_state = OFFLOAD_STATE_PLAYING;
2690 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002691 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002692 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002693 } else {
2694 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002695 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002696 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002697 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002698 return ret;
2699 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002700 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002701 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07002702 size_t bytes_to_write = bytes;
2703
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002704 if (out->muted)
2705 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07002706 // FIXME: this can be removed once audio flinger mixer supports mono output
2707 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
2708 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
2709 int16_t *src = (int16_t *)buffer;
2710 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002711
Eric Laurentad2dde92017-09-20 18:27:31 -07002712 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
2713 out->format != AUDIO_FORMAT_PCM_16_BIT,
2714 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002715
Eric Laurentad2dde92017-09-20 18:27:31 -07002716 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
2717 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
2718 }
2719 bytes_to_write /= 2;
2720 }
2721 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes_to_write);
2722
2723 long ns = (frames * NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002724 request_out_focus(out, ns);
2725
2726 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2727 if (use_mmap)
Eric Laurentad2dde92017-09-20 18:27:31 -07002728 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002729 else
Eric Laurentad2dde92017-09-20 18:27:31 -07002730 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002731
Haynes Mathew George03c40102016-01-29 17:57:48 -08002732 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002733 } else {
2734 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002735 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002736 }
2737
2738exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002739 // For PCM we always consume the buffer and return #bytes regardless of ret.
2740 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07002741 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07002742 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002743 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07002744
Andy Hung7401c7c2016-09-21 12:41:21 -07002745 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07002746 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07002747 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2748 ALOGE_IF(out->pcm != NULL,
2749 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07002750 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002751 // usleep not guaranteed for values over 1 second but we don't limit here.
2752 }
2753 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002754
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002755 pthread_mutex_unlock(&out->lock);
2756
2757 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002758 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002759 if (sleeptime_us != 0)
2760 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002761 }
2762 return bytes;
2763}
2764
2765static int out_get_render_position(const struct audio_stream_out *stream,
2766 uint32_t *dsp_frames)
2767{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002768 struct stream_out *out = (struct stream_out *)stream;
2769 *dsp_frames = 0;
2770 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002771 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002772 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002773 unsigned long frames = 0;
2774 // TODO: check return value
2775 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2776 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002777 ALOGVV("%s rendered frames %d sample_rate %d",
2778 __func__, *dsp_frames, out->sample_rate);
2779 }
2780 pthread_mutex_unlock(&out->lock);
2781 return 0;
2782 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002783 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002784}
2785
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002786static int out_add_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_remove_audio_effect(const struct audio_stream *stream __unused,
2793 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002794{
2795 return 0;
2796}
2797
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002798static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2799 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002800{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002801 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002802}
2803
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002804static int out_get_presentation_position(const struct audio_stream_out *stream,
2805 uint64_t *frames, struct timespec *timestamp)
2806{
2807 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002808 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07002809 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002810
Eric Laurenta1478072015-09-21 17:21:52 -07002811 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002812
Eric Laurent949a0892013-09-20 09:20:13 -07002813 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2814 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002815 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002816 compress_get_tstamp(out->compr, &dsp_frames,
2817 &out->sample_rate);
2818 ALOGVV("%s rendered frames %ld sample_rate %d",
2819 __func__, dsp_frames, out->sample_rate);
2820 *frames = dsp_frames;
2821 ret = 0;
2822 /* this is the best we can do */
2823 clock_gettime(CLOCK_MONOTONIC, timestamp);
2824 }
2825 } else {
2826 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002827 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002828 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2829 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002830 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002831 // This adjustment accounts for buffering after app processor.
2832 // It is based on estimated DSP latency per use case, rather than exact.
2833 signed_frames -=
2834 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2835
Eric Laurent949a0892013-09-20 09:20:13 -07002836 // It would be unusual for this value to be negative, but check just in case ...
2837 if (signed_frames >= 0) {
2838 *frames = signed_frames;
2839 ret = 0;
2840 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002841 }
2842 }
2843 }
2844
2845 pthread_mutex_unlock(&out->lock);
2846
2847 return ret;
2848}
2849
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002850static int out_set_callback(struct audio_stream_out *stream,
2851 stream_callback_t callback, void *cookie)
2852{
2853 struct stream_out *out = (struct stream_out *)stream;
2854
2855 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002856 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002857 out->offload_callback = callback;
2858 out->offload_cookie = cookie;
2859 pthread_mutex_unlock(&out->lock);
2860 return 0;
2861}
2862
2863static int out_pause(struct audio_stream_out* stream)
2864{
2865 struct stream_out *out = (struct stream_out *)stream;
2866 int status = -ENOSYS;
2867 ALOGV("%s", __func__);
2868 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002869 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002870 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2871 status = compress_pause(out->compr);
2872 out->offload_state = OFFLOAD_STATE_PAUSED;
2873 }
2874 pthread_mutex_unlock(&out->lock);
2875 }
2876 return status;
2877}
2878
2879static int out_resume(struct audio_stream_out* stream)
2880{
2881 struct stream_out *out = (struct stream_out *)stream;
2882 int status = -ENOSYS;
2883 ALOGV("%s", __func__);
2884 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2885 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002886 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002887 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2888 status = compress_resume(out->compr);
2889 out->offload_state = OFFLOAD_STATE_PLAYING;
2890 }
2891 pthread_mutex_unlock(&out->lock);
2892 }
2893 return status;
2894}
2895
2896static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2897{
2898 struct stream_out *out = (struct stream_out *)stream;
2899 int status = -ENOSYS;
2900 ALOGV("%s", __func__);
2901 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002902 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002903 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2904 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2905 else
2906 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2907 pthread_mutex_unlock(&out->lock);
2908 }
2909 return status;
2910}
2911
2912static int out_flush(struct audio_stream_out* stream)
2913{
2914 struct stream_out *out = (struct stream_out *)stream;
2915 ALOGV("%s", __func__);
2916 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002917 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002918 stop_compressed_output_l(out);
2919 pthread_mutex_unlock(&out->lock);
2920 return 0;
2921 }
2922 return -ENOSYS;
2923}
2924
Eric Laurent0e46adf2016-12-16 12:49:24 -08002925static int out_stop(const struct audio_stream_out* stream)
2926{
2927 struct stream_out *out = (struct stream_out *)stream;
2928 struct audio_device *adev = out->dev;
2929 int ret = -ENOSYS;
2930
2931 ALOGV("%s", __func__);
2932 pthread_mutex_lock(&adev->lock);
2933 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2934 out->playback_started && out->pcm != NULL) {
2935 pcm_stop(out->pcm);
2936 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08002937 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002938 }
2939 pthread_mutex_unlock(&adev->lock);
2940 return ret;
2941}
2942
2943static int out_start(const struct audio_stream_out* stream)
2944{
2945 struct stream_out *out = (struct stream_out *)stream;
2946 struct audio_device *adev = out->dev;
2947 int ret = -ENOSYS;
2948
2949 ALOGV("%s", __func__);
2950 pthread_mutex_lock(&adev->lock);
2951 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2952 !out->playback_started && out->pcm != NULL) {
2953 ret = start_output_stream(out);
2954 if (ret == 0) {
2955 out->playback_started = true;
2956 }
2957 }
2958 pthread_mutex_unlock(&adev->lock);
2959 return ret;
2960}
2961
Phil Burkbc991042017-02-24 08:06:44 -08002962/*
2963 * Modify config->period_count based on min_size_frames
2964 */
2965static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
2966{
2967 int periodCountRequested = (min_size_frames + config->period_size - 1)
2968 / config->period_size;
2969 int periodCount = MMAP_PERIOD_COUNT_MIN;
2970
2971 ALOGV("%s original config.period_size = %d config.period_count = %d",
2972 __func__, config->period_size, config->period_count);
2973
2974 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
2975 periodCount *= 2;
2976 }
2977 config->period_count = periodCount;
2978
2979 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
2980}
2981
Eric Laurent0e46adf2016-12-16 12:49:24 -08002982static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2983 int32_t min_size_frames,
2984 struct audio_mmap_buffer_info *info)
2985{
2986 struct stream_out *out = (struct stream_out *)stream;
2987 struct audio_device *adev = out->dev;
2988 int ret = 0;
2989 unsigned int offset1;
2990 unsigned int frames1;
2991 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07002992 uint32_t mmap_size;
2993 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002994
2995 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08002996 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002997 pthread_mutex_lock(&adev->lock);
2998
2999 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003000 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003001 ret = -EINVAL;
3002 goto exit;
3003 }
3004 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003005 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003006 ret = -ENOSYS;
3007 goto exit;
3008 }
3009 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3010 if (out->pcm_device_id < 0) {
3011 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3012 __func__, out->pcm_device_id, out->usecase);
3013 ret = -EINVAL;
3014 goto exit;
3015 }
Phil Burkbc991042017-02-24 08:06:44 -08003016
3017 adjust_mmap_period_count(&out->config, min_size_frames);
3018
Eric Laurent0e46adf2016-12-16 12:49:24 -08003019 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3020 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3021 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3022 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3023 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3024 step = "open";
3025 ret = -ENODEV;
3026 goto exit;
3027 }
3028 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3029 if (ret < 0) {
3030 step = "begin";
3031 goto exit;
3032 }
3033 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003034 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003035 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003036 ret = platform_get_mmap_data_fd(adev->platform,
3037 out->pcm_device_id, 0 /*playback*/,
3038 &info->shared_memory_fd,
3039 &mmap_size);
3040 if (ret < 0) {
3041 // Fall back to non exclusive mode
3042 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3043 } else {
3044 if (mmap_size < buffer_size) {
3045 step = "mmap";
3046 goto exit;
3047 }
3048 // FIXME: indicate exclusive mode support by returning a negative buffer size
3049 info->buffer_size_frames *= -1;
3050 }
3051 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003052
3053 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3054 if (ret < 0) {
3055 step = "commit";
3056 goto exit;
3057 }
Phil Burkbc991042017-02-24 08:06:44 -08003058
3059 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003060 ret = 0;
3061
3062 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3063 __func__, info->shared_memory_address, info->buffer_size_frames);
3064
3065exit:
3066 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003067 if (out->pcm == NULL) {
3068 ALOGE("%s: %s - %d", __func__, step, ret);
3069 } else {
3070 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003071 pcm_close(out->pcm);
3072 out->pcm = NULL;
3073 }
3074 }
3075 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003076 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003077 return ret;
3078}
3079
3080static int out_get_mmap_position(const struct audio_stream_out *stream,
3081 struct audio_mmap_position *position)
3082{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003083 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003084 struct stream_out *out = (struct stream_out *)stream;
3085 ALOGVV("%s", __func__);
3086 if (position == NULL) {
3087 return -EINVAL;
3088 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003089 lock_output_stream(out);
3090 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3091 out->pcm == NULL) {
3092 ret = -ENOSYS;
3093 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003094 }
3095
3096 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003097 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003098 if (ret < 0) {
3099 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003100 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003101 }
Andy Hungfc044e12017-03-20 09:24:22 -07003102 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003103exit:
3104 pthread_mutex_unlock(&out->lock);
3105 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003106}
3107
3108
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003109/** audio_stream_in implementation **/
3110static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3111{
3112 struct stream_in *in = (struct stream_in *)stream;
3113
3114 return in->config.rate;
3115}
3116
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003117static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003118{
3119 return -ENOSYS;
3120}
3121
3122static size_t in_get_buffer_size(const struct audio_stream *stream)
3123{
3124 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003125 return in->config.period_size * in->af_period_multiplier *
3126 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003127}
3128
3129static uint32_t in_get_channels(const struct audio_stream *stream)
3130{
3131 struct stream_in *in = (struct stream_in *)stream;
3132
3133 return in->channel_mask;
3134}
3135
vivek mehta4ed66e62016-04-15 23:33:34 -07003136static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003137{
vivek mehta4ed66e62016-04-15 23:33:34 -07003138 struct stream_in *in = (struct stream_in *)stream;
3139 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003140}
3141
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003142static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003143{
3144 return -ENOSYS;
3145}
3146
3147static int in_standby(struct audio_stream *stream)
3148{
3149 struct stream_in *in = (struct stream_in *)stream;
3150 struct audio_device *adev = in->dev;
3151 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003152 bool do_stop = true;
3153
Eric Laurent994a6932013-07-17 11:51:42 -07003154 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003155
3156 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003157
3158 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003159 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003160 audio_extn_sound_trigger_stop_lab(in);
3161 in->standby = true;
3162 }
3163
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003164 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003165 if (adev->adm_deregister_stream)
3166 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3167
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003168 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003169 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003170 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003171 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003172 in->capture_started = false;
3173 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003174 if (in->pcm) {
3175 pcm_close(in->pcm);
3176 in->pcm = NULL;
3177 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003178 adev->enable_voicerx = false;
3179 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003180 if (do_stop) {
3181 status = stop_input_stream(in);
3182 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003183 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003184 }
3185 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003186 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003187 return status;
3188}
3189
Andy Hungd13f0d32017-06-12 13:58:37 -07003190static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003191{
Andy Hungd13f0d32017-06-12 13:58:37 -07003192 struct stream_in *in = (struct stream_in *)stream;
3193
3194 // We try to get the lock for consistency,
3195 // but it isn't necessary for these variables.
3196 // If we're not in standby, we may be blocked on a read.
3197 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3198 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3199 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3200 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3201
3202 if (locked) {
3203 pthread_mutex_unlock(&in->lock);
3204 }
3205
3206 // dump error info
3207 (void)error_log_dump(
3208 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003209 return 0;
3210}
3211
3212static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3213{
3214 struct stream_in *in = (struct stream_in *)stream;
3215 struct audio_device *adev = in->dev;
3216 struct str_parms *parms;
3217 char *str;
3218 char value[32];
3219 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003220 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003221
Eric Laurent994a6932013-07-17 11:51:42 -07003222 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003223 parms = str_parms_create_str(kvpairs);
3224
3225 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3226
Eric Laurenta1478072015-09-21 17:21:52 -07003227 lock_input_stream(in);
3228
Eric Laurent150dbfe2013-02-27 14:31:02 -08003229 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003230 if (ret >= 0) {
3231 val = atoi(value);
3232 /* no audio source uses val == 0 */
3233 if ((in->source != val) && (val != 0)) {
3234 in->source = val;
3235 }
3236 }
3237
3238 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003239
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003240 if (ret >= 0) {
3241 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003242 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003243
3244 // Workaround: If routing to an non existing usb device, fail gracefully
3245 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003246 int card;
3247 if (audio_is_usb_in_device(val) &&
3248 (card = get_alive_usb_card(parms)) >= 0) {
3249
3250 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003251 status = -ENOSYS;
3252 } else {
3253
3254 in->device = val;
3255 /* If recording is in progress, change the tx device to new device */
3256 if (!in->standby) {
3257 ALOGV("update input routing change");
3258 // inform adm before actual routing to prevent glitches.
3259 if (adev->adm_on_routing_change) {
3260 adev->adm_on_routing_change(adev->adm_data,
3261 in->capture_handle);
3262 }
3263 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003264 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003265 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003266 }
3267 }
3268
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003269 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003270 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003271
3272 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003273 ALOGV("%s: exit: status(%d)", __func__, status);
3274 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003275}
3276
Haynes Mathew George569b7482017-05-08 14:44:27 -07003277static char* in_get_parameters(const struct audio_stream *stream,
3278 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003279{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003280 struct stream_in *in = (struct stream_in *)stream;
3281 struct str_parms *query = str_parms_create_str(keys);
3282 char *str;
3283 struct str_parms *reply = str_parms_create();
3284 bool replied = false;
3285
3286 ALOGV("%s: enter: keys - %s", __func__, keys);
3287 replied |= stream_get_parameter_channels(query, reply,
3288 &in->supported_channel_masks[0]);
3289 replied |= stream_get_parameter_formats(query, reply,
3290 &in->supported_formats[0]);
3291 replied |= stream_get_parameter_rates(query, reply,
3292 &in->supported_sample_rates[0]);
3293 if (replied) {
3294 str = str_parms_to_str(reply);
3295 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003296 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003297 }
3298 str_parms_destroy(query);
3299 str_parms_destroy(reply);
3300 ALOGV("%s: exit: returns - %s", __func__, str);
3301 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003302}
3303
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003304static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003305{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003306 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003307}
3308
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003309static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3310{
3311 if (!stream || !parms)
3312 return;
3313
3314 struct stream_in *in = (struct stream_in *)stream;
3315 struct audio_device *adev = in->dev;
3316
3317 card_status_t status;
3318 int card;
3319 if (parse_snd_card_status(parms, &card, &status) < 0)
3320 return;
3321
3322 pthread_mutex_lock(&adev->lock);
3323 bool valid_cb = (card == adev->snd_card);
3324 pthread_mutex_unlock(&adev->lock);
3325
3326 if (!valid_cb)
3327 return;
3328
3329 lock_input_stream(in);
3330 if (in->card_status != status)
3331 in->card_status = status;
3332 pthread_mutex_unlock(&in->lock);
3333
3334 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3335 use_case_table[in->usecase],
3336 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3337
3338 // a better solution would be to report error back to AF and let
3339 // it put the stream to standby
3340 if (status == CARD_STATUS_OFFLINE)
3341 in_standby(&in->stream.common);
3342
3343 return;
3344}
3345
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003346static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3347 size_t bytes)
3348{
3349 struct stream_in *in = (struct stream_in *)stream;
3350 struct audio_device *adev = in->dev;
3351 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003352 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003353 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003354
Eric Laurenta1478072015-09-21 17:21:52 -07003355 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003356 const size_t frame_size = audio_stream_in_frame_size(stream);
3357 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003358
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003359 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003360 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003361 /* Read from sound trigger HAL */
3362 audio_extn_sound_trigger_read(in, buffer, bytes);
3363 pthread_mutex_unlock(&in->lock);
3364 return bytes;
3365 }
3366
Eric Laurent0e46adf2016-12-16 12:49:24 -08003367 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3368 ret = -ENOSYS;
3369 goto exit;
3370 }
3371
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003372 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003373 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003374 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003375 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003376 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003377 goto exit;
3378 }
3379 in->standby = 0;
3380 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003381
Andy Hungd13f0d32017-06-12 13:58:37 -07003382 // errors that occur here are read errors.
3383 error_code = ERROR_CODE_READ;
3384
Haynes Mathew George03c40102016-01-29 17:57:48 -08003385 //what's the duration requested by the client?
3386 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3387 in->config.rate;
3388 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003389
Haynes Mathew George03c40102016-01-29 17:57:48 -08003390 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003391 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003392 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003393 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003394 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003395 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003396 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003397 if (ret < 0) {
3398 ALOGE("Failed to read w/err %s", strerror(errno));
3399 ret = -errno;
3400 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003401 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3402 if (bytes % 4 == 0) {
3403 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3404 int_buf_stream = buffer;
3405 for (size_t itt=0; itt < bytes/4 ; itt++) {
3406 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003407 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003408 } else {
3409 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3410 ret = -EINVAL;
3411 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003412 }
3413 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003414 }
3415
Haynes Mathew George03c40102016-01-29 17:57:48 -08003416 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003417
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003418 /*
3419 * Instead of writing zeroes here, we could trust the hardware
3420 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003421 * 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 -08003422 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08003423 if (ret == 0 && adev->mic_muted &&
3424 !voice_is_in_call_rec_stream(in) &&
3425 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003426 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07003427 in->frames_muted += frames;
3428 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003429
3430exit:
3431 pthread_mutex_unlock(&in->lock);
3432
3433 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07003434 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003435 in_standby(&in->stream.common);
3436 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003437 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003438 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07003439 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08003440 }
3441 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003442 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003443 }
3444 return bytes;
3445}
3446
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003447static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003448{
3449 return 0;
3450}
3451
Andy Hung6ebe5962016-01-15 17:46:57 -08003452static int in_get_capture_position(const struct audio_stream_in *stream,
3453 int64_t *frames, int64_t *time)
3454{
3455 if (stream == NULL || frames == NULL || time == NULL) {
3456 return -EINVAL;
3457 }
3458 struct stream_in *in = (struct stream_in *)stream;
3459 int ret = -ENOSYS;
3460
3461 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003462 // note: ST sessions do not close the alsa pcm driver synchronously
3463 // on standby. Therefore, we may return an error even though the
3464 // pcm stream is still opened.
3465 if (in->standby) {
3466 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
3467 "%s stream in standby but pcm not NULL for non ST session", __func__);
3468 goto exit;
3469 }
Andy Hung6ebe5962016-01-15 17:46:57 -08003470 if (in->pcm) {
3471 struct timespec timestamp;
3472 unsigned int avail;
3473 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3474 *frames = in->frames_read + avail;
3475 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3476 ret = 0;
3477 }
3478 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003479exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08003480 pthread_mutex_unlock(&in->lock);
3481 return ret;
3482}
3483
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003484static int add_remove_audio_effect(const struct audio_stream *stream,
3485 effect_handle_t effect,
3486 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003487{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003488 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003489 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003490 int status = 0;
3491 effect_descriptor_t desc;
3492
3493 status = (*effect)->get_descriptor(effect, &desc);
3494 if (status != 0)
3495 return status;
3496
Eric Laurenta1478072015-09-21 17:21:52 -07003497 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003498 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003499 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003500 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003501 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003502 in->enable_aec != enable &&
3503 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3504 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003505 if (!enable)
3506 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003507 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3508 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3509 adev->enable_voicerx = enable;
3510 struct audio_usecase *usecase;
3511 struct listnode *node;
3512 list_for_each(node, &adev->usecase_list) {
3513 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07003514 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07003515 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05003516 }
3517 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003518 if (!in->standby)
3519 select_devices(in->dev, in->usecase);
3520 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003521 if (in->enable_ns != enable &&
3522 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3523 in->enable_ns = enable;
3524 if (!in->standby)
3525 select_devices(in->dev, in->usecase);
3526 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003527 pthread_mutex_unlock(&in->dev->lock);
3528 pthread_mutex_unlock(&in->lock);
3529
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003530 return 0;
3531}
3532
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003533static int in_add_audio_effect(const struct audio_stream *stream,
3534 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003535{
Eric Laurent994a6932013-07-17 11:51:42 -07003536 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003537 return add_remove_audio_effect(stream, effect, true);
3538}
3539
3540static int in_remove_audio_effect(const struct audio_stream *stream,
3541 effect_handle_t effect)
3542{
Eric Laurent994a6932013-07-17 11:51:42 -07003543 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003544 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003545}
3546
Eric Laurent0e46adf2016-12-16 12:49:24 -08003547static int in_stop(const struct audio_stream_in* stream)
3548{
3549 struct stream_in *in = (struct stream_in *)stream;
3550 struct audio_device *adev = in->dev;
3551
3552 int ret = -ENOSYS;
3553 ALOGV("%s", __func__);
3554 pthread_mutex_lock(&adev->lock);
3555 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3556 in->capture_started && in->pcm != NULL) {
3557 pcm_stop(in->pcm);
3558 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003559 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003560 }
3561 pthread_mutex_unlock(&adev->lock);
3562 return ret;
3563}
3564
3565static int in_start(const struct audio_stream_in* stream)
3566{
3567 struct stream_in *in = (struct stream_in *)stream;
3568 struct audio_device *adev = in->dev;
3569 int ret = -ENOSYS;
3570
3571 ALOGV("%s in %p", __func__, in);
3572 pthread_mutex_lock(&adev->lock);
3573 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3574 !in->capture_started && in->pcm != NULL) {
3575 if (!in->capture_started) {
3576 ret = start_input_stream(in);
3577 if (ret == 0) {
3578 in->capture_started = true;
3579 }
3580 }
3581 }
3582 pthread_mutex_unlock(&adev->lock);
3583 return ret;
3584}
3585
3586static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3587 int32_t min_size_frames,
3588 struct audio_mmap_buffer_info *info)
3589{
3590 struct stream_in *in = (struct stream_in *)stream;
3591 struct audio_device *adev = in->dev;
3592 int ret = 0;
3593 unsigned int offset1;
3594 unsigned int frames1;
3595 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003596 uint32_t mmap_size;
3597 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003598
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003599 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003600 pthread_mutex_lock(&adev->lock);
3601 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003602
Eric Laurent0e46adf2016-12-16 12:49:24 -08003603 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003604 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003605 ret = -EINVAL;
3606 goto exit;
3607 }
3608 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003609 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003610 ALOGV("%s in %p", __func__, in);
3611 ret = -ENOSYS;
3612 goto exit;
3613 }
3614 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3615 if (in->pcm_device_id < 0) {
3616 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3617 __func__, in->pcm_device_id, in->usecase);
3618 ret = -EINVAL;
3619 goto exit;
3620 }
Phil Burkbc991042017-02-24 08:06:44 -08003621
3622 adjust_mmap_period_count(&in->config, min_size_frames);
3623
Eric Laurent0e46adf2016-12-16 12:49:24 -08003624 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3625 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3626 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3627 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3628 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3629 step = "open";
3630 ret = -ENODEV;
3631 goto exit;
3632 }
3633
3634 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3635 if (ret < 0) {
3636 step = "begin";
3637 goto exit;
3638 }
3639 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003640 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003641 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003642 ret = platform_get_mmap_data_fd(adev->platform,
3643 in->pcm_device_id, 1 /*capture*/,
3644 &info->shared_memory_fd,
3645 &mmap_size);
3646 if (ret < 0) {
3647 // Fall back to non exclusive mode
3648 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3649 } else {
3650 if (mmap_size < buffer_size) {
3651 step = "mmap";
3652 goto exit;
3653 }
3654 // FIXME: indicate exclusive mode support by returning a negative buffer size
3655 info->buffer_size_frames *= -1;
3656 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08003657
Haynes Mathew George96483a22017-03-28 14:52:47 -07003658 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003659
3660 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3661 if (ret < 0) {
3662 step = "commit";
3663 goto exit;
3664 }
3665
Phil Burkbc991042017-02-24 08:06:44 -08003666 in->standby = false;
3667 ret = 0;
3668
Eric Laurent0e46adf2016-12-16 12:49:24 -08003669 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3670 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003671
3672exit:
3673 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003674 if (in->pcm == NULL) {
3675 ALOGE("%s: %s - %d", __func__, step, ret);
3676 } else {
3677 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003678 pcm_close(in->pcm);
3679 in->pcm = NULL;
3680 }
3681 }
3682 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003683 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003684 return ret;
3685}
3686
3687static int in_get_mmap_position(const struct audio_stream_in *stream,
3688 struct audio_mmap_position *position)
3689{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003690 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003691 struct stream_in *in = (struct stream_in *)stream;
3692 ALOGVV("%s", __func__);
3693 if (position == NULL) {
3694 return -EINVAL;
3695 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003696 lock_input_stream(in);
3697 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
3698 in->pcm == NULL) {
3699 ret = -ENOSYS;
3700 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003701 }
3702 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003703 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003704 if (ret < 0) {
3705 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003706 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003707 }
Andy Hungfc044e12017-03-20 09:24:22 -07003708 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003709exit:
3710 pthread_mutex_unlock(&in->lock);
3711 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003712}
3713
3714
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003715static int adev_open_output_stream(struct audio_hw_device *dev,
3716 audio_io_handle_t handle,
3717 audio_devices_t devices,
3718 audio_output_flags_t flags,
3719 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003720 struct audio_stream_out **stream_out,
3721 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003722{
3723 struct audio_device *adev = (struct audio_device *)dev;
3724 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003725 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003726 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
3727 bool is_usb_dev = audio_is_usb_out_device(devices) &&
3728 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003729
Andy Hungd9653bd2017-08-01 19:31:39 -07003730 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
3731 return -ENOSYS;
3732 }
3733
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003734 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
3735 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003736 *stream_out = NULL;
3737 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3738
3739 if (devices == AUDIO_DEVICE_NONE)
3740 devices = AUDIO_DEVICE_OUT_SPEAKER;
3741
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003742 out->flags = flags;
3743 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003744 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003745 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003746 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003747
3748 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003749 if ((is_hdmi || is_usb_dev) &&
3750 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
3751 (flags == AUDIO_OUTPUT_FLAG_NONE ||
3752 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003753 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003754 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003755 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003756 if (config->sample_rate == 0)
3757 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3758 if (config->channel_mask == 0)
3759 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3760 if (config->format == AUDIO_FORMAT_DEFAULT)
3761 config->format = AUDIO_FORMAT_PCM_16_BIT;
3762 } else if (is_usb_dev) {
3763 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
3764 &config->format,
3765 &out->supported_formats[0],
3766 MAX_SUPPORTED_FORMATS,
3767 &config->channel_mask,
3768 &out->supported_channel_masks[0],
3769 MAX_SUPPORTED_CHANNEL_MASKS,
3770 &config->sample_rate,
3771 &out->supported_sample_rates[0],
3772 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003773 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003774 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003775 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003776 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003777 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003778
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003779
Haynes Mathew George569b7482017-05-08 14:44:27 -07003780 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003781 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003782 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003783 if (is_hdmi) {
3784 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3785 out->config = pcm_config_hdmi_multi;
3786 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3787 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3788 out->config = pcm_config_mmap_playback;
3789 out->stream.start = out_start;
3790 out->stream.stop = out_stop;
3791 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3792 out->stream.get_mmap_position = out_get_mmap_position;
3793 } else {
3794 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3795 out->config = pcm_config_hifi;
3796 }
3797
3798 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003799 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003800 if (is_hdmi) {
3801 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
3802 audio_bytes_per_sample(out->format));
3803 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003804 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003805 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003806 pthread_mutex_lock(&adev->lock);
3807 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3808 pthread_mutex_unlock(&adev->lock);
3809
3810 // reject offload during card offline to allow
3811 // fallback to s/w paths
3812 if (offline) {
3813 ret = -ENODEV;
3814 goto error_open;
3815 }
3816
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003817 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3818 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3819 ALOGE("%s: Unsupported Offload information", __func__);
3820 ret = -EINVAL;
3821 goto error_open;
3822 }
3823 if (!is_supported_format(config->offload_info.format)) {
3824 ALOGE("%s: Unsupported audio format", __func__);
3825 ret = -EINVAL;
3826 goto error_open;
3827 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003828 out->sample_rate = config->offload_info.sample_rate;
3829 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
3830 out->channel_mask = config->offload_info.channel_mask;
3831 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
3832 out->channel_mask = config->channel_mask;
3833 else
3834 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3835
3836 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003837
3838 out->compr_config.codec = (struct snd_codec *)
3839 calloc(1, sizeof(struct snd_codec));
3840
3841 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003842
3843 out->stream.set_callback = out_set_callback;
3844 out->stream.pause = out_pause;
3845 out->stream.resume = out_resume;
3846 out->stream.drain = out_drain;
3847 out->stream.flush = out_flush;
3848
3849 out->compr_config.codec->id =
3850 get_snd_codec_id(config->offload_info.format);
3851 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3852 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003853 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003854 out->compr_config.codec->bit_rate =
3855 config->offload_info.bit_rate;
3856 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003857 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003858 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3859
3860 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3861 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003862
3863 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003864 create_offload_callback_thread(out);
3865 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3866 __func__, config->offload_info.version,
3867 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003868 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07003869 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003870 case 0:
3871 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
3872 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07003873 case 8000:
3874 case 16000:
3875 case 48000:
3876 out->sample_rate = config->sample_rate;
3877 break;
3878 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003879 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
3880 config->sample_rate);
3881 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3882 ret = -EINVAL;
3883 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003884 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003885 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
3886 switch (config->channel_mask) {
3887 case AUDIO_CHANNEL_NONE:
3888 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3889 break;
3890 case AUDIO_CHANNEL_OUT_STEREO:
3891 out->channel_mask = config->channel_mask;
3892 break;
3893 default:
3894 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
3895 config->channel_mask);
3896 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3897 ret = -EINVAL;
3898 break;
3899 }
3900 switch (config->format) {
3901 case AUDIO_FORMAT_DEFAULT:
3902 out->format = AUDIO_FORMAT_PCM_16_BIT;
3903 break;
3904 case AUDIO_FORMAT_PCM_16_BIT:
3905 out->format = config->format;
3906 break;
3907 default:
3908 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
3909 config->format);
3910 config->format = AUDIO_FORMAT_PCM_16_BIT;
3911 ret = -EINVAL;
3912 break;
3913 }
3914 if (ret != 0)
3915 goto error_open;
3916
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003917 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3918 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003919 out->config.rate = out->sample_rate;
3920 out->config.channels =
3921 audio_channel_count_from_out_mask(out->channel_mask);
3922 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003923 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003924 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
3925 switch (config->sample_rate) {
3926 case 0:
3927 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3928 break;
3929 case 8000:
3930 case 16000:
3931 case 32000:
3932 case 48000:
3933 out->sample_rate = config->sample_rate;
3934 break;
3935 default:
3936 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
3937 config->sample_rate);
3938 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3939 ret = -EINVAL;
3940 break;
3941 }
Eric Laurentad2dde92017-09-20 18:27:31 -07003942 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003943 switch (config->channel_mask) {
3944 case AUDIO_CHANNEL_NONE:
3945 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3946 break;
3947 case AUDIO_CHANNEL_OUT_STEREO:
3948 out->channel_mask = config->channel_mask;
3949 break;
3950 default:
3951 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
3952 config->channel_mask);
3953 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3954 ret = -EINVAL;
3955 break;
3956 }
3957 switch (config->format) {
3958 case AUDIO_FORMAT_DEFAULT:
3959 out->format = AUDIO_FORMAT_PCM_16_BIT;
3960 break;
3961 case AUDIO_FORMAT_PCM_16_BIT:
3962 out->format = config->format;
3963 break;
3964 default:
3965 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
3966 config->format);
3967 config->format = AUDIO_FORMAT_PCM_16_BIT;
3968 ret = -EINVAL;
3969 break;
3970 }
3971 if (ret != 0)
3972 goto error_open;
3973
vivek mehtaa68fea62017-06-08 19:04:02 -07003974 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07003975 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
3976 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003977 out->config.rate = out->sample_rate;
3978 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07003979 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003980 out->sample_rate,
3981 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07003982 out->config.channels,
3983 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003984 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07003985 out->config.period_size = buffer_size / frame_size;
3986 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
3987 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003988 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003989 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003990 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3991 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003992 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003993 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3994 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003995 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003996 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003997 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003998 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003999 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004000 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4001 out->config = pcm_config_mmap_playback;
4002 out->stream.start = out_start;
4003 out->stream.stop = out_stop;
4004 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4005 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004006 } else {
4007 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4008 out->config = pcm_config_low_latency;
4009 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004010
4011 if (config->sample_rate == 0) {
4012 out->sample_rate = out->config.rate;
4013 } else {
4014 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004015 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004016 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
4017 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
4018 } else {
4019 out->channel_mask = config->channel_mask;
4020 }
4021 if (config->format == AUDIO_FORMAT_DEFAULT)
4022 out->format = audio_format_from_pcm_format(out->config.format);
4023 else if (!audio_is_linear_pcm(config->format)) {
4024 config->format = AUDIO_FORMAT_PCM_16_BIT;
4025 ret = -EINVAL;
4026 goto error_open;
4027 } else {
4028 out->format = config->format;
4029 }
4030
4031 out->config.rate = out->sample_rate;
4032 out->config.channels =
4033 audio_channel_count_from_out_mask(out->channel_mask);
4034 if (out->format != audio_format_from_pcm_format(out->config.format)) {
4035 out->config.format = pcm_format_from_audio_format(out->format);
4036 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004037 }
Kevin Rocard50eff892017-05-02 16:52:05 -07004038
4039 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
4040 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004041 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004042 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
4043 __func__, config->sample_rate, config->format, config->channel_mask);
4044 config->sample_rate = out->sample_rate;
4045 config->format = out->format;
4046 config->channel_mask = out->channel_mask;
4047 ret = -EINVAL;
4048 goto error_open;
4049 }
4050
Andy Hung6fcba9c2014-03-18 11:53:32 -07004051 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
4052 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004053
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004054 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004055 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004056 adev->primary_output = out;
4057 else {
4058 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004059 ret = -EEXIST;
4060 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004061 }
4062 }
4063
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004064 /* Check if this usecase is already existing */
4065 pthread_mutex_lock(&adev->lock);
4066 if (get_usecase_from_list(adev, out->usecase) != NULL) {
4067 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004068 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004069 ret = -EEXIST;
4070 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004071 }
4072 pthread_mutex_unlock(&adev->lock);
4073
4074 out->stream.common.get_sample_rate = out_get_sample_rate;
4075 out->stream.common.set_sample_rate = out_set_sample_rate;
4076 out->stream.common.get_buffer_size = out_get_buffer_size;
4077 out->stream.common.get_channels = out_get_channels;
4078 out->stream.common.get_format = out_get_format;
4079 out->stream.common.set_format = out_set_format;
4080 out->stream.common.standby = out_standby;
4081 out->stream.common.dump = out_dump;
4082 out->stream.common.set_parameters = out_set_parameters;
4083 out->stream.common.get_parameters = out_get_parameters;
4084 out->stream.common.add_audio_effect = out_add_audio_effect;
4085 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4086 out->stream.get_latency = out_get_latency;
4087 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004088#ifdef NO_AUDIO_OUT
4089 out->stream.write = out_write_for_no_output;
4090#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004091 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004092#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004093 out->stream.get_render_position = out_get_render_position;
4094 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004095 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004096
Eric Laurent0e46adf2016-12-16 12:49:24 -08004097 if (out->realtime)
4098 out->af_period_multiplier = af_period_multiplier;
4099 else
4100 out->af_period_multiplier = 1;
4101
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004102 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004103 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004104 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004105
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004106 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004107 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004108 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4109
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004110 config->format = out->stream.common.get_format(&out->stream.common);
4111 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4112 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4113
Andy Hunga452b0a2017-03-15 14:51:15 -07004114 out->error_log = error_log_create(
4115 ERROR_LOG_ENTRIES,
4116 1000000000 /* aggregate consecutive identical errors within one second in ns */);
4117
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004118 /*
4119 By locking output stream before registering, we allow the callback
4120 to update stream's state only after stream's initial state is set to
4121 adev state.
4122 */
4123 lock_output_stream(out);
4124 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4125 pthread_mutex_lock(&adev->lock);
4126 out->card_status = adev->card_status;
4127 pthread_mutex_unlock(&adev->lock);
4128 pthread_mutex_unlock(&out->lock);
4129
vivek mehta4a824772017-06-08 19:05:49 -07004130 stream_app_type_cfg_init(&out->app_type_cfg);
4131
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004132 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004133
Eric Laurent994a6932013-07-17 11:51:42 -07004134 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004135 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004136
4137error_open:
4138 free(out);
4139 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07004140 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004141 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004142}
4143
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004144static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004145 struct audio_stream_out *stream)
4146{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004147 struct stream_out *out = (struct stream_out *)stream;
4148 struct audio_device *adev = out->dev;
4149
Eric Laurent994a6932013-07-17 11:51:42 -07004150 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004151
4152 // must deregister from sndmonitor first to prevent races
4153 // between the callback and close_stream
4154 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004155 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004156 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
4157 destroy_offload_callback_thread(out);
4158
4159 if (out->compr_config.codec != NULL)
4160 free(out->compr_config.codec);
4161 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004162
4163 if (adev->voice_tx_output == out)
4164 adev->voice_tx_output = NULL;
4165
Andy Hunga452b0a2017-03-15 14:51:15 -07004166 error_log_destroy(out->error_log);
4167 out->error_log = NULL;
4168
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004169 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004170 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004171 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004172 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004173 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004174}
4175
4176static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4177{
4178 struct audio_device *adev = (struct audio_device *)dev;
4179 struct str_parms *parms;
4180 char *str;
4181 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004182 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004183 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07004184 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004185
Joe Onorato188b6222016-03-01 11:02:27 -08004186 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004187
4188 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004189
4190 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004191 status = voice_set_parameters(adev, parms);
4192 if (status != 0) {
4193 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004194 }
4195
4196 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4197 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07004198 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004199 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4200 adev->bluetooth_nrec = true;
4201 else
4202 adev->bluetooth_nrec = false;
4203 }
4204
4205 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4206 if (ret >= 0) {
4207 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4208 adev->screen_off = false;
4209 else
4210 adev->screen_off = true;
4211 }
4212
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004213 ret = str_parms_get_int(parms, "rotation", &val);
4214 if (ret >= 0) {
4215 bool reverse_speakers = false;
4216 switch(val) {
4217 // FIXME: note that the code below assumes that the speakers are in the correct placement
4218 // relative to the user when the device is rotated 90deg from its default rotation. This
4219 // assumption is device-specific, not platform-specific like this code.
4220 case 270:
4221 reverse_speakers = true;
4222 break;
4223 case 0:
4224 case 90:
4225 case 180:
4226 break;
4227 default:
4228 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07004229 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004230 }
Eric Laurent03f09432014-03-25 18:09:11 -07004231 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004232 // check and set swap
4233 // - check if orientation changed and speaker active
4234 // - set rotation and cache the rotation value
4235 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004236 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004237 }
4238
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004239 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4240 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004241 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004242 }
4243
David Linee3fe402017-03-13 10:00:42 -07004244 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4245 if (ret >= 0) {
4246 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004247 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004248 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4249 if (ret >= 0) {
4250 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004251 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004252 }
Eric Laurent99dab492017-06-17 15:19:08 -07004253 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004254 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4255 if (ret >= 0) {
4256 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004257 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004258 }
4259 }
4260 }
4261
4262 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4263 if (ret >= 0) {
4264 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004265 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004266 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4267 if (ret >= 0) {
4268 const int card = atoi(value);
4269
Eric Laurent99dab492017-06-17 15:19:08 -07004270 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004271 }
Eric Laurent99dab492017-06-17 15:19:08 -07004272 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004273 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4274 if (ret >= 0) {
4275 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004276 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004277 }
4278 }
4279 }
4280
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004281 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004282done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004283 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004284 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004285 ALOGV("%s: exit with code(%d)", __func__, status);
4286 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004287}
4288
4289static char* adev_get_parameters(const struct audio_hw_device *dev,
4290 const char *keys)
4291{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004292 struct audio_device *adev = (struct audio_device *)dev;
4293 struct str_parms *reply = str_parms_create();
4294 struct str_parms *query = str_parms_create_str(keys);
4295 char *str;
4296
4297 pthread_mutex_lock(&adev->lock);
4298
4299 voice_get_parameters(adev, query, reply);
4300 str = str_parms_to_str(reply);
4301 str_parms_destroy(query);
4302 str_parms_destroy(reply);
4303
4304 pthread_mutex_unlock(&adev->lock);
4305 ALOGV("%s: exit: returns - %s", __func__, str);
4306 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004307}
4308
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004309static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004310{
4311 return 0;
4312}
4313
Haynes Mathew George5191a852013-09-11 14:19:36 -07004314static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4315{
4316 int ret;
4317 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004318
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004319 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4320
Haynes Mathew George5191a852013-09-11 14:19:36 -07004321 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004322 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004323 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004324
Haynes Mathew George5191a852013-09-11 14:19:36 -07004325 return ret;
4326}
4327
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004328static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004329{
4330 return -ENOSYS;
4331}
4332
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004333static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4334 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004335{
4336 return -ENOSYS;
4337}
4338
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004339static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004340{
4341 return -ENOSYS;
4342}
4343
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004344static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004345{
4346 return -ENOSYS;
4347}
4348
4349static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4350{
4351 struct audio_device *adev = (struct audio_device *)dev;
4352
4353 pthread_mutex_lock(&adev->lock);
4354 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004355 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004356 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004357 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4358 voice_is_in_call(adev)) {
4359 voice_stop_call(adev);
4360 adev->current_call_output = NULL;
4361 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004362 }
4363 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004364
4365 audio_extn_extspk_set_mode(adev->extspk, mode);
4366
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004367 return 0;
4368}
4369
4370static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4371{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004372 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004373 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004374
Eric Laurent2bafff12016-03-17 12:17:23 -07004375 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004376 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004377 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4378 ret = audio_extn_hfp_set_mic_mute(adev, state);
4379 } else {
4380 ret = voice_set_mic_mute(adev, state);
4381 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004382 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004383 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004384
4385 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004386}
4387
4388static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4389{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004390 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004391 return 0;
4392}
4393
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004394static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004395 const struct audio_config *config)
4396{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004397 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004398
Eric Laurent74b55762017-07-09 17:04:53 -07004399 /* Don't know if USB HIFI in this context so use true to be conservative */
4400 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4401 true /*is_usb_hifi */) != 0)
4402 return 0;
4403
vivek mehtaa68fea62017-06-08 19:04:02 -07004404 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4405 config->sample_rate, config->format,
4406 channel_count,
4407 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004408}
4409
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004410static bool adev_input_allow_hifi_record(struct audio_device *adev,
4411 audio_devices_t devices,
4412 audio_input_flags_t flags,
4413 audio_source_t source) {
4414 const bool allowed = true;
4415
4416 if (!audio_is_usb_in_device(devices))
4417 return !allowed;
4418
4419 switch (flags) {
4420 case AUDIO_INPUT_FLAG_NONE:
4421 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4422 break;
4423 default:
4424 return !allowed;
4425 }
4426
4427 switch (source) {
4428 case AUDIO_SOURCE_DEFAULT:
4429 case AUDIO_SOURCE_MIC:
4430 case AUDIO_SOURCE_UNPROCESSED:
4431 break;
4432 default:
4433 return !allowed;
4434 }
4435
4436 switch (adev->mode) {
4437 case 0:
4438 break;
4439 default:
4440 return !allowed;
4441 }
4442
4443 return allowed;
4444}
4445
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004446static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004447 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004448 audio_devices_t devices,
4449 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004450 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004451 audio_input_flags_t flags,
4452 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004453 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004454{
4455 struct audio_device *adev = (struct audio_device *)dev;
4456 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004457 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004458 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004459 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004460 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004461 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4462 devices,
4463 flags,
4464 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004465 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004466 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004467
Andy Hungd9653bd2017-08-01 19:31:39 -07004468 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
4469 return -ENOSYS;
4470 }
4471
Eric Laurent74b55762017-07-09 17:04:53 -07004472 if (!(is_usb_dev && may_use_hifi_record)) {
4473 if (config->sample_rate == 0)
4474 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4475 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4476 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4477 if (config->format == AUDIO_FORMAT_DEFAULT)
4478 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004479
Eric Laurent74b55762017-07-09 17:04:53 -07004480 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
4481
4482 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
4483 return -EINVAL;
4484 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004485
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004486 if (audio_extn_tfa_98xx_is_supported() &&
4487 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004488 return -EINVAL;
4489
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004490 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4491
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004492 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004493 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004494
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004495 in->stream.common.get_sample_rate = in_get_sample_rate;
4496 in->stream.common.set_sample_rate = in_set_sample_rate;
4497 in->stream.common.get_buffer_size = in_get_buffer_size;
4498 in->stream.common.get_channels = in_get_channels;
4499 in->stream.common.get_format = in_get_format;
4500 in->stream.common.set_format = in_set_format;
4501 in->stream.common.standby = in_standby;
4502 in->stream.common.dump = in_dump;
4503 in->stream.common.set_parameters = in_set_parameters;
4504 in->stream.common.get_parameters = in_get_parameters;
4505 in->stream.common.add_audio_effect = in_add_audio_effect;
4506 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4507 in->stream.set_gain = in_set_gain;
4508 in->stream.read = in_read;
4509 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08004510 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004511
4512 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004513 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004514 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004515 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004516 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004517 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004518
Haynes Mathew George569b7482017-05-08 14:44:27 -07004519 if (is_usb_dev && may_use_hifi_record) {
4520 /* HiFi record selects an appropriate format, channel, rate combo
4521 depending on sink capabilities*/
4522 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
4523 &config->format,
4524 &in->supported_formats[0],
4525 MAX_SUPPORTED_FORMATS,
4526 &config->channel_mask,
4527 &in->supported_channel_masks[0],
4528 MAX_SUPPORTED_CHANNEL_MASKS,
4529 &config->sample_rate,
4530 &in->supported_sample_rates[0],
4531 MAX_SUPPORTED_SAMPLE_RATES);
4532 if (ret != 0) {
4533 ret = -EINVAL;
4534 goto err_open;
4535 }
Eric Laurent74b55762017-07-09 17:04:53 -07004536 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004537 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07004538 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07004539 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
4540 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
4541 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4542 bool ret_error = false;
4543 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4544 from HAL is 8_24
4545 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4546 8_24 return error indicating supported format is 8_24
4547 *> In case of any other source requesting 24 bit or float return error
4548 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07004549
vivek mehta57ff9b52016-04-28 14:13:08 -07004550 on error flinger will retry with supported format passed
4551 */
4552 if (source != AUDIO_SOURCE_UNPROCESSED) {
4553 config->format = AUDIO_FORMAT_PCM_16_BIT;
4554 ret_error = true;
4555 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
4556 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
4557 ret_error = true;
4558 }
4559
4560 if (ret_error) {
4561 ret = -EINVAL;
4562 goto err_open;
4563 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004564 }
4565
vivek mehta57ff9b52016-04-28 14:13:08 -07004566 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07004567 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07004568
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004569 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004570 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
4571 if (config->sample_rate == 0)
4572 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4573 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4574 config->sample_rate != 8000) {
4575 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4576 ret = -EINVAL;
4577 goto err_open;
4578 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004579
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004580 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4581 config->format = AUDIO_FORMAT_PCM_16_BIT;
4582 ret = -EINVAL;
4583 goto err_open;
4584 }
4585
4586 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4587 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07004588 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004589 } else if (is_usb_dev && may_use_hifi_record) {
4590 in->usecase = USECASE_AUDIO_RECORD_HIFI;
4591 in->config = pcm_config_audio_capture;
4592 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004593 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4594 config->sample_rate,
4595 config->format,
4596 channel_count,
4597 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004598 in->config.period_size = buffer_size / frame_size;
4599 in->config.rate = config->sample_rate;
4600 in->af_period_multiplier = 1;
4601 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004602 } else {
4603 in->usecase = USECASE_AUDIO_RECORD;
4604 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08004605 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004606 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07004607#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004608 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07004609#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08004610 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004611 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08004612 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004613 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004614 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4615 config->sample_rate,
4616 config->format,
4617 channel_count,
4618 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004619 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004620 in->config.rate = config->sample_rate;
4621 in->af_period_multiplier = 1;
4622 } else {
4623 // period size is left untouched for rt mode playback
4624 in->config = pcm_config_audio_capture_rt;
4625 in->af_period_multiplier = af_period_multiplier;
4626 }
4627 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
4628 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004629 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08004630 in->usecase = USECASE_AUDIO_RECORD_MMAP;
4631 in->config = pcm_config_mmap_capture;
4632 in->stream.start = in_start;
4633 in->stream.stop = in_stop;
4634 in->stream.create_mmap_buffer = in_create_mmap_buffer;
4635 in->stream.get_mmap_position = in_get_mmap_position;
4636 in->af_period_multiplier = 1;
4637 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07004638 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07004639 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07004640 (config->sample_rate == 8000 ||
4641 config->sample_rate == 16000 ||
4642 config->sample_rate == 32000 ||
4643 config->sample_rate == 48000) &&
4644 channel_count == 1) {
4645 in->usecase = USECASE_AUDIO_RECORD_VOIP;
4646 in->config = pcm_config_audio_capture;
4647 frame_size = audio_stream_in_frame_size(&in->stream);
4648 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
4649 config->sample_rate,
4650 config->format,
4651 channel_count, false /*is_low_latency*/);
4652 in->config.period_size = buffer_size / frame_size;
4653 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
4654 in->config.rate = config->sample_rate;
4655 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004656 } else {
4657 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004658 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004659 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4660 config->sample_rate,
4661 config->format,
4662 channel_count,
4663 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004664 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004665 in->config.rate = config->sample_rate;
4666 in->af_period_multiplier = 1;
4667 }
4668 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
4669 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004670 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004671
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004672 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07004673 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004674
Andy Hungd13f0d32017-06-12 13:58:37 -07004675 in->error_log = error_log_create(
4676 ERROR_LOG_ENTRIES,
4677 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
4678
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004679 /* This stream could be for sound trigger lab,
4680 get sound trigger pcm if present */
4681 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004682
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004683 lock_input_stream(in);
4684 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
4685 pthread_mutex_lock(&adev->lock);
4686 in->card_status = adev->card_status;
4687 pthread_mutex_unlock(&adev->lock);
4688 pthread_mutex_unlock(&in->lock);
4689
vivek mehta4a824772017-06-08 19:05:49 -07004690 stream_app_type_cfg_init(&in->app_type_cfg);
4691
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004692 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004693 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004694 return 0;
4695
4696err_open:
4697 free(in);
4698 *stream_in = NULL;
4699 return ret;
4700}
4701
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004702static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004703 struct audio_stream_in *stream)
4704{
Andy Hungd13f0d32017-06-12 13:58:37 -07004705 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004706 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004707
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004708 // must deregister from sndmonitor first to prevent races
4709 // between the callback and close_stream
4710 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004711 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07004712
4713 error_log_destroy(in->error_log);
4714 in->error_log = NULL;
4715
Andy Hung0dbb52b2017-08-09 13:51:38 -07004716 pthread_mutex_destroy(&in->pre_lock);
4717 pthread_mutex_destroy(&in->lock);
4718
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004719 free(stream);
4720
4721 return;
4722}
4723
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004724static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004725{
4726 return 0;
4727}
4728
Andy Hung31aca912014-03-20 17:14:59 -07004729/* verifies input and output devices and their capabilities.
4730 *
4731 * This verification is required when enabling extended bit-depth or
4732 * sampling rates, as not all qcom products support it.
4733 *
4734 * Suitable for calling only on initialization such as adev_open().
4735 * It fills the audio_device use_case_table[] array.
4736 *
4737 * Has a side-effect that it needs to configure audio routing / devices
4738 * in order to power up the devices and read the device parameters.
4739 * It does not acquire any hw device lock. Should restore the devices
4740 * back to "normal state" upon completion.
4741 */
4742static int adev_verify_devices(struct audio_device *adev)
4743{
4744 /* enumeration is a bit difficult because one really wants to pull
4745 * the use_case, device id, etc from the hidden pcm_device_table[].
4746 * In this case there are the following use cases and device ids.
4747 *
4748 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
4749 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004750 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07004751 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
4752 * [USECASE_AUDIO_RECORD] = {0, 0},
4753 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
4754 * [USECASE_VOICE_CALL] = {2, 2},
4755 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004756 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07004757 * USECASE_VOICE_CALL omitted, but possible for either input or output.
4758 */
4759
4760 /* should be the usecases enabled in adev_open_input_stream() */
4761 static const int test_in_usecases[] = {
4762 USECASE_AUDIO_RECORD,
4763 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
4764 };
4765 /* should be the usecases enabled in adev_open_output_stream()*/
4766 static const int test_out_usecases[] = {
4767 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
4768 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
4769 };
4770 static const usecase_type_t usecase_type_by_dir[] = {
4771 PCM_PLAYBACK,
4772 PCM_CAPTURE,
4773 };
4774 static const unsigned flags_by_dir[] = {
4775 PCM_OUT,
4776 PCM_IN,
4777 };
4778
4779 size_t i;
4780 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004781 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07004782 char info[512]; /* for possible debug info */
4783
4784 for (dir = 0; dir < 2; ++dir) {
4785 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
4786 const unsigned flags_dir = flags_by_dir[dir];
4787 const size_t testsize =
4788 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
4789 const int *testcases =
4790 dir ? test_in_usecases : test_out_usecases;
4791 const audio_devices_t audio_device =
4792 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
4793
4794 for (i = 0; i < testsize; ++i) {
4795 const audio_usecase_t audio_usecase = testcases[i];
4796 int device_id;
4797 snd_device_t snd_device;
4798 struct pcm_params **pparams;
4799 struct stream_out out;
4800 struct stream_in in;
4801 struct audio_usecase uc_info;
4802 int retval;
4803
4804 pparams = &adev->use_case_table[audio_usecase];
4805 pcm_params_free(*pparams); /* can accept null input */
4806 *pparams = NULL;
4807
4808 /* find the device ID for the use case (signed, for error) */
4809 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
4810 if (device_id < 0)
4811 continue;
4812
4813 /* prepare structures for device probing */
4814 memset(&uc_info, 0, sizeof(uc_info));
4815 uc_info.id = audio_usecase;
4816 uc_info.type = usecase_type;
4817 if (dir) {
4818 adev->active_input = &in;
4819 memset(&in, 0, sizeof(in));
4820 in.device = audio_device;
4821 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4822 uc_info.stream.in = &in;
4823 } else {
4824 adev->active_input = NULL;
4825 }
4826 memset(&out, 0, sizeof(out));
4827 out.devices = audio_device; /* only field needed in select_devices */
4828 uc_info.stream.out = &out;
4829 uc_info.devices = audio_device;
4830 uc_info.in_snd_device = SND_DEVICE_NONE;
4831 uc_info.out_snd_device = SND_DEVICE_NONE;
4832 list_add_tail(&adev->usecase_list, &uc_info.list);
4833
4834 /* select device - similar to start_(in/out)put_stream() */
4835 retval = select_devices(adev, audio_usecase);
4836 if (retval >= 0) {
4837 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4838#if LOG_NDEBUG == 0
4839 if (*pparams) {
4840 ALOGV("%s: (%s) card %d device %d", __func__,
4841 dir ? "input" : "output", card_id, device_id);
4842 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004843 } else {
4844 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4845 }
4846#endif
4847 }
4848
4849 /* deselect device - similar to stop_(in/out)put_stream() */
4850 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004851 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004852 /* 2. Disable the rx device */
4853 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004854 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004855 list_remove(&uc_info.list);
4856 }
4857 }
4858 adev->active_input = NULL; /* restore adev state */
4859 return 0;
4860}
4861
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004862static int adev_close(hw_device_t *device)
4863{
Andy Hung31aca912014-03-20 17:14:59 -07004864 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004865 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004866
4867 if (!adev)
4868 return 0;
4869
4870 pthread_mutex_lock(&adev_init_lock);
4871
4872 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004873 audio_extn_snd_mon_unregister_listener(adev);
4874 audio_extn_tfa_98xx_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004875 audio_route_free(adev->audio_route);
4876 free(adev->snd_dev_ref_cnt);
4877 platform_deinit(adev->platform);
4878 audio_extn_extspk_deinit(adev->extspk);
4879 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004880 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004881 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4882 pcm_params_free(adev->use_case_table[i]);
4883 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004884 if (adev->adm_deinit)
4885 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004886 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004887 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004888 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004889
4890 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004891
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004892 return 0;
4893}
4894
Glenn Kasten4f993392014-05-14 07:30:48 -07004895/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4896 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4897 * just that it _might_ work.
4898 */
4899static int period_size_is_plausible_for_low_latency(int period_size)
4900{
4901 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004902 case 48:
4903 case 96:
4904 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004905 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004906 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004907 case 240:
4908 case 320:
4909 case 480:
4910 return 1;
4911 default:
4912 return 0;
4913 }
4914}
4915
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004916static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4917{
4918 int card;
4919 card_status_t status;
4920
4921 if (!parms)
4922 return;
4923
4924 if (parse_snd_card_status(parms, &card, &status) < 0)
4925 return;
4926
4927 pthread_mutex_lock(&adev->lock);
4928 bool valid_cb = (card == adev->snd_card);
4929 if (valid_cb) {
4930 if (adev->card_status != status) {
4931 adev->card_status = status;
4932 platform_snd_card_update(adev->platform, status);
4933 }
4934 }
4935 pthread_mutex_unlock(&adev->lock);
4936 return;
4937}
4938
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004939static int adev_open(const hw_module_t *module, const char *name,
4940 hw_device_t **device)
4941{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004942 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004943
Eric Laurent2bafff12016-03-17 12:17:23 -07004944 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004945 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004946 pthread_mutex_lock(&adev_init_lock);
4947 if (audio_device_ref_count != 0) {
4948 *device = &adev->device.common;
4949 audio_device_ref_count++;
4950 ALOGV("%s: returning existing instance of adev", __func__);
4951 ALOGV("%s: exit", __func__);
4952 pthread_mutex_unlock(&adev_init_lock);
4953 return 0;
4954 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004955 adev = calloc(1, sizeof(struct audio_device));
4956
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004957 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4958
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004959 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4960 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4961 adev->device.common.module = (struct hw_module_t *)module;
4962 adev->device.common.close = adev_close;
4963
4964 adev->device.init_check = adev_init_check;
4965 adev->device.set_voice_volume = adev_set_voice_volume;
4966 adev->device.set_master_volume = adev_set_master_volume;
4967 adev->device.get_master_volume = adev_get_master_volume;
4968 adev->device.set_master_mute = adev_set_master_mute;
4969 adev->device.get_master_mute = adev_get_master_mute;
4970 adev->device.set_mode = adev_set_mode;
4971 adev->device.set_mic_mute = adev_set_mic_mute;
4972 adev->device.get_mic_mute = adev_get_mic_mute;
4973 adev->device.set_parameters = adev_set_parameters;
4974 adev->device.get_parameters = adev_get_parameters;
4975 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4976 adev->device.open_output_stream = adev_open_output_stream;
4977 adev->device.close_output_stream = adev_close_output_stream;
4978 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004979
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004980 adev->device.close_input_stream = adev_close_input_stream;
4981 adev->device.dump = adev_dump;
4982
4983 /* Set the default route before the PCM stream is opened */
4984 pthread_mutex_lock(&adev->lock);
4985 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004986 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004987 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004988 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004989 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004990 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004991 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004992 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004993 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004994 pthread_mutex_unlock(&adev->lock);
4995
4996 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004997 adev->platform = platform_init(adev);
4998 if (!adev->platform) {
4999 free(adev->snd_dev_ref_cnt);
5000 free(adev);
5001 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5002 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005003 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005004 return -EINVAL;
5005 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05005006 adev->extspk = audio_extn_extspk_init(adev);
5007
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005008 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5009 if (adev->visualizer_lib == NULL) {
5010 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5011 } else {
5012 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5013 adev->visualizer_start_output =
5014 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5015 "visualizer_hal_start_output");
5016 adev->visualizer_stop_output =
5017 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5018 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07005019 }
5020
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005021 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5022 if (adev->offload_effects_lib == NULL) {
5023 ALOGW("%s: DLOPEN failed for %s", __func__,
5024 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5025 } else {
5026 ALOGV("%s: DLOPEN successful for %s", __func__,
5027 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5028 adev->offload_effects_start_output =
5029 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5030 "offload_effects_bundle_hal_start_output");
5031 adev->offload_effects_stop_output =
5032 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5033 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07005034 }
5035
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005036 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5037 if (adev->adm_lib == NULL) {
5038 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5039 } else {
5040 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5041 adev->adm_init = (adm_init_t)
5042 dlsym(adev->adm_lib, "adm_init");
5043 adev->adm_deinit = (adm_deinit_t)
5044 dlsym(adev->adm_lib, "adm_deinit");
5045 adev->adm_register_input_stream = (adm_register_input_stream_t)
5046 dlsym(adev->adm_lib, "adm_register_input_stream");
5047 adev->adm_register_output_stream = (adm_register_output_stream_t)
5048 dlsym(adev->adm_lib, "adm_register_output_stream");
5049 adev->adm_deregister_stream = (adm_deregister_stream_t)
5050 dlsym(adev->adm_lib, "adm_deregister_stream");
5051 adev->adm_request_focus = (adm_request_focus_t)
5052 dlsym(adev->adm_lib, "adm_request_focus");
5053 adev->adm_abandon_focus = (adm_abandon_focus_t)
5054 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08005055 adev->adm_set_config = (adm_set_config_t)
5056 dlsym(adev->adm_lib, "adm_set_config");
5057 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5058 dlsym(adev->adm_lib, "adm_request_focus_v2");
5059 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5060 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5061 adev->adm_on_routing_change = (adm_on_routing_change_t)
5062 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005063 }
5064
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005065 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005066 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005067
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005068 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005069
Andy Hung31aca912014-03-20 17:14:59 -07005070 if (k_enable_extended_precision)
5071 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005072
Glenn Kasten4f993392014-05-14 07:30:48 -07005073 char value[PROPERTY_VALUE_MAX];
5074 int trial;
5075 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5076 trial = atoi(value);
5077 if (period_size_is_plausible_for_low_latency(trial)) {
5078 pcm_config_low_latency.period_size = trial;
5079 pcm_config_low_latency.start_threshold = trial / 4;
5080 pcm_config_low_latency.avail_min = trial / 4;
5081 configured_low_latency_capture_period_size = trial;
5082 }
5083 }
5084 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5085 trial = atoi(value);
5086 if (period_size_is_plausible_for_low_latency(trial)) {
5087 configured_low_latency_capture_period_size = trial;
5088 }
5089 }
5090
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005091 // commented as full set of app type cfg is sent from platform
5092 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005093 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005094
5095 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5096 af_period_multiplier = atoi(value);
5097 if (af_period_multiplier < 0) {
5098 af_period_multiplier = 2;
5099 } else if (af_period_multiplier > 4) {
5100 af_period_multiplier = 4;
5101 }
5102 ALOGV("new period_multiplier = %d", af_period_multiplier);
5103 }
5104
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005105 audio_extn_tfa_98xx_init(adev);
5106
vivek mehta1a9b7c02015-06-25 11:49:38 -07005107 pthread_mutex_unlock(&adev_init_lock);
5108
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005109 if (adev->adm_init)
5110 adev->adm_data = adev->adm_init();
5111
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005112 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005113 audio_extn_snd_mon_init();
5114 pthread_mutex_lock(&adev->lock);
5115 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
5116 adev->card_status = CARD_STATUS_ONLINE;
5117 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005118 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005119
Eric Laurent2bafff12016-03-17 12:17:23 -07005120 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005121 return 0;
5122}
5123
5124static struct hw_module_methods_t hal_module_methods = {
5125 .open = adev_open,
5126};
5127
5128struct audio_module HAL_MODULE_INFO_SYM = {
5129 .common = {
5130 .tag = HARDWARE_MODULE_TAG,
5131 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5132 .hal_api_version = HARDWARE_HAL_API_VERSION,
5133 .id = AUDIO_HARDWARE_MODULE_ID,
5134 .name = "QCOM Audio HAL",
5135 .author = "Code Aurora Forum",
5136 .methods = &hal_module_methods,
5137 },
5138};