blob: ad5d1f1d7829e45c6208641e6ea282664a38ed43 [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"
Eric Laurentb23d5282013-05-14 15:27:20 -070054#include "platform_api.h"
55#include <platform.h>
Vineeta Srivastava4b89e372014-06-19 14:21:42 -070056#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070058#include "sound/compress_params.h"
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -080059#include "audio_extn/tfa_98xx.h"
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070060
Eric Laurent397db572016-05-11 11:31:47 -070061/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
62 * COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
Marco Nelissen32093f52015-04-08 15:14:02 -070063#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070064// 2 buffers causes problems with high bitrate files
65#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066/* ToDo: Check and update a proper value in msec */
67#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
vivek mehta4a824772017-06-08 19:05:49 -070068/* treat as unsigned Q1.13 */
69#define APP_TYPE_GAIN_DEFAULT 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070070#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
vivek mehta4a824772017-06-08 19:05:49 -070071
72/* treat as unsigned Q1.13 */
vivek mehtaa68fea62017-06-08 19:04:02 -070073#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070074
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070075#define PROXY_OPEN_RETRY_COUNT 100
76#define PROXY_OPEN_WAIT_TIME 20
77
vivek mehtadae44712015-07-27 14:13:18 -070078#define MIN_CHANNEL_COUNT 1
79#define DEFAULT_CHANNEL_COUNT 2
80
Jean-Michel Trivic0750692015-10-12 12:12:32 -070081#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
82#define MAX_CHANNEL_COUNT 1
83#else
vivek mehtadae44712015-07-27 14:13:18 -070084#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
85#define XSTR(x) STR(x)
86#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070087#endif
Eric Laurent74b55762017-07-09 17:04:53 -070088#define MAX_HIFI_CHANNEL_COUNT 8
vivek mehtadae44712015-07-27 14:13:18 -070089
Haynes Mathew George03c40102016-01-29 17:57:48 -080090#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
91
Glenn Kasten4f993392014-05-14 07:30:48 -070092static unsigned int configured_low_latency_capture_period_size =
93 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
94
Eric Laurent0e46adf2016-12-16 12:49:24 -080095
96#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Phil Burkbc991042017-02-24 08:06:44 -080097#define MMAP_PERIOD_COUNT_MIN 32
98#define MMAP_PERIOD_COUNT_MAX 512
99#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
Eric Laurent0e46adf2016-12-16 12:49:24 -0800100
Andy Hungd13f0d32017-06-12 13:58:37 -0700101static const int64_t NANOS_PER_SECOND = 1000000000;
Eric Laurent0e46adf2016-12-16 12:49:24 -0800102
Andy Hung31aca912014-03-20 17:14:59 -0700103/* This constant enables extended precision handling.
104 * TODO The flag is off until more testing is done.
105 */
106static const bool k_enable_extended_precision = false;
107
Eric Laurentb23d5282013-05-14 15:27:20 -0700108struct pcm_config pcm_config_deep_buffer = {
vivek mehtadae44712015-07-27 14:13:18 -0700109 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700110 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
111 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
112 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
113 .format = PCM_FORMAT_S16_LE,
114 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
115 .stop_threshold = INT_MAX,
116 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
117};
118
119struct pcm_config pcm_config_low_latency = {
vivek mehtadae44712015-07-27 14:13:18 -0700120 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700121 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
122 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
123 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
124 .format = PCM_FORMAT_S16_LE,
125 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
126 .stop_threshold = INT_MAX,
127 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
128};
129
Haynes Mathew George03c40102016-01-29 17:57:48 -0800130static int af_period_multiplier = 4;
131struct pcm_config pcm_config_rt = {
132 .channels = DEFAULT_CHANNEL_COUNT,
133 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
134 .period_size = ULL_PERIOD_SIZE, //1 ms
135 .period_count = 512, //=> buffer size is 512ms
136 .format = PCM_FORMAT_S16_LE,
137 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
138 .stop_threshold = INT_MAX,
139 .silence_threshold = 0,
140 .silence_size = 0,
141 .avail_min = ULL_PERIOD_SIZE, //1 ms
142};
143
Eric Laurentb23d5282013-05-14 15:27:20 -0700144struct pcm_config pcm_config_hdmi_multi = {
145 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
146 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
147 .period_size = HDMI_MULTI_PERIOD_SIZE,
148 .period_count = HDMI_MULTI_PERIOD_COUNT,
149 .format = PCM_FORMAT_S16_LE,
150 .start_threshold = 0,
151 .stop_threshold = INT_MAX,
152 .avail_min = 0,
153};
154
Eric Laurent0e46adf2016-12-16 12:49:24 -0800155struct pcm_config pcm_config_mmap_playback = {
156 .channels = DEFAULT_CHANNEL_COUNT,
157 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
158 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800159 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800160 .format = PCM_FORMAT_S16_LE,
161 .start_threshold = MMAP_PERIOD_SIZE*8,
162 .stop_threshold = INT32_MAX,
163 .silence_threshold = 0,
164 .silence_size = 0,
165 .avail_min = MMAP_PERIOD_SIZE, //1 ms
166};
167
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800168struct pcm_config pcm_config_hifi = {
169 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
170 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
171 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
172 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
173 .format = PCM_FORMAT_S24_3LE,
174 .start_threshold = 0,
175 .stop_threshold = INT_MAX,
176 .avail_min = 0,
177};
178
Eric Laurentb23d5282013-05-14 15:27:20 -0700179struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700180 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700181 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
182 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700183 .stop_threshold = INT_MAX,
184 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700185};
186
Haynes Mathew George03c40102016-01-29 17:57:48 -0800187struct pcm_config pcm_config_audio_capture_rt = {
188 .channels = DEFAULT_CHANNEL_COUNT,
189 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
190 .period_size = ULL_PERIOD_SIZE,
191 .period_count = 512,
192 .format = PCM_FORMAT_S16_LE,
193 .start_threshold = 0,
194 .stop_threshold = INT_MAX,
195 .silence_threshold = 0,
196 .silence_size = 0,
197 .avail_min = ULL_PERIOD_SIZE, //1 ms
198};
199
Eric Laurent0e46adf2016-12-16 12:49:24 -0800200struct pcm_config pcm_config_mmap_capture = {
201 .channels = DEFAULT_CHANNEL_COUNT,
202 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
203 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800204 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800205 .format = PCM_FORMAT_S16_LE,
206 .start_threshold = 0,
207 .stop_threshold = INT_MAX,
208 .silence_threshold = 0,
209 .silence_size = 0,
210 .avail_min = MMAP_PERIOD_SIZE, //1 ms
211};
212
vivek mehtaa68fea62017-06-08 19:04:02 -0700213struct pcm_config pcm_config_voip = {
214 .channels = 1,
215 .period_count = 2,
216 .format = PCM_FORMAT_S16_LE,
217 .stop_threshold = INT_MAX,
218 .avail_min = 0,
219};
220
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700221#define AFE_PROXY_CHANNEL_COUNT 2
222#define AFE_PROXY_SAMPLING_RATE 48000
223
224#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
225#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
226
227struct pcm_config pcm_config_afe_proxy_playback = {
228 .channels = AFE_PROXY_CHANNEL_COUNT,
229 .rate = AFE_PROXY_SAMPLING_RATE,
230 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
231 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
232 .format = PCM_FORMAT_S16_LE,
233 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
234 .stop_threshold = INT_MAX,
235 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
236};
237
238#define AFE_PROXY_RECORD_PERIOD_SIZE 768
239#define AFE_PROXY_RECORD_PERIOD_COUNT 4
240
241struct pcm_config pcm_config_afe_proxy_record = {
242 .channels = AFE_PROXY_CHANNEL_COUNT,
243 .rate = AFE_PROXY_SAMPLING_RATE,
244 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
245 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
246 .format = PCM_FORMAT_S16_LE,
247 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
248 .stop_threshold = INT_MAX,
249 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
250};
251
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700252const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700253 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
254 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800255 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700256 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700257 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700258 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800259 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700260
Eric Laurentb23d5282013-05-14 15:27:20 -0700261 [USECASE_AUDIO_RECORD] = "audio-record",
262 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800263 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George569b7482017-05-08 14:44:27 -0700264 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700265
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800266 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
267 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700268
Eric Laurentb23d5282013-05-14 15:27:20 -0700269 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700270 [USECASE_VOICE2_CALL] = "voice2-call",
271 [USECASE_VOLTE_CALL] = "volte-call",
272 [USECASE_QCHAT_CALL] = "qchat-call",
273 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800274 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
275 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700276
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700277 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
278 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
279
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700280 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
281 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
vivek mehta781065c2017-04-04 12:55:01 -0700282
283 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
284 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
285 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
286
vivek mehtaa68fea62017-06-08 19:04:02 -0700287 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
288 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Eric Laurentb23d5282013-05-14 15:27:20 -0700289};
290
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800291
292#define STRING_TO_ENUM(string) { #string, string }
293
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800294struct string_to_enum {
295 const char *name;
296 uint32_t value;
297};
298
Haynes Mathew George569b7482017-05-08 14:44:27 -0700299static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800300 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
301 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
302 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Eric Laurent74b55762017-07-09 17:04:53 -0700303 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
Haynes Mathew George569b7482017-05-08 14:44:27 -0700304 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
Eric Laurent74b55762017-07-09 17:04:53 -0700305 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
306 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
307 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
308 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
309 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
310 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
311 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
312 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
313 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800314};
315
Haynes Mathew George5191a852013-09-11 14:19:36 -0700316static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700317static struct audio_device *adev = NULL;
Andy Hung9e737de2017-05-22 10:51:22 -0700318static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700319static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700320//cache last MBDRC cal step level
321static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700322
Haynes Mathew George03c40102016-01-29 17:57:48 -0800323static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
324 int flags __unused)
325{
326 int dir = 0;
327 switch (uc_id) {
328 case USECASE_AUDIO_RECORD_LOW_LATENCY:
329 dir = 1;
330 case USECASE_AUDIO_PLAYBACK_ULL:
331 break;
332 default:
333 return false;
334 }
335
336 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
337 PCM_PLAYBACK : PCM_CAPTURE);
338 if (adev->adm_is_noirq_avail)
339 return adev->adm_is_noirq_avail(adev->adm_data,
340 adev->snd_card, dev_id, dir);
341 return false;
342}
343
344static void register_out_stream(struct stream_out *out)
345{
346 struct audio_device *adev = out->dev;
347 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
348 return;
349
350 if (!adev->adm_register_output_stream)
351 return;
352
353 adev->adm_register_output_stream(adev->adm_data,
354 out->handle,
355 out->flags);
356
357 if (!adev->adm_set_config)
358 return;
359
360 if (out->realtime) {
361 adev->adm_set_config(adev->adm_data,
362 out->handle,
363 out->pcm, &out->config);
364 }
365}
366
367static void register_in_stream(struct stream_in *in)
368{
369 struct audio_device *adev = in->dev;
370 if (!adev->adm_register_input_stream)
371 return;
372
373 adev->adm_register_input_stream(adev->adm_data,
374 in->capture_handle,
375 in->flags);
376
377 if (!adev->adm_set_config)
378 return;
379
380 if (in->realtime) {
381 adev->adm_set_config(adev->adm_data,
382 in->capture_handle,
383 in->pcm,
384 &in->config);
385 }
386}
387
388static void request_out_focus(struct stream_out *out, long ns)
389{
390 struct audio_device *adev = out->dev;
391
Haynes Mathew George03c40102016-01-29 17:57:48 -0800392 if (adev->adm_request_focus_v2) {
393 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
394 } else if (adev->adm_request_focus) {
395 adev->adm_request_focus(adev->adm_data, out->handle);
396 }
397}
398
399static void request_in_focus(struct stream_in *in, long ns)
400{
401 struct audio_device *adev = in->dev;
402
Haynes Mathew George03c40102016-01-29 17:57:48 -0800403 if (adev->adm_request_focus_v2) {
404 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
405 } else if (adev->adm_request_focus) {
406 adev->adm_request_focus(adev->adm_data, in->capture_handle);
407 }
408}
409
410static void release_out_focus(struct stream_out *out, long ns __unused)
411{
412 struct audio_device *adev = out->dev;
413
414 if (adev->adm_abandon_focus)
415 adev->adm_abandon_focus(adev->adm_data, out->handle);
416}
417
418static void release_in_focus(struct stream_in *in, long ns __unused)
419{
420 struct audio_device *adev = in->dev;
421 if (adev->adm_abandon_focus)
422 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
423}
424
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700425static int parse_snd_card_status(struct str_parms * parms, int * card,
426 card_status_t * status)
427{
428 char value[32]={0};
429 char state[32]={0};
430
431 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
432
433 if (ret < 0)
434 return -1;
435
436 // sscanf should be okay as value is of max length 32.
437 // same as sizeof state.
438 if (sscanf(value, "%d,%s", card, state) < 2)
439 return -1;
440
441 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
442 CARD_STATUS_OFFLINE;
443 return 0;
444}
445
vivek mehta1a9b7c02015-06-25 11:49:38 -0700446__attribute__ ((visibility ("default")))
447bool audio_hw_send_gain_dep_calibration(int level) {
448 bool ret_val = false;
449 ALOGV("%s: enter ... ", __func__);
450
451 pthread_mutex_lock(&adev_init_lock);
452
453 if (adev != NULL && adev->platform != NULL) {
454 pthread_mutex_lock(&adev->lock);
455 ret_val = platform_send_gain_dep_cal(adev->platform, level);
456 pthread_mutex_unlock(&adev->lock);
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700457
458 // if cal set fails, cache level info
459 // if cal set succeds, reset known last cal set
460 if (!ret_val)
461 last_known_cal_step = level;
462 else if (last_known_cal_step != -1)
463 last_known_cal_step = -1;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700464 } else {
465 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
466 }
467
468 pthread_mutex_unlock(&adev_init_lock);
469
470 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
471 return ret_val;
472}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700473
vivek mehtaa8d7c922016-05-25 14:40:44 -0700474__attribute__ ((visibility ("default")))
475int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
476 int table_size) {
477 int ret_val = 0;
478 ALOGV("%s: enter ... ", __func__);
479
480 pthread_mutex_lock(&adev_init_lock);
481 if (adev == NULL) {
482 ALOGW("%s: adev is NULL .... ", __func__);
483 goto done;
484 }
485
486 pthread_mutex_lock(&adev->lock);
487 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
488 pthread_mutex_unlock(&adev->lock);
489done:
490 pthread_mutex_unlock(&adev_init_lock);
491 ALOGV("%s: exit ... ", __func__);
492 return ret_val;
493}
494
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700495static bool is_supported_format(audio_format_t format)
496{
Eric Laurent8251ac82014-07-23 11:00:25 -0700497 switch (format) {
498 case AUDIO_FORMAT_MP3:
499 case AUDIO_FORMAT_AAC_LC:
500 case AUDIO_FORMAT_AAC_HE_V1:
501 case AUDIO_FORMAT_AAC_HE_V2:
502 return true;
503 default:
504 break;
505 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700506 return false;
507}
508
Haynes Mathew George03c40102016-01-29 17:57:48 -0800509static inline bool is_mmap_usecase(audio_usecase_t uc_id)
510{
511 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
512 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
513}
514
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700515static int get_snd_codec_id(audio_format_t format)
516{
517 int id = 0;
518
Eric Laurent8251ac82014-07-23 11:00:25 -0700519 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700520 case AUDIO_FORMAT_MP3:
521 id = SND_AUDIOCODEC_MP3;
522 break;
523 case AUDIO_FORMAT_AAC:
524 id = SND_AUDIOCODEC_AAC;
525 break;
526 default:
527 ALOGE("%s: Unsupported audio format", __func__);
528 }
529
530 return id;
531}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800532
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800533static int audio_ssr_status(struct audio_device *adev)
534{
535 int ret = 0;
536 struct mixer_ctl *ctl;
537 const char *mixer_ctl_name = "Audio SSR Status";
538
539 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
540 ret = mixer_ctl_get_value(ctl, 0);
541 ALOGD("%s: value: %d", __func__, ret);
542 return ret;
543}
544
vivek mehta4a824772017-06-08 19:05:49 -0700545static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
546{
547 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
548}
549
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800550int enable_audio_route(struct audio_device *adev,
551 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800552{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700553 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800554 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800555
556 if (usecase == NULL)
557 return -EINVAL;
558
559 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
560
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800561 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700562 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800563 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700564 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800565
Yamit Mehtae3b99562016-09-16 22:44:00 +0530566 audio_extn_utils_send_app_type_cfg(adev, usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800567 audio_extn_utils_send_audio_calibration(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800568 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500569 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700570 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700571 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800572
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800573 ALOGV("%s: exit", __func__);
574 return 0;
575}
576
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800577int disable_audio_route(struct audio_device *adev,
578 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800579{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700580 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800581 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800582
583 if (usecase == NULL)
584 return -EINVAL;
585
586 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700587 if (usecase->type == PCM_CAPTURE)
588 snd_device = usecase->in_snd_device;
589 else
590 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800591 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500592 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700593 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700594 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800595
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800596 ALOGV("%s: exit", __func__);
597 return 0;
598}
599
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800600int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700601 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800602{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700603 int i, num_devices = 0;
604 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800605 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800606 if (snd_device < SND_DEVICE_MIN ||
607 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800608 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800609 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800610 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700611
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700612 platform_send_audio_calibration(adev->platform, snd_device);
613
vivek mehtade4849c2016-03-03 17:23:38 -0800614 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700615 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700616 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800617 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700618 }
619
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700620 /* due to the possibility of calibration overwrite between listen
621 and audio, notify sound trigger hal before audio calibration is sent */
622 audio_extn_sound_trigger_update_device_status(snd_device,
623 ST_EVENT_SND_DEVICE_BUSY);
624
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700625 if (audio_extn_spkr_prot_is_enabled())
626 audio_extn_spkr_prot_calib_cancel(adev);
627
zhaoyang yin4211fad2015-06-04 21:13:25 +0800628 audio_extn_dsm_feedback_enable(adev, snd_device, true);
629
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700630 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
631 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
632 audio_extn_spkr_prot_is_enabled()) {
633 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800634 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700635 }
636 if (audio_extn_spkr_prot_start_processing(snd_device)) {
637 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800638 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700639 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700640 } else if (platform_can_split_snd_device(snd_device,
641 &num_devices,
642 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700643 for (i = 0; i < num_devices; i++) {
644 enable_snd_device(adev, new_snd_devices[i]);
645 }
vivek mehtab6506412015-08-07 16:55:17 -0700646 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700647 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800648 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
649 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
650 ALOGE(" %s: Invalid sound device returned", __func__);
651 goto on_error;
652 }
Ed Tam70b5c142016-03-21 19:14:29 -0700653
Eric Laurent2e140aa2016-06-30 17:14:46 -0700654 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800655 audio_route_apply_and_update_path(adev->audio_route, device_name);
656 }
657on_success:
658 adev->snd_dev_ref_cnt[snd_device]++;
659 ret_val = 0;
660on_error:
661 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800662}
663
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800664int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700665 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800666{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700667 int i, num_devices = 0;
668 snd_device_t new_snd_devices[2];
669
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800670 if (snd_device < SND_DEVICE_MIN ||
671 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800672 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800673 return -EINVAL;
674 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700675 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
676 ALOGE("%s: device ref cnt is already 0", __func__);
677 return -EINVAL;
678 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800679 audio_extn_tfa_98xx_disable_speaker(snd_device);
680
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700681 adev->snd_dev_ref_cnt[snd_device]--;
682 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800683 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700684 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700685 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700686 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
687 audio_extn_spkr_prot_is_enabled()) {
688 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700689
690 // when speaker device is disabled, reset swap.
691 // will be renabled on usecase start
692 platform_set_swap_channels(adev, false);
693
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700694 } else if (platform_can_split_snd_device(snd_device,
695 &num_devices,
696 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700697 for (i = 0; i < num_devices; i++) {
698 disable_snd_device(adev, new_snd_devices[i]);
699 }
vivek mehtab6506412015-08-07 16:55:17 -0700700 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700701 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800702 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
703 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
704 ALOGE(" %s: Invalid sound device returned", __func__);
705 return -EINVAL;
706 }
707
Eric Laurent2e140aa2016-06-30 17:14:46 -0700708 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800709 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700710 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700711 audio_extn_sound_trigger_update_device_status(snd_device,
712 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700713 }
vivek mehtab6506412015-08-07 16:55:17 -0700714
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800715 return 0;
716}
717
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700718/*
719 legend:
720 uc - existing usecase
721 new_uc - new usecase
722 d1, d11, d2 - SND_DEVICE enums
723 a1, a2 - corresponding ANDROID device enums
724 B, B1, B2 - backend strings
725
726case 1
727 uc->dev d1 (a1) B1
728 new_uc->dev d1 (a1), d2 (a2) B1, B2
729
730 resolution: disable and enable uc->dev on d1
731
732case 2
733 uc->dev d1 (a1) B1
734 new_uc->dev d11 (a1) B1
735
736 resolution: need to switch uc since d1 and d11 are related
737 (e.g. speaker and voice-speaker)
738 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
739
740case 3
741 uc->dev d1 (a1) B1
742 new_uc->dev d2 (a2) B2
743
744 resolution: no need to switch uc
745
746case 4
747 uc->dev d1 (a1) B
748 new_uc->dev d2 (a2) B
749
750 resolution: disable enable uc-dev on d2 since backends match
751 we cannot enable two streams on two different devices if they
752 share the same backend. e.g. if offload is on speaker device using
753 QUAD_MI2S backend and a low-latency stream is started on voice-handset
754 using the same backend, offload must also be switched to voice-handset.
755
756case 5
757 uc->dev d1 (a1) B
758 new_uc->dev d1 (a1), d2 (a2) B
759
760 resolution: disable enable uc-dev on d2 since backends match
761 we cannot enable two streams on two different devices if they
762 share the same backend.
763
764case 6
765 uc->dev d1 a1 B1
766 new_uc->dev d2 a1 B2
767
768 resolution: no need to switch
769
770case 7
771
772 uc->dev d1 (a1), d2 (a2) B1, B2
773 new_uc->dev d1 B1
774
775 resolution: no need to switch
776
777*/
778static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
779 struct audio_usecase *new_uc,
780 snd_device_t new_snd_device)
781{
782 audio_devices_t a1 = uc->stream.out->devices;
783 audio_devices_t a2 = new_uc->stream.out->devices;
784
785 snd_device_t d1 = uc->out_snd_device;
786 snd_device_t d2 = new_snd_device;
787
788 // Treat as a special case when a1 and a2 are not disjoint
789 if ((a1 != a2) && (a1 & a2)) {
790 snd_device_t d3[2];
791 int num_devices = 0;
792 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
793 &num_devices,
794 d3);
795 if (ret < 0) {
796 if (ret != -ENOSYS) {
797 ALOGW("%s failed to split snd_device %d",
798 __func__,
799 popcount(a1) > 1 ? d1 : d2);
800 }
801 goto end;
802 }
803
804 // NB: case 7 is hypothetical and isn't a practical usecase yet.
805 // But if it does happen, we need to give priority to d2 if
806 // the combo devices active on the existing usecase share a backend.
807 // This is because we cannot have a usecase active on a combo device
808 // and a new usecase requests one device in this combo pair.
809 if (platform_check_backends_match(d3[0], d3[1])) {
810 return d2; // case 5
811 } else {
812 return d1; // case 1
813 }
814 } else {
815 if (platform_check_backends_match(d1, d2)) {
816 return d2; // case 2, 4
817 } else {
818 return d1; // case 6, 3
819 }
820 }
821
822end:
823 return d2; // return whatever was calculated before.
824}
825
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700826static void check_and_route_playback_usecases(struct audio_device *adev,
827 struct audio_usecase *uc_info,
828 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700829{
830 struct listnode *node;
831 struct audio_usecase *usecase;
832 bool switch_device[AUDIO_USECASE_MAX];
833 int i, num_uc_to_switch = 0;
834
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700835 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
836 uc_info,
837 snd_device);
David Linee3fe402017-03-13 10:00:42 -0700838
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700839 /*
840 * This function is to make sure that all the usecases that are active on
841 * the hardware codec backend are always routed to any one device that is
842 * handled by the hardware codec.
843 * For example, if low-latency and deep-buffer usecases are currently active
844 * on speaker and out_set_parameters(headset) is received on low-latency
845 * output, then we have to make sure deep-buffer is also switched to headset,
846 * because of the limitation that both the devices cannot be enabled
847 * at the same time as they share the same backend.
848 */
849 /* Disable all the usecases on the shared backend other than the
850 specified usecase */
851 for (i = 0; i < AUDIO_USECASE_MAX; i++)
852 switch_device[i] = false;
853
854 list_for_each(node, &adev->usecase_list) {
855 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700856 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
857 continue;
858
859 if (force_routing ||
860 (usecase->out_snd_device != snd_device &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -0700861 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
862 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700863 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700864 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
865 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700866 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700867 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700868 switch_device[usecase->id] = true;
869 num_uc_to_switch++;
870 }
871 }
872
873 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700874 list_for_each(node, &adev->usecase_list) {
875 usecase = node_to_item(node, struct audio_usecase, list);
876 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700877 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900878 }
879 }
880
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700881 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900882 list_for_each(node, &adev->usecase_list) {
883 usecase = node_to_item(node, struct audio_usecase, list);
884 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700885 d_device = derive_playback_snd_device(usecase, uc_info,
886 snd_device);
887 enable_snd_device(adev, d_device);
888 /* Update the out_snd_device before enabling the audio route */
889 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700890 }
891 }
892
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700893 /* Re-route all the usecases on the shared backend other than the
894 specified usecase to new snd devices */
895 list_for_each(node, &adev->usecase_list) {
896 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700897 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700898 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700899 }
900 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700901 }
902}
903
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700904static void check_and_route_capture_usecases(struct audio_device *adev,
905 struct audio_usecase *uc_info,
906 snd_device_t snd_device)
907{
908 struct listnode *node;
909 struct audio_usecase *usecase;
910 bool switch_device[AUDIO_USECASE_MAX];
911 int i, num_uc_to_switch = 0;
912
vivek mehta4ed66e62016-04-15 23:33:34 -0700913 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
914
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700915 /*
916 * This function is to make sure that all the active capture usecases
917 * are always routed to the same input sound device.
918 * For example, if audio-record and voice-call usecases are currently
919 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
920 * is received for voice call then we have to make sure that audio-record
921 * usecase is also switched to earpiece i.e. voice-dmic-ef,
922 * because of the limitation that two devices cannot be enabled
923 * at the same time if they share the same backend.
924 */
925 for (i = 0; i < AUDIO_USECASE_MAX; i++)
926 switch_device[i] = false;
927
928 list_for_each(node, &adev->usecase_list) {
929 usecase = node_to_item(node, struct audio_usecase, list);
930 if (usecase->type != PCM_PLAYBACK &&
931 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700932 usecase->in_snd_device != snd_device &&
933 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700934 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
935 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700936 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700937 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700938 switch_device[usecase->id] = true;
939 num_uc_to_switch++;
940 }
941 }
942
943 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700944 list_for_each(node, &adev->usecase_list) {
945 usecase = node_to_item(node, struct audio_usecase, list);
946 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700947 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700948 }
949 }
950
951 list_for_each(node, &adev->usecase_list) {
952 usecase = node_to_item(node, struct audio_usecase, list);
953 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700954 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700955 }
956 }
957
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700958 /* Re-route all the usecases on the shared backend other than the
959 specified usecase to new snd devices */
960 list_for_each(node, &adev->usecase_list) {
961 usecase = node_to_item(node, struct audio_usecase, list);
962 /* Update the in_snd_device only before enabling the audio route */
963 if (switch_device[usecase->id] ) {
964 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700965 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700966 }
967 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700968 }
969}
970
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800971/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700972static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800973{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700974 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700975 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800976
977 switch (channels) {
978 /*
979 * Do not handle stereo output in Multi-channel cases
980 * Stereo case is handled in normal playback path
981 */
982 case 6:
983 ALOGV("%s: HDMI supports 5.1", __func__);
984 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
985 break;
986 case 8:
987 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
988 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
989 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
990 break;
991 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700992 ALOGE("HDMI does not support multi channel playback");
993 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800994 break;
995 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700996 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800997}
998
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -0700999static ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1000 uint32_t *supported_sample_rates __unused,
1001 uint32_t max_rates __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001002{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001003 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1004 supported_sample_rates,
1005 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001006#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001007 for (ssize_t i=0; i<count; i++) {
1008 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1009 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001010 }
1011#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001012 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001013}
1014
Haynes Mathew George569b7482017-05-08 14:44:27 -07001015static int read_usb_sup_channel_masks(bool is_playback,
1016 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001017 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001018{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001019 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001020 int channel_count;
1021 uint32_t num_masks = 0;
1022 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1023 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001024 }
Eric Laurent74b55762017-07-09 17:04:53 -07001025 if (is_playback) {
1026 // For playback we never report mono because the framework always outputs stereo
1027 channel_count = DEFAULT_CHANNEL_COUNT;
1028 // audio_channel_out_mask_from_count() does return positional masks for channel counts
1029 // above 2 but we want indexed masks here. So we
1030 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1031 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1032 }
1033 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1034 supported_channel_masks[num_masks++] =
1035 audio_channel_mask_for_index_assignment_from_count(channel_count);
1036 }
1037 } else {
1038 // For capture we report all supported channel masks from 1 channel up.
1039 channel_count = MIN_CHANNEL_COUNT;
1040 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1041 // indexed mask
1042 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1043 supported_channel_masks[num_masks++] =
1044 audio_channel_in_mask_from_count(channel_count);
1045 }
1046 }
1047 ALOGV("%s: %s supported ch %d supported_channel_masks[0] %08x num_masks %d", __func__,
1048 is_playback ? "P" : "C", channels, supported_channel_masks[0], num_masks);
1049 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001050}
1051
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001052static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001053 audio_format_t *supported_formats,
1054 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001055{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001056 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001057 switch (bitwidth) {
1058 case 24:
1059 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001060 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001061 break;
1062 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001063 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001064 break;
1065 case 16:
1066 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001067 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001068 break;
1069 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001070 ALOGV("%s: %s supported format %d", __func__,
1071 is_playback ? "P" : "C", bitwidth);
1072 return 1;
1073}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001074
Haynes Mathew George569b7482017-05-08 14:44:27 -07001075static int read_usb_sup_params_and_compare(bool is_playback,
1076 audio_format_t *format,
1077 audio_format_t *supported_formats,
1078 uint32_t max_formats,
1079 audio_channel_mask_t *mask,
1080 audio_channel_mask_t *supported_channel_masks,
1081 uint32_t max_masks,
1082 uint32_t *rate,
1083 uint32_t *supported_sample_rates,
1084 uint32_t max_rates) {
1085 int ret = 0;
1086 int num_formats;
1087 int num_masks;
1088 int num_rates;
1089 int i;
1090
1091 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1092 max_formats);
1093 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1094 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001095
Haynes Mathew George569b7482017-05-08 14:44:27 -07001096 num_rates = read_usb_sup_sample_rates(is_playback,
1097 supported_sample_rates, max_rates);
1098
1099#define LUT(table, len, what, dflt) \
1100 for (i=0; i<len && (table[i] != what); i++); \
1101 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1102
1103 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1104 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1105 LUT(supported_sample_rates, num_rates, *rate, 0);
1106
1107#undef LUT
1108 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001109}
1110
Andy Hungd9653bd2017-08-01 19:31:39 -07001111static bool is_usb_ready(struct audio_device *adev, bool is_playback)
1112{
1113 // Check if usb is ready.
1114 // The usb device may have been removed quickly after insertion and hence
1115 // no longer available. This will show up as empty channel masks, or rates.
1116
1117 pthread_mutex_lock(&adev->lock);
1118 uint32_t supported_sample_rate;
1119
1120 // we consider usb ready if we can fetch at least one sample rate.
1121 const bool ready = read_usb_sup_sample_rates(
1122 is_playback, &supported_sample_rate, 1 /* max_rates */) > 0;
1123 pthread_mutex_unlock(&adev->lock);
1124 return ready;
1125}
1126
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001127static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1128{
1129 struct audio_usecase *usecase;
1130 struct listnode *node;
1131
1132 list_for_each(node, &adev->usecase_list) {
1133 usecase = node_to_item(node, struct audio_usecase, list);
1134 if (usecase->type == VOICE_CALL) {
1135 ALOGV("%s: usecase id %d", __func__, usecase->id);
1136 return usecase->id;
1137 }
1138 }
1139 return USECASE_INVALID;
1140}
1141
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001142struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1143 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001144{
1145 struct audio_usecase *usecase;
1146 struct listnode *node;
1147
1148 list_for_each(node, &adev->usecase_list) {
1149 usecase = node_to_item(node, struct audio_usecase, list);
1150 if (usecase->id == uc_id)
1151 return usecase;
1152 }
1153 return NULL;
1154}
1155
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001156int select_devices(struct audio_device *adev,
1157 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001158{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001159 snd_device_t out_snd_device = SND_DEVICE_NONE;
1160 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001161 struct audio_usecase *usecase = NULL;
1162 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001163 struct audio_usecase *hfp_usecase = NULL;
1164 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001165 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001166 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001167
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001168 usecase = get_usecase_from_list(adev, uc_id);
1169 if (usecase == NULL) {
1170 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1171 return -EINVAL;
1172 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001173
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001174 if ((usecase->type == VOICE_CALL) ||
1175 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001176 out_snd_device = platform_get_output_snd_device(adev->platform,
1177 usecase->stream.out->devices);
1178 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001179 usecase->devices = usecase->stream.out->devices;
1180 } else {
1181 /*
1182 * If the voice call is active, use the sound devices of voice call usecase
1183 * so that it would not result any device switch. All the usecases will
1184 * be switched to new device when select_devices() is called for voice call
1185 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001186 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001187 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001188 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001189 vc_usecase = get_usecase_from_list(adev,
1190 get_voice_usecase_id_from_list(adev));
1191 if ((vc_usecase != NULL) &&
1192 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1193 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001194 in_snd_device = vc_usecase->in_snd_device;
1195 out_snd_device = vc_usecase->out_snd_device;
1196 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001197 } else if (audio_extn_hfp_is_active(adev)) {
1198 hfp_ucid = audio_extn_hfp_get_usecase();
1199 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1200 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1201 in_snd_device = hfp_usecase->in_snd_device;
1202 out_snd_device = hfp_usecase->out_snd_device;
1203 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001204 }
1205 if (usecase->type == PCM_PLAYBACK) {
1206 usecase->devices = usecase->stream.out->devices;
1207 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001208 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001209 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001210 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001211 if (usecase->stream.out == adev->primary_output &&
1212 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001213 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1214 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001215 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001216 select_devices(adev, adev->active_input->usecase);
1217 }
1218 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001219 } else if (usecase->type == PCM_CAPTURE) {
1220 usecase->devices = usecase->stream.in->device;
1221 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001222 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001223 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001224 if (adev->active_input &&
1225 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1226 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001227 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001228 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1229 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
1230 } else if (adev->primary_output) {
1231 out_device = adev->primary_output->devices;
1232 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001233 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001234 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001235 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001236 }
1237 }
1238
1239 if (out_snd_device == usecase->out_snd_device &&
1240 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001241 return 0;
1242 }
1243
Eric Laurent2bafff12016-03-17 12:17:23 -07001244 if (out_snd_device != SND_DEVICE_NONE &&
1245 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1246 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1247 __func__,
1248 use_case_table[uc_id],
1249 adev->last_logged_snd_device[uc_id][0],
1250 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1251 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1252 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1253 -1,
1254 out_snd_device,
1255 platform_get_snd_device_name(out_snd_device),
1256 platform_get_snd_device_acdb_id(out_snd_device));
1257 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1258 }
1259 if (in_snd_device != SND_DEVICE_NONE &&
1260 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1261 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1262 __func__,
1263 use_case_table[uc_id],
1264 adev->last_logged_snd_device[uc_id][1],
1265 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1266 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1267 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1268 -1,
1269 in_snd_device,
1270 platform_get_snd_device_name(in_snd_device),
1271 platform_get_snd_device_acdb_id(in_snd_device));
1272 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1273 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001274
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001275 /*
1276 * Limitation: While in call, to do a device switch we need to disable
1277 * and enable both RX and TX devices though one of them is same as current
1278 * device.
1279 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001280 if ((usecase->type == VOICE_CALL) &&
1281 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1282 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001283 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001284 /* Disable sidetone only if voice call already exists */
1285 if (voice_is_call_state_active(adev))
1286 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001287 }
1288
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001289 /* Disable current sound devices */
1290 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001291 disable_audio_route(adev, usecase);
1292 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001293 }
1294
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001295 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001296 disable_audio_route(adev, usecase);
1297 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001298 }
1299
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001300 /* Applicable only on the targets that has external modem.
1301 * New device information should be sent to modem before enabling
1302 * the devices to reduce in-call device switch time.
1303 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001304 if ((usecase->type == VOICE_CALL) &&
1305 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1306 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001307 status = platform_switch_voice_call_enable_device_config(adev->platform,
1308 out_snd_device,
1309 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001310 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001311
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001312 /* Enable new sound devices */
1313 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001314 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Eric Laurent99dab492017-06-17 15:19:08 -07001315 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001316 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001317 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001318 }
1319
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001320 if (in_snd_device != SND_DEVICE_NONE) {
1321 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001322 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001323 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001324
Eric Laurentb23d5282013-05-14 15:27:20 -07001325 if (usecase->type == VOICE_CALL)
1326 status = platform_switch_voice_call_device_post(adev->platform,
1327 out_snd_device,
1328 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001329
sangwoo170731f2013-06-08 15:36:36 +09001330 usecase->in_snd_device = in_snd_device;
1331 usecase->out_snd_device = out_snd_device;
1332
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001333 audio_extn_tfa_98xx_set_mode();
1334
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001335 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001336
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001337 /* Applicable only on the targets that has external modem.
1338 * Enable device command should be sent to modem only after
1339 * enabling voice call mixer controls
1340 */
vivek mehta765eb642015-08-07 19:46:06 -07001341 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001342 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1343 out_snd_device,
1344 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001345 /* Enable sidetone only if voice call already exists */
1346 if (voice_is_call_state_active(adev))
1347 voice_set_sidetone(adev, out_snd_device, true);
1348 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001349
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001350 return status;
1351}
1352
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001353static int stop_input_stream(struct stream_in *in)
1354{
1355 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001356 struct audio_usecase *uc_info;
1357 struct audio_device *adev = in->dev;
1358
Eric Laurent994a6932013-07-17 11:51:42 -07001359 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001360 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001361
1362 if (adev->active_input) {
1363 if (adev->active_input->usecase == in->usecase) {
1364 adev->active_input = NULL;
1365 } else {
1366 ALOGW("%s adev->active_input->usecase %s, v/s in->usecase %s",
1367 __func__,
1368 use_case_table[adev->active_input->usecase],
1369 use_case_table[in->usecase]);
1370 }
1371 }
1372
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001373 uc_info = get_usecase_from_list(adev, in->usecase);
1374 if (uc_info == NULL) {
1375 ALOGE("%s: Could not find the usecase (%d) in the list",
1376 __func__, in->usecase);
1377 return -EINVAL;
1378 }
1379
vivek mehta781065c2017-04-04 12:55:01 -07001380 /* Close in-call recording streams */
1381 voice_check_and_stop_incall_rec_usecase(adev, in);
1382
Eric Laurent150dbfe2013-02-27 14:31:02 -08001383 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001384 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001385
1386 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001387 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001388
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001389 list_remove(&uc_info->list);
1390 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001391
Eric Laurent994a6932013-07-17 11:51:42 -07001392 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001393 return ret;
1394}
1395
1396int start_input_stream(struct stream_in *in)
1397{
1398 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001399 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001400 struct audio_usecase *uc_info;
1401 struct audio_device *adev = in->dev;
1402
Eric Laurent994a6932013-07-17 11:51:42 -07001403 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001404
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001405 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1406 return -EIO;
1407
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001408 if (in->card_status == CARD_STATUS_OFFLINE ||
1409 adev->card_status == CARD_STATUS_OFFLINE) {
1410 ALOGW("in->card_status or adev->card_status offline, try again");
1411 ret = -EAGAIN;
1412 goto error_config;
1413 }
1414
vivek mehta781065c2017-04-04 12:55:01 -07001415 /* Check if source matches incall recording usecase criteria */
1416 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1417 if (ret)
1418 goto error_config;
1419 else
1420 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1421
Eric Laurentb23d5282013-05-14 15:27:20 -07001422 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001423 if (in->pcm_device_id < 0) {
1424 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1425 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001426 ret = -EINVAL;
1427 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001428 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001429
1430 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001431 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1432 uc_info->id = in->usecase;
1433 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001434 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001435 uc_info->devices = in->device;
1436 uc_info->in_snd_device = SND_DEVICE_NONE;
1437 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001438
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001439 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001440
1441 audio_extn_perf_lock_acquire();
1442
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001443 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001444
Eric Laurent0e46adf2016-12-16 12:49:24 -08001445 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001446 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001447 ALOGE("%s: pcm stream not ready", __func__);
1448 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001449 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001450 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001451 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001452 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1453 goto error_open;
1454 }
1455 } else {
1456 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1457 unsigned int pcm_open_retry_count = 0;
1458
1459 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1460 flags |= PCM_MMAP | PCM_NOIRQ;
1461 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1462 } else if (in->realtime) {
1463 flags |= PCM_MMAP | PCM_NOIRQ;
1464 }
1465
1466 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1467 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1468
1469 while (1) {
1470 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1471 flags, &in->config);
1472 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1473 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1474 if (in->pcm != NULL) {
1475 pcm_close(in->pcm);
1476 in->pcm = NULL;
1477 }
1478 if (pcm_open_retry_count-- == 0) {
1479 ret = -EIO;
1480 goto error_open;
1481 }
1482 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1483 continue;
1484 }
1485 break;
1486 }
1487
1488 ALOGV("%s: pcm_prepare", __func__);
1489 ret = pcm_prepare(in->pcm);
1490 if (ret < 0) {
1491 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001492 pcm_close(in->pcm);
1493 in->pcm = NULL;
1494 goto error_open;
1495 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001496 if (in->realtime) {
1497 ret = pcm_start(in->pcm);
1498 if (ret < 0) {
1499 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1500 pcm_close(in->pcm);
1501 in->pcm = NULL;
1502 goto error_open;
1503 }
1504 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001505 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001506 register_in_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001507 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001508 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001509
Eric Laurent0e46adf2016-12-16 12:49:24 -08001510 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001511
1512error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001513 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001514 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001515
1516error_config:
1517 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001518 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001519 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001520}
1521
Eric Laurenta1478072015-09-21 17:21:52 -07001522void lock_input_stream(struct stream_in *in)
1523{
1524 pthread_mutex_lock(&in->pre_lock);
1525 pthread_mutex_lock(&in->lock);
1526 pthread_mutex_unlock(&in->pre_lock);
1527}
1528
1529void lock_output_stream(struct stream_out *out)
1530{
1531 pthread_mutex_lock(&out->pre_lock);
1532 pthread_mutex_lock(&out->lock);
1533 pthread_mutex_unlock(&out->pre_lock);
1534}
1535
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001536/* must be called with out->lock locked */
1537static int send_offload_cmd_l(struct stream_out* out, int command)
1538{
1539 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1540
1541 ALOGVV("%s %d", __func__, command);
1542
1543 cmd->cmd = command;
1544 list_add_tail(&out->offload_cmd_list, &cmd->node);
1545 pthread_cond_signal(&out->offload_cond);
1546 return 0;
1547}
1548
1549/* must be called iwth out->lock locked */
1550static void stop_compressed_output_l(struct stream_out *out)
1551{
1552 out->offload_state = OFFLOAD_STATE_IDLE;
1553 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001554 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001555 if (out->compr != NULL) {
1556 compress_stop(out->compr);
1557 while (out->offload_thread_blocked) {
1558 pthread_cond_wait(&out->cond, &out->lock);
1559 }
1560 }
1561}
1562
1563static void *offload_thread_loop(void *context)
1564{
1565 struct stream_out *out = (struct stream_out *) context;
1566 struct listnode *item;
1567
1568 out->offload_state = OFFLOAD_STATE_IDLE;
1569 out->playback_started = 0;
1570
1571 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1572 set_sched_policy(0, SP_FOREGROUND);
1573 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1574
1575 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001576 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001577 for (;;) {
1578 struct offload_cmd *cmd = NULL;
1579 stream_callback_event_t event;
1580 bool send_callback = false;
1581
1582 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1583 __func__, list_empty(&out->offload_cmd_list),
1584 out->offload_state);
1585 if (list_empty(&out->offload_cmd_list)) {
1586 ALOGV("%s SLEEPING", __func__);
1587 pthread_cond_wait(&out->offload_cond, &out->lock);
1588 ALOGV("%s RUNNING", __func__);
1589 continue;
1590 }
1591
1592 item = list_head(&out->offload_cmd_list);
1593 cmd = node_to_item(item, struct offload_cmd, node);
1594 list_remove(item);
1595
1596 ALOGVV("%s STATE %d CMD %d out->compr %p",
1597 __func__, out->offload_state, cmd->cmd, out->compr);
1598
1599 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1600 free(cmd);
1601 break;
1602 }
1603
1604 if (out->compr == NULL) {
1605 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001606 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001607 pthread_cond_signal(&out->cond);
1608 continue;
1609 }
1610 out->offload_thread_blocked = true;
1611 pthread_mutex_unlock(&out->lock);
1612 send_callback = false;
1613 switch(cmd->cmd) {
1614 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1615 compress_wait(out->compr, -1);
1616 send_callback = true;
1617 event = STREAM_CBK_EVENT_WRITE_READY;
1618 break;
1619 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001620 compress_next_track(out->compr);
1621 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001622 send_callback = true;
1623 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001624 /* Resend the metadata for next iteration */
1625 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001626 break;
1627 case OFFLOAD_CMD_DRAIN:
1628 compress_drain(out->compr);
1629 send_callback = true;
1630 event = STREAM_CBK_EVENT_DRAIN_READY;
1631 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001632 case OFFLOAD_CMD_ERROR:
1633 send_callback = true;
1634 event = STREAM_CBK_EVENT_ERROR;
1635 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001636 default:
1637 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1638 break;
1639 }
Eric Laurenta1478072015-09-21 17:21:52 -07001640 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001641 out->offload_thread_blocked = false;
1642 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001643 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001644 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001645 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001646 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001647 free(cmd);
1648 }
1649
1650 pthread_cond_signal(&out->cond);
1651 while (!list_empty(&out->offload_cmd_list)) {
1652 item = list_head(&out->offload_cmd_list);
1653 list_remove(item);
1654 free(node_to_item(item, struct offload_cmd, node));
1655 }
1656 pthread_mutex_unlock(&out->lock);
1657
1658 return NULL;
1659}
1660
1661static int create_offload_callback_thread(struct stream_out *out)
1662{
1663 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1664 list_init(&out->offload_cmd_list);
1665 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1666 offload_thread_loop, out);
1667 return 0;
1668}
1669
1670static int destroy_offload_callback_thread(struct stream_out *out)
1671{
Eric Laurenta1478072015-09-21 17:21:52 -07001672 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001673 stop_compressed_output_l(out);
1674 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1675
1676 pthread_mutex_unlock(&out->lock);
1677 pthread_join(out->offload_thread, (void **) NULL);
1678 pthread_cond_destroy(&out->offload_cond);
1679
1680 return 0;
1681}
1682
Eric Laurent07eeafd2013-10-06 12:52:49 -07001683static bool allow_hdmi_channel_config(struct audio_device *adev)
1684{
1685 struct listnode *node;
1686 struct audio_usecase *usecase;
1687 bool ret = true;
1688
1689 list_for_each(node, &adev->usecase_list) {
1690 usecase = node_to_item(node, struct audio_usecase, list);
1691 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1692 /*
1693 * If voice call is already existing, do not proceed further to avoid
1694 * disabling/enabling both RX and TX devices, CSD calls, etc.
1695 * Once the voice call done, the HDMI channels can be configured to
1696 * max channels of remaining use cases.
1697 */
1698 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001699 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001700 __func__);
1701 ret = false;
1702 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001703 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1704 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001705 "no change in HDMI channels", __func__);
1706 ret = false;
1707 break;
1708 }
1709 }
1710 }
1711 return ret;
1712}
1713
1714static int check_and_set_hdmi_channels(struct audio_device *adev,
1715 unsigned int channels)
1716{
1717 struct listnode *node;
1718 struct audio_usecase *usecase;
1719
1720 /* Check if change in HDMI channel config is allowed */
1721 if (!allow_hdmi_channel_config(adev))
1722 return 0;
1723
1724 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001725 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001726 return 0;
1727 }
1728
1729 platform_set_hdmi_channels(adev->platform, channels);
1730 adev->cur_hdmi_channels = channels;
1731
1732 /*
1733 * Deroute all the playback streams routed to HDMI so that
1734 * the back end is deactivated. Note that backend will not
1735 * be deactivated if any one stream is connected to it.
1736 */
1737 list_for_each(node, &adev->usecase_list) {
1738 usecase = node_to_item(node, struct audio_usecase, list);
1739 if (usecase->type == PCM_PLAYBACK &&
1740 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001741 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001742 }
1743 }
1744
1745 /*
1746 * Enable all the streams disabled above. Now the HDMI backend
1747 * will be activated with new channel configuration
1748 */
1749 list_for_each(node, &adev->usecase_list) {
1750 usecase = node_to_item(node, struct audio_usecase, list);
1751 if (usecase->type == PCM_PLAYBACK &&
1752 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001753 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001754 }
1755 }
1756
1757 return 0;
1758}
1759
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001760static int stop_output_stream(struct stream_out *out)
1761{
1762 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001763 struct audio_usecase *uc_info;
1764 struct audio_device *adev = out->dev;
1765
Eric Laurent994a6932013-07-17 11:51:42 -07001766 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001767 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001768 uc_info = get_usecase_from_list(adev, out->usecase);
1769 if (uc_info == NULL) {
1770 ALOGE("%s: Could not find the usecase (%d) in the list",
1771 __func__, out->usecase);
1772 return -EINVAL;
1773 }
1774
Haynes Mathew George41f86652014-06-17 14:22:15 -07001775 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1776 if (adev->visualizer_stop_output != NULL)
1777 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1778 if (adev->offload_effects_stop_output != NULL)
1779 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1780 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001781
Eric Laurent150dbfe2013-02-27 14:31:02 -08001782 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001783 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001784
1785 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001786 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001787
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001788 list_remove(&uc_info->list);
1789 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001790
Eric Laurent0499d4f2014-08-25 22:39:29 -05001791 audio_extn_extspk_update(adev->extspk);
1792
Eric Laurent07eeafd2013-10-06 12:52:49 -07001793 /* Must be called after removing the usecase from list */
1794 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1795 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07001796 else if (out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
1797 struct listnode *node;
1798 struct audio_usecase *usecase;
1799 list_for_each(node, &adev->usecase_list) {
1800 usecase = node_to_item(node, struct audio_usecase, list);
1801 if (usecase->devices & AUDIO_DEVICE_OUT_SPEAKER)
1802 select_devices(adev, usecase->id);
1803 }
1804 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001805
Eric Laurent994a6932013-07-17 11:51:42 -07001806 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001807 return ret;
1808}
1809
1810int start_output_stream(struct stream_out *out)
1811{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001812 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001813 struct audio_usecase *uc_info;
1814 struct audio_device *adev = out->dev;
1815
Eric Laurent994a6932013-07-17 11:51:42 -07001816 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001817 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001818
1819 if (out->card_status == CARD_STATUS_OFFLINE ||
1820 adev->card_status == CARD_STATUS_OFFLINE) {
1821 ALOGW("out->card_status or adev->card_status offline, try again");
1822 ret = -EAGAIN;
1823 goto error_config;
1824 }
1825
Eric Laurentb23d5282013-05-14 15:27:20 -07001826 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001827 if (out->pcm_device_id < 0) {
1828 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1829 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001830 ret = -EINVAL;
1831 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001832 }
1833
1834 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1835 uc_info->id = out->usecase;
1836 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001837 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001838 uc_info->devices = out->devices;
1839 uc_info->in_snd_device = SND_DEVICE_NONE;
1840 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001841
Eric Laurent07eeafd2013-10-06 12:52:49 -07001842 /* This must be called before adding this usecase to the list */
1843 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1844 check_and_set_hdmi_channels(adev, out->config.channels);
1845
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001846 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001847
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001848 audio_extn_perf_lock_acquire();
1849
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001850 select_devices(adev, out->usecase);
1851
Eric Laurent0499d4f2014-08-25 22:39:29 -05001852 audio_extn_extspk_update(adev->extspk);
1853
Andy Hung31aca912014-03-20 17:14:59 -07001854 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001855 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001856 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1857 out->pcm = NULL;
1858 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1859 COMPRESS_IN, &out->compr_config);
1860 if (out->compr && !is_compress_ready(out->compr)) {
1861 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1862 compress_close(out->compr);
1863 out->compr = NULL;
1864 ret = -EIO;
1865 goto error_open;
1866 }
1867 if (out->offload_callback)
1868 compress_nonblock(out->compr, out->non_blocking);
1869
1870 if (adev->visualizer_start_output != NULL)
1871 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1872 if (adev->offload_effects_start_output != NULL)
1873 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
1874 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001875 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001876 ALOGE("%s: pcm stream not ready", __func__);
1877 goto error_open;
1878 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001879 ret = pcm_start(out->pcm);
1880 if (ret < 0) {
1881 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1882 goto error_open;
1883 }
1884 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07001885 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001886 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001887
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001888 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1889 flags |= PCM_MMAP | PCM_NOIRQ;
1890 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001891 } else if (out->realtime) {
1892 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07001893 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001894
1895 while (1) {
1896 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1897 flags, &out->config);
1898 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1899 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1900 if (out->pcm != NULL) {
1901 pcm_close(out->pcm);
1902 out->pcm = NULL;
1903 }
1904 if (pcm_open_retry_count-- == 0) {
1905 ret = -EIO;
1906 goto error_open;
1907 }
1908 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1909 continue;
1910 }
1911 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001912 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001913 ALOGV("%s: pcm_prepare", __func__);
1914 if (pcm_is_ready(out->pcm)) {
1915 ret = pcm_prepare(out->pcm);
1916 if (ret < 0) {
1917 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1918 pcm_close(out->pcm);
1919 out->pcm = NULL;
1920 goto error_open;
1921 }
1922 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001923 if (out->realtime) {
1924 ret = pcm_start(out->pcm);
1925 if (ret < 0) {
1926 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1927 pcm_close(out->pcm);
1928 out->pcm = NULL;
1929 goto error_open;
1930 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001931 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001932 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001933 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001934 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001935 audio_extn_tfa_98xx_enable_speaker();
vivek mehta4a824772017-06-08 19:05:49 -07001936 audio_extn_utils_send_app_type_gain(out->dev,
1937 out->app_type_cfg.app_type,
1938 &out->app_type_cfg.gain[0]);
vivek mehtae59cfb22017-06-16 15:57:11 -07001939
1940 // consider a scenario where on pause lower layers are tear down.
1941 // so on resume, swap mixer control need to be sent only when
1942 // backend is active, hence rather than sending from enable device
1943 // sending it from start of streamtream
1944
1945 platform_set_swap_channels(adev, true);
1946
Eric Laurent994a6932013-07-17 11:51:42 -07001947 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001948 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001949error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001950 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001951 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001952error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001953 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001954}
1955
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001956static int check_input_parameters(uint32_t sample_rate,
1957 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07001958 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001959{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001960 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
1961 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07001962 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
1963 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07001964 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1965 return -EINVAL;
1966 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001967
Eric Laurent74b55762017-07-09 17:04:53 -07001968 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
1969 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001970 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07001971 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07001972 return -EINVAL;
1973 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001974
1975 switch (sample_rate) {
1976 case 8000:
1977 case 11025:
1978 case 12000:
1979 case 16000:
1980 case 22050:
1981 case 24000:
1982 case 32000:
1983 case 44100:
1984 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001985 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001986 break;
1987 default:
vivek mehtadae44712015-07-27 14:13:18 -07001988 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001989 return -EINVAL;
1990 }
1991
1992 return 0;
1993}
1994
vivek mehtaa68fea62017-06-08 19:04:02 -07001995static size_t get_stream_buffer_size(size_t duration_ms,
1996 uint32_t sample_rate,
1997 audio_format_t format,
1998 int channel_count,
1999 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002000{
2001 size_t size = 0;
2002
vivek mehtaa68fea62017-06-08 19:04:02 -07002003 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002004 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002005 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002006
2007 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002008
Glenn Kasten4f993392014-05-14 07:30:48 -07002009 /* make sure the size is multiple of 32 bytes
2010 * At 48 kHz mono 16-bit PCM:
2011 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2012 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2013 */
2014 size += 0x1f;
2015 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002016
2017 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002018}
2019
2020static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2021{
2022 struct stream_out *out = (struct stream_out *)stream;
2023
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002024 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002025}
2026
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002027static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002028{
2029 return -ENOSYS;
2030}
2031
2032static size_t out_get_buffer_size(const struct audio_stream *stream)
2033{
2034 struct stream_out *out = (struct stream_out *)stream;
2035
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002036 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2037 return out->compr_config.fragment_size;
2038 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002039 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002040 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002041}
2042
2043static uint32_t out_get_channels(const struct audio_stream *stream)
2044{
2045 struct stream_out *out = (struct stream_out *)stream;
2046
2047 return out->channel_mask;
2048}
2049
2050static audio_format_t out_get_format(const struct audio_stream *stream)
2051{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002052 struct stream_out *out = (struct stream_out *)stream;
2053
2054 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002055}
2056
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002057static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002058{
2059 return -ENOSYS;
2060}
2061
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002062/* must be called with out->lock locked */
2063static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002064{
2065 struct stream_out *out = (struct stream_out *)stream;
2066 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002067 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002068
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002069 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002070 if (adev->adm_deregister_stream)
2071 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002072 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002073 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002074 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2075 if (out->pcm) {
2076 pcm_close(out->pcm);
2077 out->pcm = NULL;
2078 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002079 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002080 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002081 out->playback_started = false;
2082 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002083 } else {
2084 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002085 out->gapless_mdata.encoder_delay = 0;
2086 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002087 if (out->compr != NULL) {
2088 compress_close(out->compr);
2089 out->compr = NULL;
2090 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002091 }
Phil Burkbc991042017-02-24 08:06:44 -08002092 if (do_stop) {
2093 stop_output_stream(out);
2094 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002095 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002096 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002097 return 0;
2098}
2099
2100static int out_standby(struct audio_stream *stream)
2101{
2102 struct stream_out *out = (struct stream_out *)stream;
2103
2104 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2105 out->usecase, use_case_table[out->usecase]);
2106
2107 lock_output_stream(out);
2108 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002109 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002110 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002111 return 0;
2112}
2113
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002114static int out_on_error(struct audio_stream *stream)
2115{
2116 struct stream_out *out = (struct stream_out *)stream;
2117 struct audio_device *adev = out->dev;
2118 bool do_standby = false;
2119
2120 lock_output_stream(out);
2121 if (!out->standby) {
2122 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2123 stop_compressed_output_l(out);
2124 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2125 } else
2126 do_standby = true;
2127 }
2128 pthread_mutex_unlock(&out->lock);
2129
2130 if (do_standby)
2131 return out_standby(&out->stream.common);
2132
2133 return 0;
2134}
2135
Andy Hung7401c7c2016-09-21 12:41:21 -07002136static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002137{
Andy Hung7401c7c2016-09-21 12:41:21 -07002138 struct stream_out *out = (struct stream_out *)stream;
2139
2140 // We try to get the lock for consistency,
2141 // but it isn't necessary for these variables.
2142 // If we're not in standby, we may be blocked on a write.
2143 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2144 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2145 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2146
2147 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002148 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002149 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002150
2151 // dump error info
2152 (void)error_log_dump(
2153 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002154
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002155 return 0;
2156}
2157
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002158static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2159{
2160 int ret = 0;
2161 char value[32];
2162 struct compr_gapless_mdata tmp_mdata;
2163
2164 if (!out || !parms) {
2165 return -EINVAL;
2166 }
2167
2168 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2169 if (ret >= 0) {
2170 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2171 } else {
2172 return -EINVAL;
2173 }
2174
2175 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2176 if (ret >= 0) {
2177 tmp_mdata.encoder_padding = atoi(value);
2178 } else {
2179 return -EINVAL;
2180 }
2181
2182 out->gapless_mdata = tmp_mdata;
2183 out->send_new_metadata = 1;
2184 ALOGV("%s new encoder delay %u and padding %u", __func__,
2185 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2186
2187 return 0;
2188}
2189
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002190static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2191{
2192 return out == adev->primary_output || out == adev->voice_tx_output;
2193}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002194
Kevin Rocard1e02c882017-08-09 15:26:07 -07002195static int get_alive_usb_card(struct str_parms* parms) {
2196 int card;
2197 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2198 !audio_extn_usb_alive(card)) {
2199 return card;
2200 }
2201 return -ENODEV;
2202}
2203
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002204static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2205{
2206 struct stream_out *out = (struct stream_out *)stream;
2207 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002208 struct audio_usecase *usecase;
2209 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002210 struct str_parms *parms;
2211 char value[32];
2212 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002213 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002214 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002215
Eric Laurent2e140aa2016-06-30 17:14:46 -07002216 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002217 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002218 parms = str_parms_create_str(kvpairs);
2219 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2220 if (ret >= 0) {
2221 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002222
Eric Laurenta1478072015-09-21 17:21:52 -07002223 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002224
2225 // The usb driver needs to be closed after usb device disconnection
2226 // otherwise audio is no longer played on the new usb devices.
2227 // By forcing the stream in standby, the usb stack refcount drops to 0
2228 // and the driver is closed.
2229 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD && val == AUDIO_DEVICE_NONE &&
2230 audio_is_usb_out_device(out->devices)) {
2231 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2232 out_standby_l(&out->stream.common);
2233 }
2234
Eric Laurent150dbfe2013-02-27 14:31:02 -08002235 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002236
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002237 /*
2238 * When HDMI cable is unplugged the music playback is paused and
2239 * the policy manager sends routing=0. But the audioflinger
2240 * continues to write data until standby time (3sec).
2241 * As the HDMI core is turned off, the write gets blocked.
2242 * Avoid this by routing audio to speaker until standby.
2243 */
2244 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2245 val == AUDIO_DEVICE_NONE) {
2246 val = AUDIO_DEVICE_OUT_SPEAKER;
2247 }
2248
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002249 audio_devices_t new_dev = val;
2250
2251 // Workaround: If routing to an non existing usb device, fail gracefully
2252 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002253 int card;
2254 if (audio_is_usb_out_device(new_dev) &&
2255 (card = get_alive_usb_card(parms)) >= 0) {
2256
2257 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002258 pthread_mutex_unlock(&adev->lock);
2259 pthread_mutex_unlock(&out->lock);
2260 status = -ENOSYS;
2261 goto routing_fail;
2262 }
2263
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002264 /*
2265 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002266 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002267 * the select_devices(). But how do we undo this?
2268 *
2269 * For example, music playback is active on headset (deep-buffer usecase)
2270 * and if we go to ringtones and select a ringtone, low-latency usecase
2271 * will be started on headset+speaker. As we can't enable headset+speaker
2272 * and headset devices at the same time, select_devices() switches the music
2273 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2274 * So when the ringtone playback is completed, how do we undo the same?
2275 *
2276 * We are relying on the out_set_parameters() call on deep-buffer output,
2277 * once the ringtone playback is ended.
2278 * NOTE: We should not check if the current devices are same as new devices.
2279 * Because select_devices() must be called to switch back the music
2280 * playback to headset.
2281 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002282 if (new_dev != AUDIO_DEVICE_NONE) {
2283 bool same_dev = out->devices == new_dev;
2284 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002285
Eric Laurenta7657192014-10-09 21:09:33 -07002286 if (output_drives_call(adev, out)) {
2287 if (!voice_is_in_call(adev)) {
2288 if (adev->mode == AUDIO_MODE_IN_CALL) {
2289 adev->current_call_output = out;
2290 ret = voice_start_call(adev);
2291 }
2292 } else {
2293 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002294 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002295 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002296 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002297
2298 if (!out->standby) {
2299 if (!same_dev) {
2300 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002301 // inform adm before actual routing to prevent glitches.
2302 if (adev->adm_on_routing_change) {
2303 adev->adm_on_routing_change(adev->adm_data,
2304 out->handle);
2305 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002306 }
2307 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002308 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002309
2310 // on device switch force swap, lower functions will make sure
2311 // to check if swap is allowed or not.
2312
2313 if (!same_dev)
2314 platform_set_swap_channels(adev, true);
vivek mehta0d3637a2016-07-24 09:32:02 -07002315 }
2316
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002317 }
2318
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002319 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002320 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002321
2322 /*handles device and call state changes*/
2323 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002324 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002325 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002326
2327 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2328 parse_compress_metadata(out, parms);
2329 }
2330
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002331 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002332 ALOGV("%s: exit: code(%d)", __func__, status);
2333 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002334}
2335
Haynes Mathew George569b7482017-05-08 14:44:27 -07002336static bool stream_get_parameter_channels(struct str_parms *query,
2337 struct str_parms *reply,
2338 audio_channel_mask_t *supported_channel_masks) {
2339 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002340 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002341 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002342 size_t i, j;
2343
2344 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2345 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002346 value[0] = '\0';
2347 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002348 while (supported_channel_masks[i] != 0) {
2349 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2350 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002351 if (!first) {
2352 strcat(value, "|");
2353 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002354 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002355 first = false;
2356 break;
2357 }
2358 }
2359 i++;
2360 }
2361 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002362 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002363 return ret >= 0;
2364}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002365
Haynes Mathew George569b7482017-05-08 14:44:27 -07002366static bool stream_get_parameter_formats(struct str_parms *query,
2367 struct str_parms *reply,
2368 audio_format_t *supported_formats) {
2369 int ret = -1;
2370 char value[256];
2371 int i;
2372
2373 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2374 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002375 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002376 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002377 case AUDIO_FORMAT_PCM_16_BIT:
2378 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2379 break;
2380 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2381 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2382 break;
2383 case AUDIO_FORMAT_PCM_32_BIT:
2384 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2385 break;
2386 default:
2387 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002388 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002389 break;
2390 }
2391 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002392 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002393 return ret >= 0;
2394}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002395
Haynes Mathew George569b7482017-05-08 14:44:27 -07002396static bool stream_get_parameter_rates(struct str_parms *query,
2397 struct str_parms *reply,
2398 uint32_t *supported_sample_rates) {
2399
2400 int i;
2401 char value[256];
2402 int ret = -1;
2403 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2404 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002405 value[0] = '\0';
2406 i=0;
2407 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002408 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002409 int avail = sizeof(value) - cursor;
2410 ret = snprintf(value + cursor, avail, "%s%d",
2411 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002412 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002413 if (ret < 0 || ret >= avail) {
2414 // if cursor is at the last element of the array
2415 // overwrite with \0 is duplicate work as
2416 // snprintf already put a \0 in place.
2417 // else
2418 // we had space to write the '|' at value[cursor]
2419 // (which will be overwritten) or no space to fill
2420 // the first element (=> cursor == 0)
2421 value[cursor] = '\0';
2422 break;
2423 }
2424 cursor += ret;
2425 ++i;
2426 }
2427 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2428 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002429 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002430 return ret >= 0;
2431}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002432
Haynes Mathew George569b7482017-05-08 14:44:27 -07002433static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2434{
2435 struct stream_out *out = (struct stream_out *)stream;
2436 struct str_parms *query = str_parms_create_str(keys);
2437 char *str;
2438 struct str_parms *reply = str_parms_create();
2439 bool replied = false;
2440 ALOGV("%s: enter: keys - %s", __func__, keys);
2441
2442 replied |= stream_get_parameter_channels(query, reply,
2443 &out->supported_channel_masks[0]);
2444 replied |= stream_get_parameter_formats(query, reply,
2445 &out->supported_formats[0]);
2446 replied |= stream_get_parameter_rates(query, reply,
2447 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002448 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002449 str = str_parms_to_str(reply);
2450 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002451 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002452 }
2453 str_parms_destroy(query);
2454 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002455 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002456 return str;
2457}
2458
2459static uint32_t out_get_latency(const struct audio_stream_out *stream)
2460{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002461 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002462 struct stream_out *out = (struct stream_out *)stream;
2463
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002464 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2465 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002466 else if ((out->realtime) ||
2467 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002468 // since the buffer won't be filled up faster than realtime,
2469 // return a smaller number
2470 period_ms = (out->af_period_multiplier * out->config.period_size *
2471 1000) / (out->config.rate);
2472 hw_delay = platform_render_latency(out->usecase)/1000;
2473 return period_ms + hw_delay;
2474 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002475
2476 return (out->config.period_count * out->config.period_size * 1000) /
2477 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002478}
2479
2480static int out_set_volume(struct audio_stream_out *stream, float left,
2481 float right)
2482{
Eric Laurenta9024de2013-04-04 09:19:12 -07002483 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002484 int volume[2];
2485
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002486 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002487 /* only take left channel into account: the API is for stereo anyway */
2488 out->muted = (left == 0.0f);
2489 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002490 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2491 const char *mixer_ctl_name = "Compress Playback Volume";
2492 struct audio_device *adev = out->dev;
2493 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002494 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2495 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002496 /* try with the control based on device id */
2497 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2498 PCM_PLAYBACK);
2499 char ctl_name[128] = {0};
2500 snprintf(ctl_name, sizeof(ctl_name),
2501 "Compress Playback %d Volume", pcm_device_id);
2502 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2503 if (!ctl) {
2504 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2505 return -EINVAL;
2506 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002507 }
2508 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2509 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2510 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2511 return 0;
vivek mehtaa68fea62017-06-08 19:04:02 -07002512 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002513 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2514 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2515 if (!out->standby) {
2516 // if in standby, cached volume will be sent after stream is opened
2517 audio_extn_utils_send_app_type_gain(out->dev,
2518 out->app_type_cfg.app_type,
2519 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002520 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002521 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002522 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002523
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002524 return -ENOSYS;
2525}
2526
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002527// note: this call is safe only if the stream_cb is
2528// removed first in close_output_stream (as is done now).
2529static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2530{
2531 if (!stream || !parms)
2532 return;
2533
2534 struct stream_out *out = (struct stream_out *)stream;
2535 struct audio_device *adev = out->dev;
2536
2537 card_status_t status;
2538 int card;
2539 if (parse_snd_card_status(parms, &card, &status) < 0)
2540 return;
2541
2542 pthread_mutex_lock(&adev->lock);
2543 bool valid_cb = (card == adev->snd_card);
2544 pthread_mutex_unlock(&adev->lock);
2545
2546 if (!valid_cb)
2547 return;
2548
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002549 lock_output_stream(out);
2550 if (out->card_status != status)
2551 out->card_status = status;
2552 pthread_mutex_unlock(&out->lock);
2553
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002554 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2555 use_case_table[out->usecase],
2556 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2557
2558 if (status == CARD_STATUS_OFFLINE)
2559 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002560
2561 return;
2562}
2563
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002564#ifdef NO_AUDIO_OUT
2565static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002566 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002567{
2568 struct stream_out *out = (struct stream_out *)stream;
2569
2570 /* No Output device supported other than BT for playback.
2571 * Sleep for the amount of buffer duration
2572 */
Eric Laurenta1478072015-09-21 17:21:52 -07002573 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002574 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2575 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002576 out_get_sample_rate(&out->stream.common));
2577 pthread_mutex_unlock(&out->lock);
2578 return bytes;
2579}
2580#endif
2581
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002582static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2583 size_t bytes)
2584{
2585 struct stream_out *out = (struct stream_out *)stream;
2586 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002587 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002588 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002589
Eric Laurenta1478072015-09-21 17:21:52 -07002590 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002591 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07002592 const size_t frame_size = audio_stream_out_frame_size(stream);
2593 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002594
Eric Laurent0e46adf2016-12-16 12:49:24 -08002595 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2596 error_code = ERROR_CODE_WRITE;
2597 goto exit;
2598 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002599 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002600 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002601 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002602 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002603 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002604 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002605 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002606 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002607 goto exit;
2608 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002609
2610 if (last_known_cal_step != -1) {
2611 ALOGD("%s: retry previous failed cal level set", __func__);
2612 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2613 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002614 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002615
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002616 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002617 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002618 if (out->send_new_metadata) {
2619 ALOGVV("send new gapless metadata");
2620 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2621 out->send_new_metadata = 0;
2622 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002623 unsigned int avail;
2624 struct timespec tstamp;
2625 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2626 /* Do not limit write size if the available frames count is unknown */
2627 if (ret != 0) {
2628 avail = bytes;
2629 }
2630 if (avail == 0) {
2631 ret = 0;
2632 } else {
2633 if (avail > bytes) {
2634 avail = bytes;
2635 }
2636 ret = compress_write(out->compr, buffer, avail);
2637 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2638 __func__, avail, ret);
2639 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002640
Eric Laurent6e895242013-09-05 16:10:57 -07002641 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002642 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2643 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002644 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002645 compress_start(out->compr);
2646 out->playback_started = 1;
2647 out->offload_state = OFFLOAD_STATE_PLAYING;
2648 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002649 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002650 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002651 } else {
2652 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002653 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002654 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002655 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002656 return ret;
2657 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002658 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002659 if (out->pcm) {
2660 if (out->muted)
2661 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002662
Eric Laurent0e46adf2016-12-16 12:49:24 -08002663 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002664
Haynes Mathew George03c40102016-01-29 17:57:48 -08002665 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2666 out->config.rate;
2667 request_out_focus(out, ns);
2668
2669 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2670 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002671 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002672 else
2673 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002674
Haynes Mathew George03c40102016-01-29 17:57:48 -08002675 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002676 } else {
2677 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002678 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002679 }
2680
2681exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002682 // For PCM we always consume the buffer and return #bytes regardless of ret.
2683 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07002684 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07002685 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002686 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07002687
Andy Hung7401c7c2016-09-21 12:41:21 -07002688 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07002689 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07002690 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2691 ALOGE_IF(out->pcm != NULL,
2692 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07002693 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002694 // usleep not guaranteed for values over 1 second but we don't limit here.
2695 }
2696 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002697
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002698 pthread_mutex_unlock(&out->lock);
2699
2700 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002701 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002702 if (sleeptime_us != 0)
2703 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002704 }
2705 return bytes;
2706}
2707
2708static int out_get_render_position(const struct audio_stream_out *stream,
2709 uint32_t *dsp_frames)
2710{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002711 struct stream_out *out = (struct stream_out *)stream;
2712 *dsp_frames = 0;
2713 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002714 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002715 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002716 unsigned long frames = 0;
2717 // TODO: check return value
2718 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2719 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002720 ALOGVV("%s rendered frames %d sample_rate %d",
2721 __func__, *dsp_frames, out->sample_rate);
2722 }
2723 pthread_mutex_unlock(&out->lock);
2724 return 0;
2725 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002726 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002727}
2728
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002729static int out_add_audio_effect(const struct audio_stream *stream __unused,
2730 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002731{
2732 return 0;
2733}
2734
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002735static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2736 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002737{
2738 return 0;
2739}
2740
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002741static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2742 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002743{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002744 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002745}
2746
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002747static int out_get_presentation_position(const struct audio_stream_out *stream,
2748 uint64_t *frames, struct timespec *timestamp)
2749{
2750 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002751 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07002752 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002753
Eric Laurenta1478072015-09-21 17:21:52 -07002754 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002755
Eric Laurent949a0892013-09-20 09:20:13 -07002756 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2757 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002758 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002759 compress_get_tstamp(out->compr, &dsp_frames,
2760 &out->sample_rate);
2761 ALOGVV("%s rendered frames %ld sample_rate %d",
2762 __func__, dsp_frames, out->sample_rate);
2763 *frames = dsp_frames;
2764 ret = 0;
2765 /* this is the best we can do */
2766 clock_gettime(CLOCK_MONOTONIC, timestamp);
2767 }
2768 } else {
2769 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002770 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002771 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2772 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002773 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002774 // This adjustment accounts for buffering after app processor.
2775 // It is based on estimated DSP latency per use case, rather than exact.
2776 signed_frames -=
2777 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2778
Eric Laurent949a0892013-09-20 09:20:13 -07002779 // It would be unusual for this value to be negative, but check just in case ...
2780 if (signed_frames >= 0) {
2781 *frames = signed_frames;
2782 ret = 0;
2783 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002784 }
2785 }
2786 }
2787
2788 pthread_mutex_unlock(&out->lock);
2789
2790 return ret;
2791}
2792
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002793static int out_set_callback(struct audio_stream_out *stream,
2794 stream_callback_t callback, void *cookie)
2795{
2796 struct stream_out *out = (struct stream_out *)stream;
2797
2798 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002799 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002800 out->offload_callback = callback;
2801 out->offload_cookie = cookie;
2802 pthread_mutex_unlock(&out->lock);
2803 return 0;
2804}
2805
2806static int out_pause(struct audio_stream_out* stream)
2807{
2808 struct stream_out *out = (struct stream_out *)stream;
2809 int status = -ENOSYS;
2810 ALOGV("%s", __func__);
2811 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002812 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002813 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2814 status = compress_pause(out->compr);
2815 out->offload_state = OFFLOAD_STATE_PAUSED;
2816 }
2817 pthread_mutex_unlock(&out->lock);
2818 }
2819 return status;
2820}
2821
2822static int out_resume(struct audio_stream_out* stream)
2823{
2824 struct stream_out *out = (struct stream_out *)stream;
2825 int status = -ENOSYS;
2826 ALOGV("%s", __func__);
2827 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2828 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002829 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002830 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2831 status = compress_resume(out->compr);
2832 out->offload_state = OFFLOAD_STATE_PLAYING;
2833 }
2834 pthread_mutex_unlock(&out->lock);
2835 }
2836 return status;
2837}
2838
2839static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2840{
2841 struct stream_out *out = (struct stream_out *)stream;
2842 int status = -ENOSYS;
2843 ALOGV("%s", __func__);
2844 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002845 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002846 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2847 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2848 else
2849 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2850 pthread_mutex_unlock(&out->lock);
2851 }
2852 return status;
2853}
2854
2855static int out_flush(struct audio_stream_out* stream)
2856{
2857 struct stream_out *out = (struct stream_out *)stream;
2858 ALOGV("%s", __func__);
2859 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002860 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002861 stop_compressed_output_l(out);
2862 pthread_mutex_unlock(&out->lock);
2863 return 0;
2864 }
2865 return -ENOSYS;
2866}
2867
Eric Laurent0e46adf2016-12-16 12:49:24 -08002868static int out_stop(const struct audio_stream_out* stream)
2869{
2870 struct stream_out *out = (struct stream_out *)stream;
2871 struct audio_device *adev = out->dev;
2872 int ret = -ENOSYS;
2873
2874 ALOGV("%s", __func__);
2875 pthread_mutex_lock(&adev->lock);
2876 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2877 out->playback_started && out->pcm != NULL) {
2878 pcm_stop(out->pcm);
2879 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08002880 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002881 }
2882 pthread_mutex_unlock(&adev->lock);
2883 return ret;
2884}
2885
2886static int out_start(const struct audio_stream_out* stream)
2887{
2888 struct stream_out *out = (struct stream_out *)stream;
2889 struct audio_device *adev = out->dev;
2890 int ret = -ENOSYS;
2891
2892 ALOGV("%s", __func__);
2893 pthread_mutex_lock(&adev->lock);
2894 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2895 !out->playback_started && out->pcm != NULL) {
2896 ret = start_output_stream(out);
2897 if (ret == 0) {
2898 out->playback_started = true;
2899 }
2900 }
2901 pthread_mutex_unlock(&adev->lock);
2902 return ret;
2903}
2904
Phil Burkbc991042017-02-24 08:06:44 -08002905/*
2906 * Modify config->period_count based on min_size_frames
2907 */
2908static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
2909{
2910 int periodCountRequested = (min_size_frames + config->period_size - 1)
2911 / config->period_size;
2912 int periodCount = MMAP_PERIOD_COUNT_MIN;
2913
2914 ALOGV("%s original config.period_size = %d config.period_count = %d",
2915 __func__, config->period_size, config->period_count);
2916
2917 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
2918 periodCount *= 2;
2919 }
2920 config->period_count = periodCount;
2921
2922 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
2923}
2924
Eric Laurent0e46adf2016-12-16 12:49:24 -08002925static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2926 int32_t min_size_frames,
2927 struct audio_mmap_buffer_info *info)
2928{
2929 struct stream_out *out = (struct stream_out *)stream;
2930 struct audio_device *adev = out->dev;
2931 int ret = 0;
2932 unsigned int offset1;
2933 unsigned int frames1;
2934 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07002935 uint32_t mmap_size;
2936 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002937
2938 ALOGV("%s", __func__);
2939 pthread_mutex_lock(&adev->lock);
2940
2941 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002942 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002943 ret = -EINVAL;
2944 goto exit;
2945 }
2946 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08002947 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002948 ret = -ENOSYS;
2949 goto exit;
2950 }
2951 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
2952 if (out->pcm_device_id < 0) {
2953 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2954 __func__, out->pcm_device_id, out->usecase);
2955 ret = -EINVAL;
2956 goto exit;
2957 }
Phil Burkbc991042017-02-24 08:06:44 -08002958
2959 adjust_mmap_period_count(&out->config, min_size_frames);
2960
Eric Laurent0e46adf2016-12-16 12:49:24 -08002961 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2962 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
2963 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2964 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
2965 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2966 step = "open";
2967 ret = -ENODEV;
2968 goto exit;
2969 }
2970 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
2971 if (ret < 0) {
2972 step = "begin";
2973 goto exit;
2974 }
2975 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07002976 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002977 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07002978 ret = platform_get_mmap_data_fd(adev->platform,
2979 out->pcm_device_id, 0 /*playback*/,
2980 &info->shared_memory_fd,
2981 &mmap_size);
2982 if (ret < 0) {
2983 // Fall back to non exclusive mode
2984 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
2985 } else {
2986 if (mmap_size < buffer_size) {
2987 step = "mmap";
2988 goto exit;
2989 }
2990 // FIXME: indicate exclusive mode support by returning a negative buffer size
2991 info->buffer_size_frames *= -1;
2992 }
2993 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002994
2995 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
2996 if (ret < 0) {
2997 step = "commit";
2998 goto exit;
2999 }
Phil Burkbc991042017-02-24 08:06:44 -08003000
3001 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003002 ret = 0;
3003
3004 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3005 __func__, info->shared_memory_address, info->buffer_size_frames);
3006
3007exit:
3008 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003009 if (out->pcm == NULL) {
3010 ALOGE("%s: %s - %d", __func__, step, ret);
3011 } else {
3012 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003013 pcm_close(out->pcm);
3014 out->pcm = NULL;
3015 }
3016 }
3017 pthread_mutex_unlock(&adev->lock);
3018 return ret;
3019}
3020
3021static int out_get_mmap_position(const struct audio_stream_out *stream,
3022 struct audio_mmap_position *position)
3023{
3024 struct stream_out *out = (struct stream_out *)stream;
3025 ALOGVV("%s", __func__);
3026 if (position == NULL) {
3027 return -EINVAL;
3028 }
3029 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
3030 return -ENOSYS;
3031 }
3032 if (out->pcm == NULL) {
3033 return -ENOSYS;
3034 }
3035
3036 struct timespec ts = { 0, 0 };
3037 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
3038 if (ret < 0) {
3039 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
3040 return ret;
3041 }
Andy Hungfc044e12017-03-20 09:24:22 -07003042 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003043 return 0;
3044}
3045
3046
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003047/** audio_stream_in implementation **/
3048static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3049{
3050 struct stream_in *in = (struct stream_in *)stream;
3051
3052 return in->config.rate;
3053}
3054
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003055static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003056{
3057 return -ENOSYS;
3058}
3059
3060static size_t in_get_buffer_size(const struct audio_stream *stream)
3061{
3062 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003063 return in->config.period_size * in->af_period_multiplier *
3064 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003065}
3066
3067static uint32_t in_get_channels(const struct audio_stream *stream)
3068{
3069 struct stream_in *in = (struct stream_in *)stream;
3070
3071 return in->channel_mask;
3072}
3073
vivek mehta4ed66e62016-04-15 23:33:34 -07003074static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003075{
vivek mehta4ed66e62016-04-15 23:33:34 -07003076 struct stream_in *in = (struct stream_in *)stream;
3077 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003078}
3079
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003080static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003081{
3082 return -ENOSYS;
3083}
3084
3085static int in_standby(struct audio_stream *stream)
3086{
3087 struct stream_in *in = (struct stream_in *)stream;
3088 struct audio_device *adev = in->dev;
3089 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003090 bool do_stop = true;
3091
Eric Laurent994a6932013-07-17 11:51:42 -07003092 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003093
3094 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003095
3096 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003097 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003098 audio_extn_sound_trigger_stop_lab(in);
3099 in->standby = true;
3100 }
3101
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003102 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003103 if (adev->adm_deregister_stream)
3104 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3105
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003106 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003107 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003108 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003109 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003110 in->capture_started = false;
3111 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003112 if (in->pcm) {
3113 pcm_close(in->pcm);
3114 in->pcm = NULL;
3115 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003116 adev->enable_voicerx = false;
3117 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003118 if (do_stop) {
3119 status = stop_input_stream(in);
3120 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003121 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003122 }
3123 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003124 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003125 return status;
3126}
3127
Andy Hungd13f0d32017-06-12 13:58:37 -07003128static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003129{
Andy Hungd13f0d32017-06-12 13:58:37 -07003130 struct stream_in *in = (struct stream_in *)stream;
3131
3132 // We try to get the lock for consistency,
3133 // but it isn't necessary for these variables.
3134 // If we're not in standby, we may be blocked on a read.
3135 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3136 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3137 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3138 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3139
3140 if (locked) {
3141 pthread_mutex_unlock(&in->lock);
3142 }
3143
3144 // dump error info
3145 (void)error_log_dump(
3146 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003147 return 0;
3148}
3149
3150static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3151{
3152 struct stream_in *in = (struct stream_in *)stream;
3153 struct audio_device *adev = in->dev;
3154 struct str_parms *parms;
3155 char *str;
3156 char value[32];
3157 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003158 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003159
Eric Laurent994a6932013-07-17 11:51:42 -07003160 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003161 parms = str_parms_create_str(kvpairs);
3162
3163 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3164
Eric Laurenta1478072015-09-21 17:21:52 -07003165 lock_input_stream(in);
3166
Eric Laurent150dbfe2013-02-27 14:31:02 -08003167 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003168 if (ret >= 0) {
3169 val = atoi(value);
3170 /* no audio source uses val == 0 */
3171 if ((in->source != val) && (val != 0)) {
3172 in->source = val;
3173 }
3174 }
3175
3176 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003177
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003178 if (ret >= 0) {
3179 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003180 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003181
3182 // Workaround: If routing to an non existing usb device, fail gracefully
3183 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003184 int card;
3185 if (audio_is_usb_in_device(val) &&
3186 (card = get_alive_usb_card(parms)) >= 0) {
3187
3188 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003189 status = -ENOSYS;
3190 } else {
3191
3192 in->device = val;
3193 /* If recording is in progress, change the tx device to new device */
3194 if (!in->standby) {
3195 ALOGV("update input routing change");
3196 // inform adm before actual routing to prevent glitches.
3197 if (adev->adm_on_routing_change) {
3198 adev->adm_on_routing_change(adev->adm_data,
3199 in->capture_handle);
3200 }
3201 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003202 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003203 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003204 }
3205 }
3206
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003207 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003208 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003209
3210 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003211 ALOGV("%s: exit: status(%d)", __func__, status);
3212 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003213}
3214
Haynes Mathew George569b7482017-05-08 14:44:27 -07003215static char* in_get_parameters(const struct audio_stream *stream,
3216 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003217{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003218 struct stream_in *in = (struct stream_in *)stream;
3219 struct str_parms *query = str_parms_create_str(keys);
3220 char *str;
3221 struct str_parms *reply = str_parms_create();
3222 bool replied = false;
3223
3224 ALOGV("%s: enter: keys - %s", __func__, keys);
3225 replied |= stream_get_parameter_channels(query, reply,
3226 &in->supported_channel_masks[0]);
3227 replied |= stream_get_parameter_formats(query, reply,
3228 &in->supported_formats[0]);
3229 replied |= stream_get_parameter_rates(query, reply,
3230 &in->supported_sample_rates[0]);
3231 if (replied) {
3232 str = str_parms_to_str(reply);
3233 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003234 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003235 }
3236 str_parms_destroy(query);
3237 str_parms_destroy(reply);
3238 ALOGV("%s: exit: returns - %s", __func__, str);
3239 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003240}
3241
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003242static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003243{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003244 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003245}
3246
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003247static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3248{
3249 if (!stream || !parms)
3250 return;
3251
3252 struct stream_in *in = (struct stream_in *)stream;
3253 struct audio_device *adev = in->dev;
3254
3255 card_status_t status;
3256 int card;
3257 if (parse_snd_card_status(parms, &card, &status) < 0)
3258 return;
3259
3260 pthread_mutex_lock(&adev->lock);
3261 bool valid_cb = (card == adev->snd_card);
3262 pthread_mutex_unlock(&adev->lock);
3263
3264 if (!valid_cb)
3265 return;
3266
3267 lock_input_stream(in);
3268 if (in->card_status != status)
3269 in->card_status = status;
3270 pthread_mutex_unlock(&in->lock);
3271
3272 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3273 use_case_table[in->usecase],
3274 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3275
3276 // a better solution would be to report error back to AF and let
3277 // it put the stream to standby
3278 if (status == CARD_STATUS_OFFLINE)
3279 in_standby(&in->stream.common);
3280
3281 return;
3282}
3283
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003284static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3285 size_t bytes)
3286{
3287 struct stream_in *in = (struct stream_in *)stream;
3288 struct audio_device *adev = in->dev;
3289 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003290 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003291 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003292
Eric Laurenta1478072015-09-21 17:21:52 -07003293 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003294 const size_t frame_size = audio_stream_in_frame_size(stream);
3295 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003296
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003297 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003298 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003299 /* Read from sound trigger HAL */
3300 audio_extn_sound_trigger_read(in, buffer, bytes);
3301 pthread_mutex_unlock(&in->lock);
3302 return bytes;
3303 }
3304
Eric Laurent0e46adf2016-12-16 12:49:24 -08003305 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3306 ret = -ENOSYS;
3307 goto exit;
3308 }
3309
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003310 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003311 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003312 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003313 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003314 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003315 goto exit;
3316 }
3317 in->standby = 0;
3318 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003319
Andy Hungd13f0d32017-06-12 13:58:37 -07003320 // errors that occur here are read errors.
3321 error_code = ERROR_CODE_READ;
3322
Haynes Mathew George03c40102016-01-29 17:57:48 -08003323 //what's the duration requested by the client?
3324 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3325 in->config.rate;
3326 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003327
Haynes Mathew George03c40102016-01-29 17:57:48 -08003328 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003329 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003330 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003331 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003332 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003333 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003334 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003335 if (ret < 0) {
3336 ALOGE("Failed to read w/err %s", strerror(errno));
3337 ret = -errno;
3338 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003339 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3340 if (bytes % 4 == 0) {
3341 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3342 int_buf_stream = buffer;
3343 for (size_t itt=0; itt < bytes/4 ; itt++) {
3344 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003345 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003346 } else {
3347 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3348 ret = -EINVAL;
3349 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003350 }
3351 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003352 }
3353
Haynes Mathew George03c40102016-01-29 17:57:48 -08003354 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003355
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003356 /*
3357 * Instead of writing zeroes here, we could trust the hardware
3358 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003359 * 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 -08003360 */
Andy Hungd13f0d32017-06-12 13:58:37 -07003361 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003362 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07003363 in->frames_muted += frames;
3364 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003365
3366exit:
3367 pthread_mutex_unlock(&in->lock);
3368
3369 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07003370 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003371 in_standby(&in->stream.common);
3372 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003373 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003374 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07003375 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08003376 }
3377 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003378 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003379 }
3380 return bytes;
3381}
3382
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003383static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003384{
3385 return 0;
3386}
3387
Andy Hung6ebe5962016-01-15 17:46:57 -08003388static int in_get_capture_position(const struct audio_stream_in *stream,
3389 int64_t *frames, int64_t *time)
3390{
3391 if (stream == NULL || frames == NULL || time == NULL) {
3392 return -EINVAL;
3393 }
3394 struct stream_in *in = (struct stream_in *)stream;
3395 int ret = -ENOSYS;
3396
3397 lock_input_stream(in);
3398 if (in->pcm) {
3399 struct timespec timestamp;
3400 unsigned int avail;
3401 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3402 *frames = in->frames_read + avail;
3403 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3404 ret = 0;
3405 }
3406 }
3407 pthread_mutex_unlock(&in->lock);
3408 return ret;
3409}
3410
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003411static int add_remove_audio_effect(const struct audio_stream *stream,
3412 effect_handle_t effect,
3413 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003414{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003415 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003416 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003417 int status = 0;
3418 effect_descriptor_t desc;
3419
3420 status = (*effect)->get_descriptor(effect, &desc);
3421 if (status != 0)
3422 return status;
3423
Eric Laurenta1478072015-09-21 17:21:52 -07003424 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003425 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003426 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003427 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003428 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003429 in->enable_aec != enable &&
3430 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3431 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003432 if (!enable)
3433 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003434 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3435 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3436 adev->enable_voicerx = enable;
3437 struct audio_usecase *usecase;
3438 struct listnode *node;
3439 list_for_each(node, &adev->usecase_list) {
3440 usecase = node_to_item(node, struct audio_usecase, list);
3441 if (usecase->type == PCM_PLAYBACK) {
3442 select_devices(adev, usecase->id);
3443 break;
3444 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003445 }
3446 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003447 if (!in->standby)
3448 select_devices(in->dev, in->usecase);
3449 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003450 if (in->enable_ns != enable &&
3451 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3452 in->enable_ns = enable;
3453 if (!in->standby)
3454 select_devices(in->dev, in->usecase);
3455 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003456 pthread_mutex_unlock(&in->dev->lock);
3457 pthread_mutex_unlock(&in->lock);
3458
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003459 return 0;
3460}
3461
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003462static int in_add_audio_effect(const struct audio_stream *stream,
3463 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003464{
Eric Laurent994a6932013-07-17 11:51:42 -07003465 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003466 return add_remove_audio_effect(stream, effect, true);
3467}
3468
3469static int in_remove_audio_effect(const struct audio_stream *stream,
3470 effect_handle_t effect)
3471{
Eric Laurent994a6932013-07-17 11:51:42 -07003472 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003473 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003474}
3475
Eric Laurent0e46adf2016-12-16 12:49:24 -08003476static int in_stop(const struct audio_stream_in* stream)
3477{
3478 struct stream_in *in = (struct stream_in *)stream;
3479 struct audio_device *adev = in->dev;
3480
3481 int ret = -ENOSYS;
3482 ALOGV("%s", __func__);
3483 pthread_mutex_lock(&adev->lock);
3484 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3485 in->capture_started && in->pcm != NULL) {
3486 pcm_stop(in->pcm);
3487 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003488 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003489 }
3490 pthread_mutex_unlock(&adev->lock);
3491 return ret;
3492}
3493
3494static int in_start(const struct audio_stream_in* stream)
3495{
3496 struct stream_in *in = (struct stream_in *)stream;
3497 struct audio_device *adev = in->dev;
3498 int ret = -ENOSYS;
3499
3500 ALOGV("%s in %p", __func__, in);
3501 pthread_mutex_lock(&adev->lock);
3502 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3503 !in->capture_started && in->pcm != NULL) {
3504 if (!in->capture_started) {
3505 ret = start_input_stream(in);
3506 if (ret == 0) {
3507 in->capture_started = true;
3508 }
3509 }
3510 }
3511 pthread_mutex_unlock(&adev->lock);
3512 return ret;
3513}
3514
3515static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3516 int32_t min_size_frames,
3517 struct audio_mmap_buffer_info *info)
3518{
3519 struct stream_in *in = (struct stream_in *)stream;
3520 struct audio_device *adev = in->dev;
3521 int ret = 0;
3522 unsigned int offset1;
3523 unsigned int frames1;
3524 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003525 uint32_t mmap_size;
3526 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003527
3528 pthread_mutex_lock(&adev->lock);
3529 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003530
Eric Laurent0e46adf2016-12-16 12:49:24 -08003531 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003532 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003533 ret = -EINVAL;
3534 goto exit;
3535 }
3536 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003537 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003538 ALOGV("%s in %p", __func__, in);
3539 ret = -ENOSYS;
3540 goto exit;
3541 }
3542 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3543 if (in->pcm_device_id < 0) {
3544 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3545 __func__, in->pcm_device_id, in->usecase);
3546 ret = -EINVAL;
3547 goto exit;
3548 }
Phil Burkbc991042017-02-24 08:06:44 -08003549
3550 adjust_mmap_period_count(&in->config, min_size_frames);
3551
Eric Laurent0e46adf2016-12-16 12:49:24 -08003552 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3553 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3554 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3555 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3556 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3557 step = "open";
3558 ret = -ENODEV;
3559 goto exit;
3560 }
3561
3562 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3563 if (ret < 0) {
3564 step = "begin";
3565 goto exit;
3566 }
3567 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003568 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003569 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003570 ret = platform_get_mmap_data_fd(adev->platform,
3571 in->pcm_device_id, 1 /*capture*/,
3572 &info->shared_memory_fd,
3573 &mmap_size);
3574 if (ret < 0) {
3575 // Fall back to non exclusive mode
3576 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3577 } else {
3578 if (mmap_size < buffer_size) {
3579 step = "mmap";
3580 goto exit;
3581 }
3582 // FIXME: indicate exclusive mode support by returning a negative buffer size
3583 info->buffer_size_frames *= -1;
3584 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08003585
Haynes Mathew George96483a22017-03-28 14:52:47 -07003586 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003587
3588 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3589 if (ret < 0) {
3590 step = "commit";
3591 goto exit;
3592 }
3593
Phil Burkbc991042017-02-24 08:06:44 -08003594 in->standby = false;
3595 ret = 0;
3596
Eric Laurent0e46adf2016-12-16 12:49:24 -08003597 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3598 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003599
3600exit:
3601 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003602 if (in->pcm == NULL) {
3603 ALOGE("%s: %s - %d", __func__, step, ret);
3604 } else {
3605 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003606 pcm_close(in->pcm);
3607 in->pcm = NULL;
3608 }
3609 }
3610 pthread_mutex_unlock(&adev->lock);
3611 return ret;
3612}
3613
3614static int in_get_mmap_position(const struct audio_stream_in *stream,
3615 struct audio_mmap_position *position)
3616{
3617 struct stream_in *in = (struct stream_in *)stream;
3618 ALOGVV("%s", __func__);
3619 if (position == NULL) {
3620 return -EINVAL;
3621 }
3622 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
3623 return -ENOSYS;
3624 }
3625 if (in->pcm == NULL) {
3626 return -ENOSYS;
3627 }
3628 struct timespec ts = { 0, 0 };
3629 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
3630 if (ret < 0) {
3631 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3632 return ret;
3633 }
Andy Hungfc044e12017-03-20 09:24:22 -07003634 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003635 return 0;
3636}
3637
3638
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003639static int adev_open_output_stream(struct audio_hw_device *dev,
3640 audio_io_handle_t handle,
3641 audio_devices_t devices,
3642 audio_output_flags_t flags,
3643 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003644 struct audio_stream_out **stream_out,
3645 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003646{
3647 struct audio_device *adev = (struct audio_device *)dev;
3648 struct stream_out *out;
3649 int i, ret;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003650 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
3651 bool is_usb_dev = audio_is_usb_out_device(devices) &&
3652 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
3653 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003654
Andy Hungd9653bd2017-08-01 19:31:39 -07003655 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
3656 return -ENOSYS;
3657 }
3658
Eric Laurent994a6932013-07-17 11:51:42 -07003659 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003660 __func__, config->sample_rate, config->channel_mask, devices, flags);
3661 *stream_out = NULL;
3662 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3663
3664 if (devices == AUDIO_DEVICE_NONE)
3665 devices = AUDIO_DEVICE_OUT_SPEAKER;
3666
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003667 out->flags = flags;
3668 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003669 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003670 out->format = config->format;
3671 out->sample_rate = config->sample_rate;
3672 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3673 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003674 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003675
3676 /* Init use case and pcm_config */
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003677 if (audio_is_linear_pcm(out->format) &&
3678 (out->flags == AUDIO_OUTPUT_FLAG_NONE ||
Haynes Mathew George569b7482017-05-08 14:44:27 -07003679 out->flags == AUDIO_OUTPUT_FLAG_DIRECT) && direct_dev) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003680 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003681 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003682 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003683 if (config->sample_rate == 0)
3684 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3685 if (config->channel_mask == 0)
3686 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3687 if (config->format == AUDIO_FORMAT_DEFAULT)
3688 config->format = AUDIO_FORMAT_PCM_16_BIT;
3689 } else if (is_usb_dev) {
3690 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
3691 &config->format,
3692 &out->supported_formats[0],
3693 MAX_SUPPORTED_FORMATS,
3694 &config->channel_mask,
3695 &out->supported_channel_masks[0],
3696 MAX_SUPPORTED_CHANNEL_MASKS,
3697 &config->sample_rate,
3698 &out->supported_sample_rates[0],
3699 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003700 ALOGV("plugged dev USB ret %d", ret);
3701 } else {
3702 ret = -1;
3703 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003704 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003705 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003706 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003707
Haynes Mathew George569b7482017-05-08 14:44:27 -07003708 out->channel_mask = config->channel_mask;
3709 out->sample_rate = config->sample_rate;
3710 out->format = config->format;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003711 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3712 // does this change?
Haynes Mathew George569b7482017-05-08 14:44:27 -07003713 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003714 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003715 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Andy Hung928efbe2017-06-12 14:05:22 -07003716 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
3717 audio_bytes_per_sample(config->format));
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003718 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003719 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003720 pthread_mutex_lock(&adev->lock);
3721 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3722 pthread_mutex_unlock(&adev->lock);
3723
3724 // reject offload during card offline to allow
3725 // fallback to s/w paths
3726 if (offline) {
3727 ret = -ENODEV;
3728 goto error_open;
3729 }
3730
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003731 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3732 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3733 ALOGE("%s: Unsupported Offload information", __func__);
3734 ret = -EINVAL;
3735 goto error_open;
3736 }
3737 if (!is_supported_format(config->offload_info.format)) {
3738 ALOGE("%s: Unsupported audio format", __func__);
3739 ret = -EINVAL;
3740 goto error_open;
3741 }
3742
3743 out->compr_config.codec = (struct snd_codec *)
3744 calloc(1, sizeof(struct snd_codec));
3745
3746 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3747 if (config->offload_info.channel_mask)
3748 out->channel_mask = config->offload_info.channel_mask;
3749 else if (config->channel_mask)
3750 out->channel_mask = config->channel_mask;
3751 out->format = config->offload_info.format;
3752 out->sample_rate = config->offload_info.sample_rate;
3753
3754 out->stream.set_callback = out_set_callback;
3755 out->stream.pause = out_pause;
3756 out->stream.resume = out_resume;
3757 out->stream.drain = out_drain;
3758 out->stream.flush = out_flush;
3759
3760 out->compr_config.codec->id =
3761 get_snd_codec_id(config->offload_info.format);
3762 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3763 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07003764 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003765 out->compr_config.codec->bit_rate =
3766 config->offload_info.bit_rate;
3767 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003768 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003769 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3770
3771 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3772 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003773
3774 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003775 create_offload_callback_thread(out);
3776 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3777 __func__, config->offload_info.version,
3778 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003779 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07003780 switch (config->sample_rate) {
3781 case 8000:
3782 case 16000:
3783 case 48000:
3784 out->sample_rate = config->sample_rate;
3785 break;
3786 default:
3787 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003788 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003789 out->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003790 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3791 out->config = pcm_config_afe_proxy_playback;
3792 adev->voice_tx_output = out;
David Lin6b00c232017-07-26 00:20:16 -07003793 } else if (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT |
3794 AUDIO_OUTPUT_FLAG_VOIP_RX)) {
vivek mehtaa68fea62017-06-08 19:04:02 -07003795 uint32_t buffer_size, frame_size;
3796 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
3797 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
3798 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
3799 out->config = pcm_config_voip;
3800 out->config.format = pcm_format_from_audio_format(config->format);
3801 out->config.rate = config->sample_rate;
3802 out->config.channels =
3803 audio_channel_count_from_out_mask(config->channel_mask);
3804 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
3805 config->sample_rate,
3806 config->format,
3807 out->config.channels,
3808 false /*is_low_latency*/);
3809 frame_size = audio_bytes_per_sample(config->format) * out->config.channels;
3810 out->config.period_size = buffer_size / frame_size;
3811 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
3812 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003813 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003814 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3815 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3816 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003817 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
3818 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3819 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003820 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3821 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003822 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003823 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003824 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3825 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3826 out->config = pcm_config_mmap_playback;
3827 out->stream.start = out_start;
3828 out->stream.stop = out_stop;
3829 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3830 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003831 } else {
3832 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3833 out->config = pcm_config_low_latency;
3834 }
3835 if (config->format != audio_format_from_pcm_format(out->config.format)) {
Haynes Mathew Georgedf0f8862017-06-28 13:36:40 -07003836 out->config.format = pcm_format_from_audio_format(config->format);
Andy Hung6fcba9c2014-03-18 11:53:32 -07003837 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003838 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003839 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003840
3841 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
3842 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
3843 (config->channel_mask != 0 && config->channel_mask != out->channel_mask)) {
3844 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
3845 __func__, config->sample_rate, config->format, config->channel_mask);
3846 config->sample_rate = out->sample_rate;
3847 config->format = out->format;
3848 config->channel_mask = out->channel_mask;
3849 ret = -EINVAL;
3850 goto error_open;
3851 }
3852
Andy Hung6fcba9c2014-03-18 11:53:32 -07003853 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3854 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003855
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003856 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003857 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003858 adev->primary_output = out;
3859 else {
3860 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003861 ret = -EEXIST;
3862 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003863 }
3864 }
3865
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003866 /* Check if this usecase is already existing */
3867 pthread_mutex_lock(&adev->lock);
3868 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3869 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003870 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003871 ret = -EEXIST;
3872 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003873 }
3874 pthread_mutex_unlock(&adev->lock);
3875
3876 out->stream.common.get_sample_rate = out_get_sample_rate;
3877 out->stream.common.set_sample_rate = out_set_sample_rate;
3878 out->stream.common.get_buffer_size = out_get_buffer_size;
3879 out->stream.common.get_channels = out_get_channels;
3880 out->stream.common.get_format = out_get_format;
3881 out->stream.common.set_format = out_set_format;
3882 out->stream.common.standby = out_standby;
3883 out->stream.common.dump = out_dump;
3884 out->stream.common.set_parameters = out_set_parameters;
3885 out->stream.common.get_parameters = out_get_parameters;
3886 out->stream.common.add_audio_effect = out_add_audio_effect;
3887 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3888 out->stream.get_latency = out_get_latency;
3889 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003890#ifdef NO_AUDIO_OUT
3891 out->stream.write = out_write_for_no_output;
3892#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003893 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003894#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003895 out->stream.get_render_position = out_get_render_position;
3896 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003897 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003898
Eric Laurent0e46adf2016-12-16 12:49:24 -08003899 if (out->realtime)
3900 out->af_period_multiplier = af_period_multiplier;
3901 else
3902 out->af_period_multiplier = 1;
3903
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003904 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003905 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003906 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003907
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003908 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003909 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003910 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3911
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003912 config->format = out->stream.common.get_format(&out->stream.common);
3913 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3914 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3915
Andy Hunga452b0a2017-03-15 14:51:15 -07003916 out->error_log = error_log_create(
3917 ERROR_LOG_ENTRIES,
3918 1000000000 /* aggregate consecutive identical errors within one second in ns */);
3919
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003920 /*
3921 By locking output stream before registering, we allow the callback
3922 to update stream's state only after stream's initial state is set to
3923 adev state.
3924 */
3925 lock_output_stream(out);
3926 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3927 pthread_mutex_lock(&adev->lock);
3928 out->card_status = adev->card_status;
3929 pthread_mutex_unlock(&adev->lock);
3930 pthread_mutex_unlock(&out->lock);
3931
vivek mehta4a824772017-06-08 19:05:49 -07003932 stream_app_type_cfg_init(&out->app_type_cfg);
3933
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003934 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003935
Eric Laurent994a6932013-07-17 11:51:42 -07003936 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003937 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003938
3939error_open:
3940 free(out);
3941 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003942 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003943 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003944}
3945
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003946static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003947 struct audio_stream_out *stream)
3948{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003949 struct stream_out *out = (struct stream_out *)stream;
3950 struct audio_device *adev = out->dev;
3951
Eric Laurent994a6932013-07-17 11:51:42 -07003952 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003953
3954 // must deregister from sndmonitor first to prevent races
3955 // between the callback and close_stream
3956 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003957 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003958 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3959 destroy_offload_callback_thread(out);
3960
3961 if (out->compr_config.codec != NULL)
3962 free(out->compr_config.codec);
3963 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003964
3965 if (adev->voice_tx_output == out)
3966 adev->voice_tx_output = NULL;
3967
Andy Hunga452b0a2017-03-15 14:51:15 -07003968 error_log_destroy(out->error_log);
3969 out->error_log = NULL;
3970
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003971 pthread_cond_destroy(&out->cond);
3972 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003973 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003974 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003975}
3976
3977static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3978{
3979 struct audio_device *adev = (struct audio_device *)dev;
3980 struct str_parms *parms;
3981 char *str;
3982 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003983 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003984 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003985 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003986
Joe Onorato188b6222016-03-01 11:02:27 -08003987 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003988
3989 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003990
3991 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003992 status = voice_set_parameters(adev, parms);
3993 if (status != 0) {
3994 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003995 }
3996
3997 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3998 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003999 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004000 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4001 adev->bluetooth_nrec = true;
4002 else
4003 adev->bluetooth_nrec = false;
4004 }
4005
4006 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4007 if (ret >= 0) {
4008 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4009 adev->screen_off = false;
4010 else
4011 adev->screen_off = true;
4012 }
4013
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004014 ret = str_parms_get_int(parms, "rotation", &val);
4015 if (ret >= 0) {
4016 bool reverse_speakers = false;
4017 switch(val) {
4018 // FIXME: note that the code below assumes that the speakers are in the correct placement
4019 // relative to the user when the device is rotated 90deg from its default rotation. This
4020 // assumption is device-specific, not platform-specific like this code.
4021 case 270:
4022 reverse_speakers = true;
4023 break;
4024 case 0:
4025 case 90:
4026 case 180:
4027 break;
4028 default:
4029 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07004030 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004031 }
Eric Laurent03f09432014-03-25 18:09:11 -07004032 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004033 // check and set swap
4034 // - check if orientation changed and speaker active
4035 // - set rotation and cache the rotation value
4036 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004037 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004038 }
4039
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004040 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4041 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004042 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004043 }
4044
David Linee3fe402017-03-13 10:00:42 -07004045 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4046 if (ret >= 0) {
4047 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004048 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004049 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4050 if (ret >= 0) {
4051 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004052 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004053 }
Eric Laurent99dab492017-06-17 15:19:08 -07004054 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004055 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4056 if (ret >= 0) {
4057 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004058 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004059 }
4060 }
4061 }
4062
4063 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4064 if (ret >= 0) {
4065 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004066 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004067 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4068 if (ret >= 0) {
4069 const int card = atoi(value);
4070
Eric Laurent99dab492017-06-17 15:19:08 -07004071 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004072 }
Eric Laurent99dab492017-06-17 15:19:08 -07004073 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004074 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4075 if (ret >= 0) {
4076 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004077 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004078 }
4079 }
4080 }
4081
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004082 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004083done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004084 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004085 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004086 ALOGV("%s: exit with code(%d)", __func__, status);
4087 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004088}
4089
4090static char* adev_get_parameters(const struct audio_hw_device *dev,
4091 const char *keys)
4092{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004093 struct audio_device *adev = (struct audio_device *)dev;
4094 struct str_parms *reply = str_parms_create();
4095 struct str_parms *query = str_parms_create_str(keys);
4096 char *str;
4097
4098 pthread_mutex_lock(&adev->lock);
4099
4100 voice_get_parameters(adev, query, reply);
4101 str = str_parms_to_str(reply);
4102 str_parms_destroy(query);
4103 str_parms_destroy(reply);
4104
4105 pthread_mutex_unlock(&adev->lock);
4106 ALOGV("%s: exit: returns - %s", __func__, str);
4107 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004108}
4109
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004110static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004111{
4112 return 0;
4113}
4114
Haynes Mathew George5191a852013-09-11 14:19:36 -07004115static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4116{
4117 int ret;
4118 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004119
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004120 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4121
Haynes Mathew George5191a852013-09-11 14:19:36 -07004122 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004123 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004124 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004125
Haynes Mathew George5191a852013-09-11 14:19:36 -07004126 return ret;
4127}
4128
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004129static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004130{
4131 return -ENOSYS;
4132}
4133
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004134static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4135 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004136{
4137 return -ENOSYS;
4138}
4139
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004140static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004141{
4142 return -ENOSYS;
4143}
4144
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004145static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004146{
4147 return -ENOSYS;
4148}
4149
4150static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4151{
4152 struct audio_device *adev = (struct audio_device *)dev;
4153
4154 pthread_mutex_lock(&adev->lock);
4155 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004156 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004157 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004158 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4159 voice_is_in_call(adev)) {
4160 voice_stop_call(adev);
4161 adev->current_call_output = NULL;
4162 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004163 }
4164 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004165
4166 audio_extn_extspk_set_mode(adev->extspk, mode);
4167
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004168 return 0;
4169}
4170
4171static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4172{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004173 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004174 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004175
Eric Laurent2bafff12016-03-17 12:17:23 -07004176 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004177 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004178 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4179 ret = audio_extn_hfp_set_mic_mute(adev, state);
4180 } else {
4181 ret = voice_set_mic_mute(adev, state);
4182 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004183 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004184 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004185
4186 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004187}
4188
4189static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4190{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004191 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004192 return 0;
4193}
4194
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004195static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004196 const struct audio_config *config)
4197{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004198 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004199
Eric Laurent74b55762017-07-09 17:04:53 -07004200 /* Don't know if USB HIFI in this context so use true to be conservative */
4201 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4202 true /*is_usb_hifi */) != 0)
4203 return 0;
4204
vivek mehtaa68fea62017-06-08 19:04:02 -07004205 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4206 config->sample_rate, config->format,
4207 channel_count,
4208 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004209}
4210
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004211static bool adev_input_allow_hifi_record(struct audio_device *adev,
4212 audio_devices_t devices,
4213 audio_input_flags_t flags,
4214 audio_source_t source) {
4215 const bool allowed = true;
4216
4217 if (!audio_is_usb_in_device(devices))
4218 return !allowed;
4219
4220 switch (flags) {
4221 case AUDIO_INPUT_FLAG_NONE:
4222 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4223 break;
4224 default:
4225 return !allowed;
4226 }
4227
4228 switch (source) {
4229 case AUDIO_SOURCE_DEFAULT:
4230 case AUDIO_SOURCE_MIC:
4231 case AUDIO_SOURCE_UNPROCESSED:
4232 break;
4233 default:
4234 return !allowed;
4235 }
4236
4237 switch (adev->mode) {
4238 case 0:
4239 break;
4240 default:
4241 return !allowed;
4242 }
4243
4244 return allowed;
4245}
4246
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004247static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004248 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004249 audio_devices_t devices,
4250 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004251 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004252 audio_input_flags_t flags,
4253 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004254 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004255{
4256 struct audio_device *adev = (struct audio_device *)dev;
4257 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004258 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004259 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004260 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004261 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004262 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4263 devices,
4264 flags,
4265 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004266 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004267 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004268
Andy Hungd9653bd2017-08-01 19:31:39 -07004269 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
4270 return -ENOSYS;
4271 }
4272
Eric Laurent74b55762017-07-09 17:04:53 -07004273 if (!(is_usb_dev && may_use_hifi_record)) {
4274 if (config->sample_rate == 0)
4275 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4276 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4277 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4278 if (config->format == AUDIO_FORMAT_DEFAULT)
4279 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004280
Eric Laurent74b55762017-07-09 17:04:53 -07004281 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
4282
4283 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
4284 return -EINVAL;
4285 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004286
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004287 if (audio_extn_tfa_98xx_is_supported() &&
4288 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004289 return -EINVAL;
4290
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004291 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4292
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004293 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004294 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004295
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004296 in->stream.common.get_sample_rate = in_get_sample_rate;
4297 in->stream.common.set_sample_rate = in_set_sample_rate;
4298 in->stream.common.get_buffer_size = in_get_buffer_size;
4299 in->stream.common.get_channels = in_get_channels;
4300 in->stream.common.get_format = in_get_format;
4301 in->stream.common.set_format = in_set_format;
4302 in->stream.common.standby = in_standby;
4303 in->stream.common.dump = in_dump;
4304 in->stream.common.set_parameters = in_set_parameters;
4305 in->stream.common.get_parameters = in_get_parameters;
4306 in->stream.common.add_audio_effect = in_add_audio_effect;
4307 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4308 in->stream.set_gain = in_set_gain;
4309 in->stream.read = in_read;
4310 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08004311 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004312
4313 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004314 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004315 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004316 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004317 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004318 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004319
Haynes Mathew George569b7482017-05-08 14:44:27 -07004320 if (is_usb_dev && may_use_hifi_record) {
4321 /* HiFi record selects an appropriate format, channel, rate combo
4322 depending on sink capabilities*/
4323 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
4324 &config->format,
4325 &in->supported_formats[0],
4326 MAX_SUPPORTED_FORMATS,
4327 &config->channel_mask,
4328 &in->supported_channel_masks[0],
4329 MAX_SUPPORTED_CHANNEL_MASKS,
4330 &config->sample_rate,
4331 &in->supported_sample_rates[0],
4332 MAX_SUPPORTED_SAMPLE_RATES);
4333 if (ret != 0) {
4334 ret = -EINVAL;
4335 goto err_open;
4336 }
Eric Laurent74b55762017-07-09 17:04:53 -07004337 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004338 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07004339 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07004340 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
4341 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
4342 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4343 bool ret_error = false;
4344 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4345 from HAL is 8_24
4346 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4347 8_24 return error indicating supported format is 8_24
4348 *> In case of any other source requesting 24 bit or float return error
4349 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07004350
vivek mehta57ff9b52016-04-28 14:13:08 -07004351 on error flinger will retry with supported format passed
4352 */
4353 if (source != AUDIO_SOURCE_UNPROCESSED) {
4354 config->format = AUDIO_FORMAT_PCM_16_BIT;
4355 ret_error = true;
4356 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
4357 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
4358 ret_error = true;
4359 }
4360
4361 if (ret_error) {
4362 ret = -EINVAL;
4363 goto err_open;
4364 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004365 }
4366
vivek mehta57ff9b52016-04-28 14:13:08 -07004367 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07004368 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07004369
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004370 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004371 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
4372 if (config->sample_rate == 0)
4373 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4374 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4375 config->sample_rate != 8000) {
4376 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4377 ret = -EINVAL;
4378 goto err_open;
4379 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004380
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004381 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4382 config->format = AUDIO_FORMAT_PCM_16_BIT;
4383 ret = -EINVAL;
4384 goto err_open;
4385 }
4386
4387 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4388 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07004389 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004390 } else if (is_usb_dev && may_use_hifi_record) {
4391 in->usecase = USECASE_AUDIO_RECORD_HIFI;
4392 in->config = pcm_config_audio_capture;
4393 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004394 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4395 config->sample_rate,
4396 config->format,
4397 channel_count,
4398 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004399 in->config.period_size = buffer_size / frame_size;
4400 in->config.rate = config->sample_rate;
4401 in->af_period_multiplier = 1;
4402 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004403 } else {
4404 in->usecase = USECASE_AUDIO_RECORD;
4405 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08004406 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004407 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07004408#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004409 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07004410#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08004411 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004412 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08004413 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004414 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004415 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4416 config->sample_rate,
4417 config->format,
4418 channel_count,
4419 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004420 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004421 in->config.rate = config->sample_rate;
4422 in->af_period_multiplier = 1;
4423 } else {
4424 // period size is left untouched for rt mode playback
4425 in->config = pcm_config_audio_capture_rt;
4426 in->af_period_multiplier = af_period_multiplier;
4427 }
4428 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
4429 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004430 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08004431 in->usecase = USECASE_AUDIO_RECORD_MMAP;
4432 in->config = pcm_config_mmap_capture;
4433 in->stream.start = in_start;
4434 in->stream.stop = in_stop;
4435 in->stream.create_mmap_buffer = in_create_mmap_buffer;
4436 in->stream.get_mmap_position = in_get_mmap_position;
4437 in->af_period_multiplier = 1;
4438 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07004439 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07004440 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07004441 (config->sample_rate == 8000 ||
4442 config->sample_rate == 16000 ||
4443 config->sample_rate == 32000 ||
4444 config->sample_rate == 48000) &&
4445 channel_count == 1) {
4446 in->usecase = USECASE_AUDIO_RECORD_VOIP;
4447 in->config = pcm_config_audio_capture;
4448 frame_size = audio_stream_in_frame_size(&in->stream);
4449 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
4450 config->sample_rate,
4451 config->format,
4452 channel_count, false /*is_low_latency*/);
4453 in->config.period_size = buffer_size / frame_size;
4454 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
4455 in->config.rate = config->sample_rate;
4456 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004457 } else {
4458 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004459 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004460 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4461 config->sample_rate,
4462 config->format,
4463 channel_count,
4464 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004465 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004466 in->config.rate = config->sample_rate;
4467 in->af_period_multiplier = 1;
4468 }
4469 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
4470 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004471 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004472
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004473 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07004474 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004475
Andy Hungd13f0d32017-06-12 13:58:37 -07004476 in->error_log = error_log_create(
4477 ERROR_LOG_ENTRIES,
4478 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
4479
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004480 /* This stream could be for sound trigger lab,
4481 get sound trigger pcm if present */
4482 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004483
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004484 lock_input_stream(in);
4485 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
4486 pthread_mutex_lock(&adev->lock);
4487 in->card_status = adev->card_status;
4488 pthread_mutex_unlock(&adev->lock);
4489 pthread_mutex_unlock(&in->lock);
4490
vivek mehta4a824772017-06-08 19:05:49 -07004491 stream_app_type_cfg_init(&in->app_type_cfg);
4492
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004493 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004494 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004495 return 0;
4496
4497err_open:
4498 free(in);
4499 *stream_in = NULL;
4500 return ret;
4501}
4502
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004503static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004504 struct audio_stream_in *stream)
4505{
Andy Hungd13f0d32017-06-12 13:58:37 -07004506 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004507 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004508
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004509 // must deregister from sndmonitor first to prevent races
4510 // between the callback and close_stream
4511 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004512 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07004513
4514 error_log_destroy(in->error_log);
4515 in->error_log = NULL;
4516
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004517 free(stream);
4518
4519 return;
4520}
4521
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004522static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004523{
4524 return 0;
4525}
4526
Andy Hung31aca912014-03-20 17:14:59 -07004527/* verifies input and output devices and their capabilities.
4528 *
4529 * This verification is required when enabling extended bit-depth or
4530 * sampling rates, as not all qcom products support it.
4531 *
4532 * Suitable for calling only on initialization such as adev_open().
4533 * It fills the audio_device use_case_table[] array.
4534 *
4535 * Has a side-effect that it needs to configure audio routing / devices
4536 * in order to power up the devices and read the device parameters.
4537 * It does not acquire any hw device lock. Should restore the devices
4538 * back to "normal state" upon completion.
4539 */
4540static int adev_verify_devices(struct audio_device *adev)
4541{
4542 /* enumeration is a bit difficult because one really wants to pull
4543 * the use_case, device id, etc from the hidden pcm_device_table[].
4544 * In this case there are the following use cases and device ids.
4545 *
4546 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
4547 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004548 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07004549 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
4550 * [USECASE_AUDIO_RECORD] = {0, 0},
4551 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
4552 * [USECASE_VOICE_CALL] = {2, 2},
4553 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004554 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07004555 * USECASE_VOICE_CALL omitted, but possible for either input or output.
4556 */
4557
4558 /* should be the usecases enabled in adev_open_input_stream() */
4559 static const int test_in_usecases[] = {
4560 USECASE_AUDIO_RECORD,
4561 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
4562 };
4563 /* should be the usecases enabled in adev_open_output_stream()*/
4564 static const int test_out_usecases[] = {
4565 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
4566 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
4567 };
4568 static const usecase_type_t usecase_type_by_dir[] = {
4569 PCM_PLAYBACK,
4570 PCM_CAPTURE,
4571 };
4572 static const unsigned flags_by_dir[] = {
4573 PCM_OUT,
4574 PCM_IN,
4575 };
4576
4577 size_t i;
4578 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004579 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07004580 char info[512]; /* for possible debug info */
4581
4582 for (dir = 0; dir < 2; ++dir) {
4583 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
4584 const unsigned flags_dir = flags_by_dir[dir];
4585 const size_t testsize =
4586 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
4587 const int *testcases =
4588 dir ? test_in_usecases : test_out_usecases;
4589 const audio_devices_t audio_device =
4590 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
4591
4592 for (i = 0; i < testsize; ++i) {
4593 const audio_usecase_t audio_usecase = testcases[i];
4594 int device_id;
4595 snd_device_t snd_device;
4596 struct pcm_params **pparams;
4597 struct stream_out out;
4598 struct stream_in in;
4599 struct audio_usecase uc_info;
4600 int retval;
4601
4602 pparams = &adev->use_case_table[audio_usecase];
4603 pcm_params_free(*pparams); /* can accept null input */
4604 *pparams = NULL;
4605
4606 /* find the device ID for the use case (signed, for error) */
4607 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
4608 if (device_id < 0)
4609 continue;
4610
4611 /* prepare structures for device probing */
4612 memset(&uc_info, 0, sizeof(uc_info));
4613 uc_info.id = audio_usecase;
4614 uc_info.type = usecase_type;
4615 if (dir) {
4616 adev->active_input = &in;
4617 memset(&in, 0, sizeof(in));
4618 in.device = audio_device;
4619 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4620 uc_info.stream.in = &in;
4621 } else {
4622 adev->active_input = NULL;
4623 }
4624 memset(&out, 0, sizeof(out));
4625 out.devices = audio_device; /* only field needed in select_devices */
4626 uc_info.stream.out = &out;
4627 uc_info.devices = audio_device;
4628 uc_info.in_snd_device = SND_DEVICE_NONE;
4629 uc_info.out_snd_device = SND_DEVICE_NONE;
4630 list_add_tail(&adev->usecase_list, &uc_info.list);
4631
4632 /* select device - similar to start_(in/out)put_stream() */
4633 retval = select_devices(adev, audio_usecase);
4634 if (retval >= 0) {
4635 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4636#if LOG_NDEBUG == 0
4637 if (*pparams) {
4638 ALOGV("%s: (%s) card %d device %d", __func__,
4639 dir ? "input" : "output", card_id, device_id);
4640 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004641 } else {
4642 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4643 }
4644#endif
4645 }
4646
4647 /* deselect device - similar to stop_(in/out)put_stream() */
4648 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004649 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004650 /* 2. Disable the rx device */
4651 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004652 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004653 list_remove(&uc_info.list);
4654 }
4655 }
4656 adev->active_input = NULL; /* restore adev state */
4657 return 0;
4658}
4659
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004660static int adev_close(hw_device_t *device)
4661{
Andy Hung31aca912014-03-20 17:14:59 -07004662 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004663 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004664
4665 if (!adev)
4666 return 0;
4667
4668 pthread_mutex_lock(&adev_init_lock);
4669
4670 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004671 audio_extn_snd_mon_unregister_listener(adev);
4672 audio_extn_tfa_98xx_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004673 audio_route_free(adev->audio_route);
4674 free(adev->snd_dev_ref_cnt);
4675 platform_deinit(adev->platform);
4676 audio_extn_extspk_deinit(adev->extspk);
4677 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004678 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004679 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4680 pcm_params_free(adev->use_case_table[i]);
4681 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004682 if (adev->adm_deinit)
4683 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004684 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004685 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004686
4687 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004688
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004689 return 0;
4690}
4691
Glenn Kasten4f993392014-05-14 07:30:48 -07004692/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4693 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4694 * just that it _might_ work.
4695 */
4696static int period_size_is_plausible_for_low_latency(int period_size)
4697{
4698 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004699 case 48:
4700 case 96:
4701 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004702 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004703 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004704 case 240:
4705 case 320:
4706 case 480:
4707 return 1;
4708 default:
4709 return 0;
4710 }
4711}
4712
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004713static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4714{
4715 int card;
4716 card_status_t status;
4717
4718 if (!parms)
4719 return;
4720
4721 if (parse_snd_card_status(parms, &card, &status) < 0)
4722 return;
4723
4724 pthread_mutex_lock(&adev->lock);
4725 bool valid_cb = (card == adev->snd_card);
4726 if (valid_cb) {
4727 if (adev->card_status != status) {
4728 adev->card_status = status;
4729 platform_snd_card_update(adev->platform, status);
4730 }
4731 }
4732 pthread_mutex_unlock(&adev->lock);
4733 return;
4734}
4735
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004736static int adev_open(const hw_module_t *module, const char *name,
4737 hw_device_t **device)
4738{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004739 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004740
Eric Laurent2bafff12016-03-17 12:17:23 -07004741 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004742 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004743 pthread_mutex_lock(&adev_init_lock);
4744 if (audio_device_ref_count != 0) {
4745 *device = &adev->device.common;
4746 audio_device_ref_count++;
4747 ALOGV("%s: returning existing instance of adev", __func__);
4748 ALOGV("%s: exit", __func__);
4749 pthread_mutex_unlock(&adev_init_lock);
4750 return 0;
4751 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004752 adev = calloc(1, sizeof(struct audio_device));
4753
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004754 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4755
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004756 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4757 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4758 adev->device.common.module = (struct hw_module_t *)module;
4759 adev->device.common.close = adev_close;
4760
4761 adev->device.init_check = adev_init_check;
4762 adev->device.set_voice_volume = adev_set_voice_volume;
4763 adev->device.set_master_volume = adev_set_master_volume;
4764 adev->device.get_master_volume = adev_get_master_volume;
4765 adev->device.set_master_mute = adev_set_master_mute;
4766 adev->device.get_master_mute = adev_get_master_mute;
4767 adev->device.set_mode = adev_set_mode;
4768 adev->device.set_mic_mute = adev_set_mic_mute;
4769 adev->device.get_mic_mute = adev_get_mic_mute;
4770 adev->device.set_parameters = adev_set_parameters;
4771 adev->device.get_parameters = adev_get_parameters;
4772 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4773 adev->device.open_output_stream = adev_open_output_stream;
4774 adev->device.close_output_stream = adev_close_output_stream;
4775 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004776
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004777 adev->device.close_input_stream = adev_close_input_stream;
4778 adev->device.dump = adev_dump;
4779
4780 /* Set the default route before the PCM stream is opened */
4781 pthread_mutex_lock(&adev->lock);
4782 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004783 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004784 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004785 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004786 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004787 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004788 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004789 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004790 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004791 pthread_mutex_unlock(&adev->lock);
4792
4793 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004794 adev->platform = platform_init(adev);
4795 if (!adev->platform) {
4796 free(adev->snd_dev_ref_cnt);
4797 free(adev);
4798 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4799 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004800 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004801 return -EINVAL;
4802 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05004803 adev->extspk = audio_extn_extspk_init(adev);
4804
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004805 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4806 if (adev->visualizer_lib == NULL) {
4807 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4808 } else {
4809 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4810 adev->visualizer_start_output =
4811 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4812 "visualizer_hal_start_output");
4813 adev->visualizer_stop_output =
4814 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4815 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07004816 }
4817
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004818 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4819 if (adev->offload_effects_lib == NULL) {
4820 ALOGW("%s: DLOPEN failed for %s", __func__,
4821 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4822 } else {
4823 ALOGV("%s: DLOPEN successful for %s", __func__,
4824 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4825 adev->offload_effects_start_output =
4826 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4827 "offload_effects_bundle_hal_start_output");
4828 adev->offload_effects_stop_output =
4829 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4830 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07004831 }
4832
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004833 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4834 if (adev->adm_lib == NULL) {
4835 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4836 } else {
4837 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4838 adev->adm_init = (adm_init_t)
4839 dlsym(adev->adm_lib, "adm_init");
4840 adev->adm_deinit = (adm_deinit_t)
4841 dlsym(adev->adm_lib, "adm_deinit");
4842 adev->adm_register_input_stream = (adm_register_input_stream_t)
4843 dlsym(adev->adm_lib, "adm_register_input_stream");
4844 adev->adm_register_output_stream = (adm_register_output_stream_t)
4845 dlsym(adev->adm_lib, "adm_register_output_stream");
4846 adev->adm_deregister_stream = (adm_deregister_stream_t)
4847 dlsym(adev->adm_lib, "adm_deregister_stream");
4848 adev->adm_request_focus = (adm_request_focus_t)
4849 dlsym(adev->adm_lib, "adm_request_focus");
4850 adev->adm_abandon_focus = (adm_abandon_focus_t)
4851 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08004852 adev->adm_set_config = (adm_set_config_t)
4853 dlsym(adev->adm_lib, "adm_set_config");
4854 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4855 dlsym(adev->adm_lib, "adm_request_focus_v2");
4856 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4857 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4858 adev->adm_on_routing_change = (adm_on_routing_change_t)
4859 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004860 }
4861
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004862 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004863 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004864
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004865 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004866
Andy Hung31aca912014-03-20 17:14:59 -07004867 if (k_enable_extended_precision)
4868 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004869
Glenn Kasten4f993392014-05-14 07:30:48 -07004870 char value[PROPERTY_VALUE_MAX];
4871 int trial;
4872 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4873 trial = atoi(value);
4874 if (period_size_is_plausible_for_low_latency(trial)) {
4875 pcm_config_low_latency.period_size = trial;
4876 pcm_config_low_latency.start_threshold = trial / 4;
4877 pcm_config_low_latency.avail_min = trial / 4;
4878 configured_low_latency_capture_period_size = trial;
4879 }
4880 }
4881 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4882 trial = atoi(value);
4883 if (period_size_is_plausible_for_low_latency(trial)) {
4884 configured_low_latency_capture_period_size = trial;
4885 }
4886 }
4887
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004888 // commented as full set of app type cfg is sent from platform
4889 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004890 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004891
4892 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4893 af_period_multiplier = atoi(value);
4894 if (af_period_multiplier < 0) {
4895 af_period_multiplier = 2;
4896 } else if (af_period_multiplier > 4) {
4897 af_period_multiplier = 4;
4898 }
4899 ALOGV("new period_multiplier = %d", af_period_multiplier);
4900 }
4901
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004902 audio_extn_tfa_98xx_init(adev);
4903
vivek mehta1a9b7c02015-06-25 11:49:38 -07004904 pthread_mutex_unlock(&adev_init_lock);
4905
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004906 if (adev->adm_init)
4907 adev->adm_data = adev->adm_init();
4908
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004909 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004910 audio_extn_snd_mon_init();
4911 pthread_mutex_lock(&adev->lock);
4912 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
4913 adev->card_status = CARD_STATUS_ONLINE;
4914 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004915 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004916
Eric Laurent2bafff12016-03-17 12:17:23 -07004917 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004918 return 0;
4919}
4920
4921static struct hw_module_methods_t hal_module_methods = {
4922 .open = adev_open,
4923};
4924
4925struct audio_module HAL_MODULE_INFO_SYM = {
4926 .common = {
4927 .tag = HARDWARE_MODULE_TAG,
4928 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4929 .hal_api_version = HARDWARE_HAL_API_VERSION,
4930 .id = AUDIO_HARDWARE_MODULE_ID,
4931 .name = "QCOM Audio HAL",
4932 .author = "Code Aurora Forum",
4933 .methods = &hal_module_methods,
4934 },
4935};