blob: f8c17d0ea1e8d196780d3e05c4e90d134e195563 [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 mehta40125092017-08-21 18:48:51 -0700446// always call with adev lock held
447void send_gain_dep_calibration_l() {
448 if (last_known_cal_step >= 0)
449 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
450}
451
vivek mehta1a9b7c02015-06-25 11:49:38 -0700452__attribute__ ((visibility ("default")))
453bool audio_hw_send_gain_dep_calibration(int level) {
454 bool ret_val = false;
455 ALOGV("%s: enter ... ", __func__);
456
457 pthread_mutex_lock(&adev_init_lock);
458
459 if (adev != NULL && adev->platform != NULL) {
460 pthread_mutex_lock(&adev->lock);
vivek mehta40125092017-08-21 18:48:51 -0700461 last_known_cal_step = level;
462 send_gain_dep_calibration_l();
vivek mehta1a9b7c02015-06-25 11:49:38 -0700463 pthread_mutex_unlock(&adev->lock);
464 } 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
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700690 // FIXME b/65363602: bullhead is the only Nexus with audio_extn_spkr_prot_is_enabled()
691 // and does not use speaker swap. As this code causes a problem with device enable ref
692 // counting we remove it for now.
vivek mehtae59cfb22017-06-16 15:57:11 -0700693 // when speaker device is disabled, reset swap.
694 // will be renabled on usecase start
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700695 // platform_set_swap_channels(adev, false);
vivek mehtae59cfb22017-06-16 15:57:11 -0700696
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700697 } else if (platform_can_split_snd_device(snd_device,
698 &num_devices,
699 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700700 for (i = 0; i < num_devices; i++) {
701 disable_snd_device(adev, new_snd_devices[i]);
702 }
vivek mehtab6506412015-08-07 16:55:17 -0700703 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700704 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800705 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
706 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
707 ALOGE(" %s: Invalid sound device returned", __func__);
708 return -EINVAL;
709 }
710
Eric Laurent2e140aa2016-06-30 17:14:46 -0700711 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800712 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700713 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700714 audio_extn_sound_trigger_update_device_status(snd_device,
715 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700716 }
vivek mehtab6506412015-08-07 16:55:17 -0700717
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800718 return 0;
719}
720
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700721/*
722 legend:
723 uc - existing usecase
724 new_uc - new usecase
725 d1, d11, d2 - SND_DEVICE enums
726 a1, a2 - corresponding ANDROID device enums
727 B, B1, B2 - backend strings
728
729case 1
730 uc->dev d1 (a1) B1
731 new_uc->dev d1 (a1), d2 (a2) B1, B2
732
733 resolution: disable and enable uc->dev on d1
734
735case 2
736 uc->dev d1 (a1) B1
737 new_uc->dev d11 (a1) B1
738
739 resolution: need to switch uc since d1 and d11 are related
740 (e.g. speaker and voice-speaker)
741 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
742
743case 3
744 uc->dev d1 (a1) B1
745 new_uc->dev d2 (a2) B2
746
747 resolution: no need to switch uc
748
749case 4
750 uc->dev d1 (a1) B
751 new_uc->dev d2 (a2) B
752
753 resolution: disable enable uc-dev on d2 since backends match
754 we cannot enable two streams on two different devices if they
755 share the same backend. e.g. if offload is on speaker device using
756 QUAD_MI2S backend and a low-latency stream is started on voice-handset
757 using the same backend, offload must also be switched to voice-handset.
758
759case 5
760 uc->dev d1 (a1) B
761 new_uc->dev d1 (a1), d2 (a2) B
762
763 resolution: disable enable uc-dev on d2 since backends match
764 we cannot enable two streams on two different devices if they
765 share the same backend.
766
767case 6
768 uc->dev d1 a1 B1
769 new_uc->dev d2 a1 B2
770
771 resolution: no need to switch
772
773case 7
774
775 uc->dev d1 (a1), d2 (a2) B1, B2
776 new_uc->dev d1 B1
777
778 resolution: no need to switch
779
780*/
781static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
782 struct audio_usecase *new_uc,
783 snd_device_t new_snd_device)
784{
785 audio_devices_t a1 = uc->stream.out->devices;
786 audio_devices_t a2 = new_uc->stream.out->devices;
787
788 snd_device_t d1 = uc->out_snd_device;
789 snd_device_t d2 = new_snd_device;
790
791 // Treat as a special case when a1 and a2 are not disjoint
792 if ((a1 != a2) && (a1 & a2)) {
793 snd_device_t d3[2];
794 int num_devices = 0;
795 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
796 &num_devices,
797 d3);
798 if (ret < 0) {
799 if (ret != -ENOSYS) {
800 ALOGW("%s failed to split snd_device %d",
801 __func__,
802 popcount(a1) > 1 ? d1 : d2);
803 }
804 goto end;
805 }
806
807 // NB: case 7 is hypothetical and isn't a practical usecase yet.
808 // But if it does happen, we need to give priority to d2 if
809 // the combo devices active on the existing usecase share a backend.
810 // This is because we cannot have a usecase active on a combo device
811 // and a new usecase requests one device in this combo pair.
812 if (platform_check_backends_match(d3[0], d3[1])) {
813 return d2; // case 5
814 } else {
815 return d1; // case 1
816 }
817 } else {
818 if (platform_check_backends_match(d1, d2)) {
819 return d2; // case 2, 4
820 } else {
821 return d1; // case 6, 3
822 }
823 }
824
825end:
826 return d2; // return whatever was calculated before.
827}
828
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700829static void check_and_route_playback_usecases(struct audio_device *adev,
830 struct audio_usecase *uc_info,
831 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700832{
833 struct listnode *node;
834 struct audio_usecase *usecase;
835 bool switch_device[AUDIO_USECASE_MAX];
836 int i, num_uc_to_switch = 0;
837
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700838 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
839 uc_info,
840 snd_device);
David Linee3fe402017-03-13 10:00:42 -0700841
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700842 /*
843 * This function is to make sure that all the usecases that are active on
844 * the hardware codec backend are always routed to any one device that is
845 * handled by the hardware codec.
846 * For example, if low-latency and deep-buffer usecases are currently active
847 * on speaker and out_set_parameters(headset) is received on low-latency
848 * output, then we have to make sure deep-buffer is also switched to headset,
849 * because of the limitation that both the devices cannot be enabled
850 * at the same time as they share the same backend.
851 */
852 /* Disable all the usecases on the shared backend other than the
853 specified usecase */
854 for (i = 0; i < AUDIO_USECASE_MAX; i++)
855 switch_device[i] = false;
856
857 list_for_each(node, &adev->usecase_list) {
858 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700859 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
860 continue;
861
862 if (force_routing ||
863 (usecase->out_snd_device != snd_device &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -0700864 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
865 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700866 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700867 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
868 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700869 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700870 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700871 switch_device[usecase->id] = true;
872 num_uc_to_switch++;
873 }
874 }
875
876 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700877 list_for_each(node, &adev->usecase_list) {
878 usecase = node_to_item(node, struct audio_usecase, list);
879 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700880 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900881 }
882 }
883
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700884 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900885 list_for_each(node, &adev->usecase_list) {
886 usecase = node_to_item(node, struct audio_usecase, list);
887 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700888 d_device = derive_playback_snd_device(usecase, uc_info,
889 snd_device);
890 enable_snd_device(adev, d_device);
891 /* Update the out_snd_device before enabling the audio route */
892 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700893 }
894 }
895
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700896 /* Re-route all the usecases on the shared backend other than the
897 specified usecase to new snd devices */
898 list_for_each(node, &adev->usecase_list) {
899 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700900 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700901 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700902 }
903 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700904 }
905}
906
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700907static void check_and_route_capture_usecases(struct audio_device *adev,
908 struct audio_usecase *uc_info,
909 snd_device_t snd_device)
910{
911 struct listnode *node;
912 struct audio_usecase *usecase;
913 bool switch_device[AUDIO_USECASE_MAX];
914 int i, num_uc_to_switch = 0;
915
vivek mehta4ed66e62016-04-15 23:33:34 -0700916 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
917
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700918 /*
919 * This function is to make sure that all the active capture usecases
920 * are always routed to the same input sound device.
921 * For example, if audio-record and voice-call usecases are currently
922 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
923 * is received for voice call then we have to make sure that audio-record
924 * usecase is also switched to earpiece i.e. voice-dmic-ef,
925 * because of the limitation that two devices cannot be enabled
926 * at the same time if they share the same backend.
927 */
928 for (i = 0; i < AUDIO_USECASE_MAX; i++)
929 switch_device[i] = false;
930
931 list_for_each(node, &adev->usecase_list) {
932 usecase = node_to_item(node, struct audio_usecase, list);
933 if (usecase->type != PCM_PLAYBACK &&
934 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700935 usecase->in_snd_device != snd_device &&
936 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700937 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
938 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700939 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700940 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700941 switch_device[usecase->id] = true;
942 num_uc_to_switch++;
943 }
944 }
945
946 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700947 list_for_each(node, &adev->usecase_list) {
948 usecase = node_to_item(node, struct audio_usecase, list);
949 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700950 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700951 }
952 }
953
954 list_for_each(node, &adev->usecase_list) {
955 usecase = node_to_item(node, struct audio_usecase, list);
956 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700957 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700958 }
959 }
960
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700961 /* Re-route all the usecases on the shared backend other than the
962 specified usecase to new snd devices */
963 list_for_each(node, &adev->usecase_list) {
964 usecase = node_to_item(node, struct audio_usecase, list);
965 /* Update the in_snd_device only before enabling the audio route */
966 if (switch_device[usecase->id] ) {
967 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700968 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700969 }
970 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700971 }
972}
973
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800974/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700975static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800976{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700977 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700978 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800979
980 switch (channels) {
981 /*
982 * Do not handle stereo output in Multi-channel cases
983 * Stereo case is handled in normal playback path
984 */
985 case 6:
986 ALOGV("%s: HDMI supports 5.1", __func__);
987 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
988 break;
989 case 8:
990 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
991 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
992 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
993 break;
994 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700995 ALOGE("HDMI does not support multi channel playback");
996 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800997 break;
998 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700999 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001000}
1001
Andy Hung18859412017-08-09 11:47:21 -07001002static ssize_t read_usb_sup_sample_rates(bool is_playback,
1003 uint32_t *supported_sample_rates,
1004 uint32_t max_rates)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001005{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001006 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1007 supported_sample_rates,
1008 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001009#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001010 for (ssize_t i=0; i<count; i++) {
1011 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1012 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001013 }
1014#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001015 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001016}
1017
Haynes Mathew George569b7482017-05-08 14:44:27 -07001018static int read_usb_sup_channel_masks(bool is_playback,
1019 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001020 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001021{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001022 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001023 int channel_count;
1024 uint32_t num_masks = 0;
1025 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1026 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001027 }
Eric Laurent74b55762017-07-09 17:04:53 -07001028 if (is_playback) {
1029 // For playback we never report mono because the framework always outputs stereo
1030 channel_count = DEFAULT_CHANNEL_COUNT;
1031 // audio_channel_out_mask_from_count() does return positional masks for channel counts
1032 // above 2 but we want indexed masks here. So we
1033 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1034 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1035 }
1036 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1037 supported_channel_masks[num_masks++] =
1038 audio_channel_mask_for_index_assignment_from_count(channel_count);
1039 }
1040 } else {
1041 // For capture we report all supported channel masks from 1 channel up.
1042 channel_count = MIN_CHANNEL_COUNT;
1043 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1044 // indexed mask
1045 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1046 supported_channel_masks[num_masks++] =
1047 audio_channel_in_mask_from_count(channel_count);
1048 }
1049 }
1050 ALOGV("%s: %s supported ch %d supported_channel_masks[0] %08x num_masks %d", __func__,
1051 is_playback ? "P" : "C", channels, supported_channel_masks[0], num_masks);
1052 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001053}
1054
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001055static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001056 audio_format_t *supported_formats,
1057 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001058{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001059 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001060 switch (bitwidth) {
1061 case 24:
1062 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001063 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001064 break;
1065 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001066 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001067 break;
1068 case 16:
1069 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001070 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001071 break;
1072 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001073 ALOGV("%s: %s supported format %d", __func__,
1074 is_playback ? "P" : "C", bitwidth);
1075 return 1;
1076}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001077
Haynes Mathew George569b7482017-05-08 14:44:27 -07001078static int read_usb_sup_params_and_compare(bool is_playback,
1079 audio_format_t *format,
1080 audio_format_t *supported_formats,
1081 uint32_t max_formats,
1082 audio_channel_mask_t *mask,
1083 audio_channel_mask_t *supported_channel_masks,
1084 uint32_t max_masks,
1085 uint32_t *rate,
1086 uint32_t *supported_sample_rates,
1087 uint32_t max_rates) {
1088 int ret = 0;
1089 int num_formats;
1090 int num_masks;
1091 int num_rates;
1092 int i;
1093
1094 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1095 max_formats);
1096 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1097 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001098
Haynes Mathew George569b7482017-05-08 14:44:27 -07001099 num_rates = read_usb_sup_sample_rates(is_playback,
1100 supported_sample_rates, max_rates);
1101
1102#define LUT(table, len, what, dflt) \
1103 for (i=0; i<len && (table[i] != what); i++); \
1104 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1105
1106 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1107 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1108 LUT(supported_sample_rates, num_rates, *rate, 0);
1109
1110#undef LUT
1111 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001112}
1113
Andy Hungd9653bd2017-08-01 19:31:39 -07001114static bool is_usb_ready(struct audio_device *adev, bool is_playback)
1115{
1116 // Check if usb is ready.
1117 // The usb device may have been removed quickly after insertion and hence
1118 // no longer available. This will show up as empty channel masks, or rates.
1119
1120 pthread_mutex_lock(&adev->lock);
1121 uint32_t supported_sample_rate;
1122
1123 // we consider usb ready if we can fetch at least one sample rate.
1124 const bool ready = read_usb_sup_sample_rates(
1125 is_playback, &supported_sample_rate, 1 /* max_rates */) > 0;
1126 pthread_mutex_unlock(&adev->lock);
1127 return ready;
1128}
1129
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001130static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1131{
1132 struct audio_usecase *usecase;
1133 struct listnode *node;
1134
1135 list_for_each(node, &adev->usecase_list) {
1136 usecase = node_to_item(node, struct audio_usecase, list);
1137 if (usecase->type == VOICE_CALL) {
1138 ALOGV("%s: usecase id %d", __func__, usecase->id);
1139 return usecase->id;
1140 }
1141 }
1142 return USECASE_INVALID;
1143}
1144
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001145struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1146 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001147{
1148 struct audio_usecase *usecase;
1149 struct listnode *node;
1150
1151 list_for_each(node, &adev->usecase_list) {
1152 usecase = node_to_item(node, struct audio_usecase, list);
1153 if (usecase->id == uc_id)
1154 return usecase;
1155 }
1156 return NULL;
1157}
1158
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001159int select_devices(struct audio_device *adev,
1160 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001161{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001162 snd_device_t out_snd_device = SND_DEVICE_NONE;
1163 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001164 struct audio_usecase *usecase = NULL;
1165 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001166 struct audio_usecase *hfp_usecase = NULL;
1167 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001168 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001169 int status = 0;
Eric Laurentf4520b02017-09-20 18:31:58 -07001170 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1171 USECASE_AUDIO_PLAYBACK_VOIP);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001172
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001173 usecase = get_usecase_from_list(adev, uc_id);
1174 if (usecase == NULL) {
1175 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1176 return -EINVAL;
1177 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001178
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001179 if ((usecase->type == VOICE_CALL) ||
1180 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001181 out_snd_device = platform_get_output_snd_device(adev->platform,
1182 usecase->stream.out->devices);
1183 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001184 usecase->devices = usecase->stream.out->devices;
1185 } else {
1186 /*
1187 * If the voice call is active, use the sound devices of voice call usecase
1188 * so that it would not result any device switch. All the usecases will
1189 * be switched to new device when select_devices() is called for voice call
1190 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001191 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001192 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001193 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001194 vc_usecase = get_usecase_from_list(adev,
1195 get_voice_usecase_id_from_list(adev));
1196 if ((vc_usecase != NULL) &&
1197 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1198 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001199 in_snd_device = vc_usecase->in_snd_device;
1200 out_snd_device = vc_usecase->out_snd_device;
1201 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001202 } else if (audio_extn_hfp_is_active(adev)) {
1203 hfp_ucid = audio_extn_hfp_get_usecase();
1204 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1205 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1206 in_snd_device = hfp_usecase->in_snd_device;
1207 out_snd_device = hfp_usecase->out_snd_device;
1208 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001209 }
1210 if (usecase->type == PCM_PLAYBACK) {
1211 usecase->devices = usecase->stream.out->devices;
1212 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001213 if (out_snd_device == SND_DEVICE_NONE) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001214 struct stream_out *voip_out = adev->primary_output;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001215
Eric Laurentb23d5282013-05-14 15:27:20 -07001216 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001217 usecase->stream.out->devices);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001218
1219 if (voip_usecase)
1220 voip_out = voip_usecase->stream.out;
1221
1222 if (usecase->stream.out == voip_out &&
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001223 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001224 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001225 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001226 select_devices(adev, adev->active_input->usecase);
1227 }
1228 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001229 } else if (usecase->type == PCM_CAPTURE) {
1230 usecase->devices = usecase->stream.in->device;
1231 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001232 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001233 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001234 if (adev->active_input &&
1235 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1236 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001237
1238 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1239 USECASE_AUDIO_PLAYBACK_VOIP);
1240
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001241 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001242 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1243 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001244 } else if (voip_usecase) {
1245 out_device = voip_usecase->stream.out->devices;
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001246 } else if (adev->primary_output) {
1247 out_device = adev->primary_output->devices;
1248 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001249 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001250 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001251 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001252 }
1253 }
1254
1255 if (out_snd_device == usecase->out_snd_device &&
1256 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001257 return 0;
1258 }
1259
Eric Laurent2bafff12016-03-17 12:17:23 -07001260 if (out_snd_device != SND_DEVICE_NONE &&
1261 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1262 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1263 __func__,
1264 use_case_table[uc_id],
1265 adev->last_logged_snd_device[uc_id][0],
1266 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1267 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1268 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1269 -1,
1270 out_snd_device,
1271 platform_get_snd_device_name(out_snd_device),
1272 platform_get_snd_device_acdb_id(out_snd_device));
1273 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1274 }
1275 if (in_snd_device != SND_DEVICE_NONE &&
1276 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1277 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1278 __func__,
1279 use_case_table[uc_id],
1280 adev->last_logged_snd_device[uc_id][1],
1281 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1282 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1283 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1284 -1,
1285 in_snd_device,
1286 platform_get_snd_device_name(in_snd_device),
1287 platform_get_snd_device_acdb_id(in_snd_device));
1288 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1289 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001290
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001291 /*
1292 * Limitation: While in call, to do a device switch we need to disable
1293 * and enable both RX and TX devices though one of them is same as current
1294 * device.
1295 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001296 if ((usecase->type == VOICE_CALL) &&
1297 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1298 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001299 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001300 /* Disable sidetone only if voice call already exists */
1301 if (voice_is_call_state_active(adev))
1302 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001303 }
1304
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001305 /* Disable current sound devices */
1306 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001307 disable_audio_route(adev, usecase);
1308 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001309 }
1310
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001311 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001312 disable_audio_route(adev, usecase);
1313 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001314 }
1315
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001316 /* Applicable only on the targets that has external modem.
1317 * New device information should be sent to modem before enabling
1318 * the devices to reduce in-call device switch time.
1319 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001320 if ((usecase->type == VOICE_CALL) &&
1321 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1322 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001323 status = platform_switch_voice_call_enable_device_config(adev->platform,
1324 out_snd_device,
1325 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001326 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001327
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001328 /* Enable new sound devices */
1329 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001330 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Eric Laurent99dab492017-06-17 15:19:08 -07001331 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001332 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001333 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001334 }
1335
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001336 if (in_snd_device != SND_DEVICE_NONE) {
1337 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001338 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001339 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001340
Eric Laurentb23d5282013-05-14 15:27:20 -07001341 if (usecase->type == VOICE_CALL)
1342 status = platform_switch_voice_call_device_post(adev->platform,
1343 out_snd_device,
1344 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001345
sangwoo170731f2013-06-08 15:36:36 +09001346 usecase->in_snd_device = in_snd_device;
1347 usecase->out_snd_device = out_snd_device;
1348
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001349 audio_extn_tfa_98xx_set_mode();
1350
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001351 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001352
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001353 /* Applicable only on the targets that has external modem.
1354 * Enable device command should be sent to modem only after
1355 * enabling voice call mixer controls
1356 */
vivek mehta765eb642015-08-07 19:46:06 -07001357 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001358 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1359 out_snd_device,
1360 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001361 /* Enable sidetone only if voice call already exists */
1362 if (voice_is_call_state_active(adev))
1363 voice_set_sidetone(adev, out_snd_device, true);
1364 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001365
Eric Laurentf4520b02017-09-20 18:31:58 -07001366 if (usecase == voip_usecase) {
1367 struct stream_out *voip_out = voip_usecase->stream.out;
1368 audio_extn_utils_send_app_type_gain(adev,
1369 voip_out->app_type_cfg.app_type,
1370 &voip_out->app_type_cfg.gain[0]);
1371 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001372 return status;
1373}
1374
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001375static int stop_input_stream(struct stream_in *in)
1376{
1377 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001378 struct audio_usecase *uc_info;
1379 struct audio_device *adev = in->dev;
1380
Eric Laurent994a6932013-07-17 11:51:42 -07001381 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001382 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001383
1384 if (adev->active_input) {
1385 if (adev->active_input->usecase == in->usecase) {
1386 adev->active_input = NULL;
1387 } else {
1388 ALOGW("%s adev->active_input->usecase %s, v/s in->usecase %s",
1389 __func__,
1390 use_case_table[adev->active_input->usecase],
1391 use_case_table[in->usecase]);
1392 }
1393 }
1394
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001395 uc_info = get_usecase_from_list(adev, in->usecase);
1396 if (uc_info == NULL) {
1397 ALOGE("%s: Could not find the usecase (%d) in the list",
1398 __func__, in->usecase);
1399 return -EINVAL;
1400 }
1401
vivek mehta781065c2017-04-04 12:55:01 -07001402 /* Close in-call recording streams */
1403 voice_check_and_stop_incall_rec_usecase(adev, in);
1404
Eric Laurent150dbfe2013-02-27 14:31:02 -08001405 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001406 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001407
1408 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001409 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001410
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001411 list_remove(&uc_info->list);
1412 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001413
Eric Laurent994a6932013-07-17 11:51:42 -07001414 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001415 return ret;
1416}
1417
1418int start_input_stream(struct stream_in *in)
1419{
1420 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001421 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001422 struct audio_usecase *uc_info;
1423 struct audio_device *adev = in->dev;
1424
Eric Laurent994a6932013-07-17 11:51:42 -07001425 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001426
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001427 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1428 return -EIO;
1429
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001430 if (in->card_status == CARD_STATUS_OFFLINE ||
1431 adev->card_status == CARD_STATUS_OFFLINE) {
1432 ALOGW("in->card_status or adev->card_status offline, try again");
1433 ret = -EAGAIN;
1434 goto error_config;
1435 }
1436
vivek mehta781065c2017-04-04 12:55:01 -07001437 /* Check if source matches incall recording usecase criteria */
1438 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1439 if (ret)
1440 goto error_config;
1441 else
1442 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1443
Eric Laurentb23d5282013-05-14 15:27:20 -07001444 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001445 if (in->pcm_device_id < 0) {
1446 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1447 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001448 ret = -EINVAL;
1449 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001450 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001451
1452 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001453 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1454 uc_info->id = in->usecase;
1455 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001456 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001457 uc_info->devices = in->device;
1458 uc_info->in_snd_device = SND_DEVICE_NONE;
1459 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001460
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001461 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001462
1463 audio_extn_perf_lock_acquire();
1464
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001465 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001466
Eric Laurent0e46adf2016-12-16 12:49:24 -08001467 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001468 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001469 ALOGE("%s: pcm stream not ready", __func__);
1470 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001471 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001472 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001473 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001474 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1475 goto error_open;
1476 }
1477 } else {
1478 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1479 unsigned int pcm_open_retry_count = 0;
1480
1481 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1482 flags |= PCM_MMAP | PCM_NOIRQ;
1483 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1484 } else if (in->realtime) {
1485 flags |= PCM_MMAP | PCM_NOIRQ;
1486 }
1487
1488 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1489 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1490
1491 while (1) {
1492 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1493 flags, &in->config);
1494 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1495 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1496 if (in->pcm != NULL) {
1497 pcm_close(in->pcm);
1498 in->pcm = NULL;
1499 }
1500 if (pcm_open_retry_count-- == 0) {
1501 ret = -EIO;
1502 goto error_open;
1503 }
1504 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1505 continue;
1506 }
1507 break;
1508 }
1509
1510 ALOGV("%s: pcm_prepare", __func__);
1511 ret = pcm_prepare(in->pcm);
1512 if (ret < 0) {
1513 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001514 pcm_close(in->pcm);
1515 in->pcm = NULL;
1516 goto error_open;
1517 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001518 if (in->realtime) {
1519 ret = pcm_start(in->pcm);
1520 if (ret < 0) {
1521 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1522 pcm_close(in->pcm);
1523 in->pcm = NULL;
1524 goto error_open;
1525 }
1526 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001527 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001528 register_in_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001529 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001530 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001531
Eric Laurent0e46adf2016-12-16 12:49:24 -08001532 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001533
1534error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001535 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001536 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001537
1538error_config:
1539 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001540 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001541 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001542}
1543
Eric Laurenta1478072015-09-21 17:21:52 -07001544void lock_input_stream(struct stream_in *in)
1545{
1546 pthread_mutex_lock(&in->pre_lock);
1547 pthread_mutex_lock(&in->lock);
1548 pthread_mutex_unlock(&in->pre_lock);
1549}
1550
1551void lock_output_stream(struct stream_out *out)
1552{
1553 pthread_mutex_lock(&out->pre_lock);
1554 pthread_mutex_lock(&out->lock);
1555 pthread_mutex_unlock(&out->pre_lock);
1556}
1557
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001558/* must be called with out->lock locked */
1559static int send_offload_cmd_l(struct stream_out* out, int command)
1560{
1561 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1562
1563 ALOGVV("%s %d", __func__, command);
1564
1565 cmd->cmd = command;
1566 list_add_tail(&out->offload_cmd_list, &cmd->node);
1567 pthread_cond_signal(&out->offload_cond);
1568 return 0;
1569}
1570
1571/* must be called iwth out->lock locked */
1572static void stop_compressed_output_l(struct stream_out *out)
1573{
1574 out->offload_state = OFFLOAD_STATE_IDLE;
1575 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001576 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001577 if (out->compr != NULL) {
1578 compress_stop(out->compr);
1579 while (out->offload_thread_blocked) {
1580 pthread_cond_wait(&out->cond, &out->lock);
1581 }
1582 }
1583}
1584
1585static void *offload_thread_loop(void *context)
1586{
1587 struct stream_out *out = (struct stream_out *) context;
1588 struct listnode *item;
1589
1590 out->offload_state = OFFLOAD_STATE_IDLE;
1591 out->playback_started = 0;
1592
1593 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1594 set_sched_policy(0, SP_FOREGROUND);
1595 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1596
1597 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001598 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001599 for (;;) {
1600 struct offload_cmd *cmd = NULL;
1601 stream_callback_event_t event;
1602 bool send_callback = false;
1603
1604 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1605 __func__, list_empty(&out->offload_cmd_list),
1606 out->offload_state);
1607 if (list_empty(&out->offload_cmd_list)) {
1608 ALOGV("%s SLEEPING", __func__);
1609 pthread_cond_wait(&out->offload_cond, &out->lock);
1610 ALOGV("%s RUNNING", __func__);
1611 continue;
1612 }
1613
1614 item = list_head(&out->offload_cmd_list);
1615 cmd = node_to_item(item, struct offload_cmd, node);
1616 list_remove(item);
1617
1618 ALOGVV("%s STATE %d CMD %d out->compr %p",
1619 __func__, out->offload_state, cmd->cmd, out->compr);
1620
1621 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1622 free(cmd);
1623 break;
1624 }
1625
1626 if (out->compr == NULL) {
1627 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001628 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001629 pthread_cond_signal(&out->cond);
1630 continue;
1631 }
1632 out->offload_thread_blocked = true;
1633 pthread_mutex_unlock(&out->lock);
1634 send_callback = false;
1635 switch(cmd->cmd) {
1636 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1637 compress_wait(out->compr, -1);
1638 send_callback = true;
1639 event = STREAM_CBK_EVENT_WRITE_READY;
1640 break;
1641 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001642 compress_next_track(out->compr);
1643 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001644 send_callback = true;
1645 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001646 /* Resend the metadata for next iteration */
1647 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001648 break;
1649 case OFFLOAD_CMD_DRAIN:
1650 compress_drain(out->compr);
1651 send_callback = true;
1652 event = STREAM_CBK_EVENT_DRAIN_READY;
1653 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001654 case OFFLOAD_CMD_ERROR:
1655 send_callback = true;
1656 event = STREAM_CBK_EVENT_ERROR;
1657 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001658 default:
1659 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1660 break;
1661 }
Eric Laurenta1478072015-09-21 17:21:52 -07001662 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001663 out->offload_thread_blocked = false;
1664 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001665 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001666 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001667 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001668 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001669 free(cmd);
1670 }
1671
1672 pthread_cond_signal(&out->cond);
1673 while (!list_empty(&out->offload_cmd_list)) {
1674 item = list_head(&out->offload_cmd_list);
1675 list_remove(item);
1676 free(node_to_item(item, struct offload_cmd, node));
1677 }
1678 pthread_mutex_unlock(&out->lock);
1679
1680 return NULL;
1681}
1682
1683static int create_offload_callback_thread(struct stream_out *out)
1684{
1685 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1686 list_init(&out->offload_cmd_list);
1687 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1688 offload_thread_loop, out);
1689 return 0;
1690}
1691
1692static int destroy_offload_callback_thread(struct stream_out *out)
1693{
Eric Laurenta1478072015-09-21 17:21:52 -07001694 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001695 stop_compressed_output_l(out);
1696 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1697
1698 pthread_mutex_unlock(&out->lock);
1699 pthread_join(out->offload_thread, (void **) NULL);
1700 pthread_cond_destroy(&out->offload_cond);
1701
1702 return 0;
1703}
1704
Eric Laurent07eeafd2013-10-06 12:52:49 -07001705static bool allow_hdmi_channel_config(struct audio_device *adev)
1706{
1707 struct listnode *node;
1708 struct audio_usecase *usecase;
1709 bool ret = true;
1710
1711 list_for_each(node, &adev->usecase_list) {
1712 usecase = node_to_item(node, struct audio_usecase, list);
1713 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1714 /*
1715 * If voice call is already existing, do not proceed further to avoid
1716 * disabling/enabling both RX and TX devices, CSD calls, etc.
1717 * Once the voice call done, the HDMI channels can be configured to
1718 * max channels of remaining use cases.
1719 */
1720 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001721 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001722 __func__);
1723 ret = false;
1724 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001725 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1726 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001727 "no change in HDMI channels", __func__);
1728 ret = false;
1729 break;
1730 }
1731 }
1732 }
1733 return ret;
1734}
1735
1736static int check_and_set_hdmi_channels(struct audio_device *adev,
1737 unsigned int channels)
1738{
1739 struct listnode *node;
1740 struct audio_usecase *usecase;
1741
1742 /* Check if change in HDMI channel config is allowed */
1743 if (!allow_hdmi_channel_config(adev))
1744 return 0;
1745
1746 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001747 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001748 return 0;
1749 }
1750
1751 platform_set_hdmi_channels(adev->platform, channels);
1752 adev->cur_hdmi_channels = channels;
1753
1754 /*
1755 * Deroute all the playback streams routed to HDMI so that
1756 * the back end is deactivated. Note that backend will not
1757 * be deactivated if any one stream is connected to it.
1758 */
1759 list_for_each(node, &adev->usecase_list) {
1760 usecase = node_to_item(node, struct audio_usecase, list);
1761 if (usecase->type == PCM_PLAYBACK &&
1762 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001763 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001764 }
1765 }
1766
1767 /*
1768 * Enable all the streams disabled above. Now the HDMI backend
1769 * will be activated with new channel configuration
1770 */
1771 list_for_each(node, &adev->usecase_list) {
1772 usecase = node_to_item(node, struct audio_usecase, list);
1773 if (usecase->type == PCM_PLAYBACK &&
1774 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001775 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001776 }
1777 }
1778
1779 return 0;
1780}
1781
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001782static int stop_output_stream(struct stream_out *out)
1783{
1784 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001785 struct audio_usecase *uc_info;
1786 struct audio_device *adev = out->dev;
1787
Eric Laurent994a6932013-07-17 11:51:42 -07001788 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001789 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001790 uc_info = get_usecase_from_list(adev, out->usecase);
1791 if (uc_info == NULL) {
1792 ALOGE("%s: Could not find the usecase (%d) in the list",
1793 __func__, out->usecase);
1794 return -EINVAL;
1795 }
1796
Haynes Mathew George41f86652014-06-17 14:22:15 -07001797 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1798 if (adev->visualizer_stop_output != NULL)
1799 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1800 if (adev->offload_effects_stop_output != NULL)
1801 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1802 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001803
Eric Laurent150dbfe2013-02-27 14:31:02 -08001804 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001805 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001806
1807 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001808 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001809
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001810 list_remove(&uc_info->list);
1811 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001812
Eric Laurent0499d4f2014-08-25 22:39:29 -05001813 audio_extn_extspk_update(adev->extspk);
1814
Eric Laurent07eeafd2013-10-06 12:52:49 -07001815 /* Must be called after removing the usecase from list */
1816 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1817 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07001818 else if (out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
1819 struct listnode *node;
1820 struct audio_usecase *usecase;
1821 list_for_each(node, &adev->usecase_list) {
1822 usecase = node_to_item(node, struct audio_usecase, list);
1823 if (usecase->devices & AUDIO_DEVICE_OUT_SPEAKER)
1824 select_devices(adev, usecase->id);
1825 }
1826 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001827
Eric Laurent994a6932013-07-17 11:51:42 -07001828 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001829 return ret;
1830}
1831
1832int start_output_stream(struct stream_out *out)
1833{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001834 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001835 struct audio_usecase *uc_info;
1836 struct audio_device *adev = out->dev;
1837
Eric Laurent994a6932013-07-17 11:51:42 -07001838 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001839 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001840
1841 if (out->card_status == CARD_STATUS_OFFLINE ||
1842 adev->card_status == CARD_STATUS_OFFLINE) {
1843 ALOGW("out->card_status or adev->card_status offline, try again");
1844 ret = -EAGAIN;
1845 goto error_config;
1846 }
1847
Eric Laurentb23d5282013-05-14 15:27:20 -07001848 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001849 if (out->pcm_device_id < 0) {
1850 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1851 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001852 ret = -EINVAL;
1853 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001854 }
1855
1856 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1857 uc_info->id = out->usecase;
1858 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001859 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001860 uc_info->devices = out->devices;
1861 uc_info->in_snd_device = SND_DEVICE_NONE;
1862 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001863
Eric Laurent07eeafd2013-10-06 12:52:49 -07001864 /* This must be called before adding this usecase to the list */
1865 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1866 check_and_set_hdmi_channels(adev, out->config.channels);
1867
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001868 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001869
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001870 audio_extn_perf_lock_acquire();
1871
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001872 select_devices(adev, out->usecase);
1873
Eric Laurent0499d4f2014-08-25 22:39:29 -05001874 audio_extn_extspk_update(adev->extspk);
1875
Andy Hung31aca912014-03-20 17:14:59 -07001876 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001877 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001878 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1879 out->pcm = NULL;
1880 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1881 COMPRESS_IN, &out->compr_config);
1882 if (out->compr && !is_compress_ready(out->compr)) {
1883 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1884 compress_close(out->compr);
1885 out->compr = NULL;
1886 ret = -EIO;
1887 goto error_open;
1888 }
1889 if (out->offload_callback)
1890 compress_nonblock(out->compr, out->non_blocking);
1891
1892 if (adev->visualizer_start_output != NULL)
1893 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1894 if (adev->offload_effects_start_output != NULL)
1895 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
1896 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001897 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001898 ALOGE("%s: pcm stream not ready", __func__);
1899 goto error_open;
1900 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001901 ret = pcm_start(out->pcm);
1902 if (ret < 0) {
1903 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1904 goto error_open;
1905 }
1906 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07001907 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001908 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001909
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001910 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1911 flags |= PCM_MMAP | PCM_NOIRQ;
1912 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001913 } else if (out->realtime) {
1914 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07001915 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001916
1917 while (1) {
1918 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1919 flags, &out->config);
1920 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1921 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1922 if (out->pcm != NULL) {
1923 pcm_close(out->pcm);
1924 out->pcm = NULL;
1925 }
1926 if (pcm_open_retry_count-- == 0) {
1927 ret = -EIO;
1928 goto error_open;
1929 }
1930 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1931 continue;
1932 }
1933 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001934 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001935 ALOGV("%s: pcm_prepare", __func__);
1936 if (pcm_is_ready(out->pcm)) {
1937 ret = pcm_prepare(out->pcm);
1938 if (ret < 0) {
1939 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1940 pcm_close(out->pcm);
1941 out->pcm = NULL;
1942 goto error_open;
1943 }
1944 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001945 if (out->realtime) {
1946 ret = pcm_start(out->pcm);
1947 if (ret < 0) {
1948 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1949 pcm_close(out->pcm);
1950 out->pcm = NULL;
1951 goto error_open;
1952 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001953 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001954 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001955 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001956 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001957 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07001958
1959 // consider a scenario where on pause lower layers are tear down.
1960 // so on resume, swap mixer control need to be sent only when
1961 // backend is active, hence rather than sending from enable device
1962 // sending it from start of streamtream
1963
1964 platform_set_swap_channels(adev, true);
1965
Eric Laurent994a6932013-07-17 11:51:42 -07001966 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001967 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001968error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001969 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001970 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001971error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001972 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001973}
1974
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001975static int check_input_parameters(uint32_t sample_rate,
1976 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07001977 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001978{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001979 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
1980 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07001981 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
1982 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07001983 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1984 return -EINVAL;
1985 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001986
Eric Laurent74b55762017-07-09 17:04:53 -07001987 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
1988 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001989 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07001990 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07001991 return -EINVAL;
1992 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001993
1994 switch (sample_rate) {
1995 case 8000:
1996 case 11025:
1997 case 12000:
1998 case 16000:
1999 case 22050:
2000 case 24000:
2001 case 32000:
2002 case 44100:
2003 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002004 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002005 break;
2006 default:
vivek mehtadae44712015-07-27 14:13:18 -07002007 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002008 return -EINVAL;
2009 }
2010
2011 return 0;
2012}
2013
vivek mehtaa68fea62017-06-08 19:04:02 -07002014static size_t get_stream_buffer_size(size_t duration_ms,
2015 uint32_t sample_rate,
2016 audio_format_t format,
2017 int channel_count,
2018 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002019{
2020 size_t size = 0;
2021
vivek mehtaa68fea62017-06-08 19:04:02 -07002022 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002023 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002024 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002025
2026 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002027
Glenn Kasten4f993392014-05-14 07:30:48 -07002028 /* make sure the size is multiple of 32 bytes
2029 * At 48 kHz mono 16-bit PCM:
2030 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2031 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2032 */
2033 size += 0x1f;
2034 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002035
2036 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002037}
2038
2039static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2040{
2041 struct stream_out *out = (struct stream_out *)stream;
2042
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002043 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002044}
2045
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002046static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002047{
2048 return -ENOSYS;
2049}
2050
2051static size_t out_get_buffer_size(const struct audio_stream *stream)
2052{
2053 struct stream_out *out = (struct stream_out *)stream;
2054
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002055 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2056 return out->compr_config.fragment_size;
2057 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002058 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002059 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002060}
2061
2062static uint32_t out_get_channels(const struct audio_stream *stream)
2063{
2064 struct stream_out *out = (struct stream_out *)stream;
2065
2066 return out->channel_mask;
2067}
2068
2069static audio_format_t out_get_format(const struct audio_stream *stream)
2070{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002071 struct stream_out *out = (struct stream_out *)stream;
2072
2073 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002074}
2075
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002076static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002077{
2078 return -ENOSYS;
2079}
2080
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002081/* must be called with out->lock locked */
2082static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002083{
2084 struct stream_out *out = (struct stream_out *)stream;
2085 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002086 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002087
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002088 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002089 if (adev->adm_deregister_stream)
2090 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002091 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002092 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002093 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2094 if (out->pcm) {
2095 pcm_close(out->pcm);
2096 out->pcm = NULL;
2097 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002098 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002099 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002100 out->playback_started = false;
2101 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002102 } else {
2103 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002104 out->gapless_mdata.encoder_delay = 0;
2105 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002106 if (out->compr != NULL) {
2107 compress_close(out->compr);
2108 out->compr = NULL;
2109 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002110 }
Phil Burkbc991042017-02-24 08:06:44 -08002111 if (do_stop) {
2112 stop_output_stream(out);
2113 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002114 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002115 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002116 return 0;
2117}
2118
2119static int out_standby(struct audio_stream *stream)
2120{
2121 struct stream_out *out = (struct stream_out *)stream;
2122
2123 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2124 out->usecase, use_case_table[out->usecase]);
2125
2126 lock_output_stream(out);
2127 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002128 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002129 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002130 return 0;
2131}
2132
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002133static int out_on_error(struct audio_stream *stream)
2134{
2135 struct stream_out *out = (struct stream_out *)stream;
2136 struct audio_device *adev = out->dev;
2137 bool do_standby = false;
2138
2139 lock_output_stream(out);
2140 if (!out->standby) {
2141 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2142 stop_compressed_output_l(out);
2143 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2144 } else
2145 do_standby = true;
2146 }
2147 pthread_mutex_unlock(&out->lock);
2148
2149 if (do_standby)
2150 return out_standby(&out->stream.common);
2151
2152 return 0;
2153}
2154
Andy Hung7401c7c2016-09-21 12:41:21 -07002155static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002156{
Andy Hung7401c7c2016-09-21 12:41:21 -07002157 struct stream_out *out = (struct stream_out *)stream;
2158
2159 // We try to get the lock for consistency,
2160 // but it isn't necessary for these variables.
2161 // If we're not in standby, we may be blocked on a write.
2162 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2163 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2164 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2165
2166 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002167 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002168 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002169
2170 // dump error info
2171 (void)error_log_dump(
2172 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002173
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002174 return 0;
2175}
2176
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002177static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2178{
2179 int ret = 0;
2180 char value[32];
2181 struct compr_gapless_mdata tmp_mdata;
2182
2183 if (!out || !parms) {
2184 return -EINVAL;
2185 }
2186
2187 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2188 if (ret >= 0) {
2189 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2190 } else {
2191 return -EINVAL;
2192 }
2193
2194 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2195 if (ret >= 0) {
2196 tmp_mdata.encoder_padding = atoi(value);
2197 } else {
2198 return -EINVAL;
2199 }
2200
2201 out->gapless_mdata = tmp_mdata;
2202 out->send_new_metadata = 1;
2203 ALOGV("%s new encoder delay %u and padding %u", __func__,
2204 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2205
2206 return 0;
2207}
2208
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002209static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2210{
2211 return out == adev->primary_output || out == adev->voice_tx_output;
2212}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002213
Kevin Rocard1e02c882017-08-09 15:26:07 -07002214static int get_alive_usb_card(struct str_parms* parms) {
2215 int card;
2216 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2217 !audio_extn_usb_alive(card)) {
2218 return card;
2219 }
2220 return -ENODEV;
2221}
2222
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002223static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2224{
2225 struct stream_out *out = (struct stream_out *)stream;
2226 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002227 struct audio_usecase *usecase;
2228 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002229 struct str_parms *parms;
2230 char value[32];
2231 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002232 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002233 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002234
Eric Laurent2e140aa2016-06-30 17:14:46 -07002235 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002236 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002237 parms = str_parms_create_str(kvpairs);
2238 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2239 if (ret >= 0) {
2240 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002241
Eric Laurenta1478072015-09-21 17:21:52 -07002242 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002243
2244 // The usb driver needs to be closed after usb device disconnection
2245 // otherwise audio is no longer played on the new usb devices.
2246 // By forcing the stream in standby, the usb stack refcount drops to 0
2247 // and the driver is closed.
2248 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD && val == AUDIO_DEVICE_NONE &&
2249 audio_is_usb_out_device(out->devices)) {
2250 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2251 out_standby_l(&out->stream.common);
2252 }
2253
Eric Laurent150dbfe2013-02-27 14:31:02 -08002254 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002255
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002256 /*
2257 * When HDMI cable is unplugged the music playback is paused and
2258 * the policy manager sends routing=0. But the audioflinger
2259 * continues to write data until standby time (3sec).
2260 * As the HDMI core is turned off, the write gets blocked.
2261 * Avoid this by routing audio to speaker until standby.
2262 */
2263 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2264 val == AUDIO_DEVICE_NONE) {
2265 val = AUDIO_DEVICE_OUT_SPEAKER;
2266 }
2267
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002268 audio_devices_t new_dev = val;
2269
2270 // Workaround: If routing to an non existing usb device, fail gracefully
2271 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002272 int card;
2273 if (audio_is_usb_out_device(new_dev) &&
2274 (card = get_alive_usb_card(parms)) >= 0) {
2275
2276 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002277 pthread_mutex_unlock(&adev->lock);
2278 pthread_mutex_unlock(&out->lock);
2279 status = -ENOSYS;
2280 goto routing_fail;
2281 }
2282
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002283 /*
2284 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002285 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002286 * the select_devices(). But how do we undo this?
2287 *
2288 * For example, music playback is active on headset (deep-buffer usecase)
2289 * and if we go to ringtones and select a ringtone, low-latency usecase
2290 * will be started on headset+speaker. As we can't enable headset+speaker
2291 * and headset devices at the same time, select_devices() switches the music
2292 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2293 * So when the ringtone playback is completed, how do we undo the same?
2294 *
2295 * We are relying on the out_set_parameters() call on deep-buffer output,
2296 * once the ringtone playback is ended.
2297 * NOTE: We should not check if the current devices are same as new devices.
2298 * Because select_devices() must be called to switch back the music
2299 * playback to headset.
2300 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002301 if (new_dev != AUDIO_DEVICE_NONE) {
2302 bool same_dev = out->devices == new_dev;
2303 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002304
Eric Laurenta7657192014-10-09 21:09:33 -07002305 if (output_drives_call(adev, out)) {
2306 if (!voice_is_in_call(adev)) {
2307 if (adev->mode == AUDIO_MODE_IN_CALL) {
2308 adev->current_call_output = out;
2309 ret = voice_start_call(adev);
2310 }
2311 } else {
2312 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002313 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002314 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002315 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002316
2317 if (!out->standby) {
2318 if (!same_dev) {
2319 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002320 // inform adm before actual routing to prevent glitches.
2321 if (adev->adm_on_routing_change) {
2322 adev->adm_on_routing_change(adev->adm_data,
2323 out->handle);
2324 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002325 }
2326 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002327 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002328
2329 // on device switch force swap, lower functions will make sure
2330 // to check if swap is allowed or not.
2331
2332 if (!same_dev)
2333 platform_set_swap_channels(adev, true);
vivek mehta0d3637a2016-07-24 09:32:02 -07002334 }
2335
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002336 }
2337
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002338 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002339 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002340
2341 /*handles device and call state changes*/
2342 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002343 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002344 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002345
2346 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2347 parse_compress_metadata(out, parms);
2348 }
2349
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002350 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002351 ALOGV("%s: exit: code(%d)", __func__, status);
2352 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002353}
2354
Haynes Mathew George569b7482017-05-08 14:44:27 -07002355static bool stream_get_parameter_channels(struct str_parms *query,
2356 struct str_parms *reply,
2357 audio_channel_mask_t *supported_channel_masks) {
2358 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002359 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002360 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002361 size_t i, j;
2362
2363 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2364 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002365 value[0] = '\0';
2366 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002367 while (supported_channel_masks[i] != 0) {
2368 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2369 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002370 if (!first) {
2371 strcat(value, "|");
2372 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002373 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002374 first = false;
2375 break;
2376 }
2377 }
2378 i++;
2379 }
2380 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002381 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002382 return ret >= 0;
2383}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002384
Haynes Mathew George569b7482017-05-08 14:44:27 -07002385static bool stream_get_parameter_formats(struct str_parms *query,
2386 struct str_parms *reply,
2387 audio_format_t *supported_formats) {
2388 int ret = -1;
2389 char value[256];
2390 int i;
2391
2392 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2393 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002394 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002395 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002396 case AUDIO_FORMAT_PCM_16_BIT:
2397 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2398 break;
2399 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2400 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2401 break;
2402 case AUDIO_FORMAT_PCM_32_BIT:
2403 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2404 break;
2405 default:
2406 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002407 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002408 break;
2409 }
2410 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002411 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002412 return ret >= 0;
2413}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002414
Haynes Mathew George569b7482017-05-08 14:44:27 -07002415static bool stream_get_parameter_rates(struct str_parms *query,
2416 struct str_parms *reply,
2417 uint32_t *supported_sample_rates) {
2418
2419 int i;
2420 char value[256];
2421 int ret = -1;
2422 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2423 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002424 value[0] = '\0';
2425 i=0;
2426 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002427 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002428 int avail = sizeof(value) - cursor;
2429 ret = snprintf(value + cursor, avail, "%s%d",
2430 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002431 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002432 if (ret < 0 || ret >= avail) {
2433 // if cursor is at the last element of the array
2434 // overwrite with \0 is duplicate work as
2435 // snprintf already put a \0 in place.
2436 // else
2437 // we had space to write the '|' at value[cursor]
2438 // (which will be overwritten) or no space to fill
2439 // the first element (=> cursor == 0)
2440 value[cursor] = '\0';
2441 break;
2442 }
2443 cursor += ret;
2444 ++i;
2445 }
2446 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2447 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002448 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002449 return ret >= 0;
2450}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002451
Haynes Mathew George569b7482017-05-08 14:44:27 -07002452static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2453{
2454 struct stream_out *out = (struct stream_out *)stream;
2455 struct str_parms *query = str_parms_create_str(keys);
2456 char *str;
2457 struct str_parms *reply = str_parms_create();
2458 bool replied = false;
2459 ALOGV("%s: enter: keys - %s", __func__, keys);
2460
2461 replied |= stream_get_parameter_channels(query, reply,
2462 &out->supported_channel_masks[0]);
2463 replied |= stream_get_parameter_formats(query, reply,
2464 &out->supported_formats[0]);
2465 replied |= stream_get_parameter_rates(query, reply,
2466 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002467 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002468 str = str_parms_to_str(reply);
2469 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002470 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002471 }
2472 str_parms_destroy(query);
2473 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002474 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002475 return str;
2476}
2477
2478static uint32_t out_get_latency(const struct audio_stream_out *stream)
2479{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002480 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002481 struct stream_out *out = (struct stream_out *)stream;
2482
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002483 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2484 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002485 else if ((out->realtime) ||
2486 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002487 // since the buffer won't be filled up faster than realtime,
2488 // return a smaller number
2489 period_ms = (out->af_period_multiplier * out->config.period_size *
2490 1000) / (out->config.rate);
2491 hw_delay = platform_render_latency(out->usecase)/1000;
2492 return period_ms + hw_delay;
2493 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002494
2495 return (out->config.period_count * out->config.period_size * 1000) /
2496 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002497}
2498
2499static int out_set_volume(struct audio_stream_out *stream, float left,
2500 float right)
2501{
Eric Laurenta9024de2013-04-04 09:19:12 -07002502 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002503 int volume[2];
2504
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002505 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002506 /* only take left channel into account: the API is for stereo anyway */
2507 out->muted = (left == 0.0f);
2508 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002509 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2510 const char *mixer_ctl_name = "Compress Playback Volume";
2511 struct audio_device *adev = out->dev;
2512 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002513 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2514 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002515 /* try with the control based on device id */
2516 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2517 PCM_PLAYBACK);
2518 char ctl_name[128] = {0};
2519 snprintf(ctl_name, sizeof(ctl_name),
2520 "Compress Playback %d Volume", pcm_device_id);
2521 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2522 if (!ctl) {
2523 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2524 return -EINVAL;
2525 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002526 }
2527 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2528 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2529 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2530 return 0;
vivek mehtaa68fea62017-06-08 19:04:02 -07002531 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002532 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2533 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2534 if (!out->standby) {
2535 // if in standby, cached volume will be sent after stream is opened
2536 audio_extn_utils_send_app_type_gain(out->dev,
2537 out->app_type_cfg.app_type,
2538 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002539 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002540 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002541 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002542
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002543 return -ENOSYS;
2544}
2545
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002546// note: this call is safe only if the stream_cb is
2547// removed first in close_output_stream (as is done now).
2548static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2549{
2550 if (!stream || !parms)
2551 return;
2552
2553 struct stream_out *out = (struct stream_out *)stream;
2554 struct audio_device *adev = out->dev;
2555
2556 card_status_t status;
2557 int card;
2558 if (parse_snd_card_status(parms, &card, &status) < 0)
2559 return;
2560
2561 pthread_mutex_lock(&adev->lock);
2562 bool valid_cb = (card == adev->snd_card);
2563 pthread_mutex_unlock(&adev->lock);
2564
2565 if (!valid_cb)
2566 return;
2567
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002568 lock_output_stream(out);
2569 if (out->card_status != status)
2570 out->card_status = status;
2571 pthread_mutex_unlock(&out->lock);
2572
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002573 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2574 use_case_table[out->usecase],
2575 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2576
2577 if (status == CARD_STATUS_OFFLINE)
2578 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002579
2580 return;
2581}
2582
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002583#ifdef NO_AUDIO_OUT
2584static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002585 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002586{
2587 struct stream_out *out = (struct stream_out *)stream;
2588
2589 /* No Output device supported other than BT for playback.
2590 * Sleep for the amount of buffer duration
2591 */
Eric Laurenta1478072015-09-21 17:21:52 -07002592 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002593 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2594 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002595 out_get_sample_rate(&out->stream.common));
2596 pthread_mutex_unlock(&out->lock);
2597 return bytes;
2598}
2599#endif
2600
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002601static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2602 size_t bytes)
2603{
2604 struct stream_out *out = (struct stream_out *)stream;
2605 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002606 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002607 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002608
Eric Laurenta1478072015-09-21 17:21:52 -07002609 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002610 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07002611 const size_t frame_size = audio_stream_out_frame_size(stream);
2612 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002613
Eric Laurent0e46adf2016-12-16 12:49:24 -08002614 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2615 error_code = ERROR_CODE_WRITE;
2616 goto exit;
2617 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002618 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002619 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002620 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002621 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07002622
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002623 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002624 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002625 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07002626 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002627 goto exit;
2628 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002629
vivek mehta40125092017-08-21 18:48:51 -07002630 // after standby always force set last known cal step
2631 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
2632 ALOGD("%s: retry previous failed cal level set", __func__);
2633 send_gain_dep_calibration_l();
2634 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002635 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002636
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002637 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002638 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002639 if (out->send_new_metadata) {
2640 ALOGVV("send new gapless metadata");
2641 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2642 out->send_new_metadata = 0;
2643 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002644 unsigned int avail;
2645 struct timespec tstamp;
2646 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2647 /* Do not limit write size if the available frames count is unknown */
2648 if (ret != 0) {
2649 avail = bytes;
2650 }
2651 if (avail == 0) {
2652 ret = 0;
2653 } else {
2654 if (avail > bytes) {
2655 avail = bytes;
2656 }
2657 ret = compress_write(out->compr, buffer, avail);
2658 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2659 __func__, avail, ret);
2660 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002661
Eric Laurent6e895242013-09-05 16:10:57 -07002662 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002663 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2664 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002665 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002666 compress_start(out->compr);
2667 out->playback_started = 1;
2668 out->offload_state = OFFLOAD_STATE_PLAYING;
2669 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002670 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002671 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002672 } else {
2673 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002674 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002675 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002676 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002677 return ret;
2678 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002679 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002680 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07002681 size_t bytes_to_write = bytes;
2682
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002683 if (out->muted)
2684 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07002685 // FIXME: this can be removed once audio flinger mixer supports mono output
2686 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
2687 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
2688 int16_t *src = (int16_t *)buffer;
2689 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002690
Eric Laurentad2dde92017-09-20 18:27:31 -07002691 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
2692 out->format != AUDIO_FORMAT_PCM_16_BIT,
2693 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002694
Eric Laurentad2dde92017-09-20 18:27:31 -07002695 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
2696 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
2697 }
2698 bytes_to_write /= 2;
2699 }
2700 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes_to_write);
2701
2702 long ns = (frames * NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002703 request_out_focus(out, ns);
2704
2705 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2706 if (use_mmap)
Eric Laurentad2dde92017-09-20 18:27:31 -07002707 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002708 else
Eric Laurentad2dde92017-09-20 18:27:31 -07002709 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002710
Haynes Mathew George03c40102016-01-29 17:57:48 -08002711 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002712 } else {
2713 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002714 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002715 }
2716
2717exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002718 // For PCM we always consume the buffer and return #bytes regardless of ret.
2719 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07002720 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07002721 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002722 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07002723
Andy Hung7401c7c2016-09-21 12:41:21 -07002724 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07002725 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07002726 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2727 ALOGE_IF(out->pcm != NULL,
2728 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07002729 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002730 // usleep not guaranteed for values over 1 second but we don't limit here.
2731 }
2732 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002733
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002734 pthread_mutex_unlock(&out->lock);
2735
2736 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002737 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002738 if (sleeptime_us != 0)
2739 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002740 }
2741 return bytes;
2742}
2743
2744static int out_get_render_position(const struct audio_stream_out *stream,
2745 uint32_t *dsp_frames)
2746{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002747 struct stream_out *out = (struct stream_out *)stream;
2748 *dsp_frames = 0;
2749 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002750 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002751 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002752 unsigned long frames = 0;
2753 // TODO: check return value
2754 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2755 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002756 ALOGVV("%s rendered frames %d sample_rate %d",
2757 __func__, *dsp_frames, out->sample_rate);
2758 }
2759 pthread_mutex_unlock(&out->lock);
2760 return 0;
2761 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002762 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002763}
2764
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002765static int out_add_audio_effect(const struct audio_stream *stream __unused,
2766 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002767{
2768 return 0;
2769}
2770
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002771static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2772 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002773{
2774 return 0;
2775}
2776
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002777static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2778 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002779{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002780 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002781}
2782
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002783static int out_get_presentation_position(const struct audio_stream_out *stream,
2784 uint64_t *frames, struct timespec *timestamp)
2785{
2786 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002787 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07002788 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002789
Eric Laurenta1478072015-09-21 17:21:52 -07002790 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002791
Eric Laurent949a0892013-09-20 09:20:13 -07002792 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2793 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002794 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002795 compress_get_tstamp(out->compr, &dsp_frames,
2796 &out->sample_rate);
2797 ALOGVV("%s rendered frames %ld sample_rate %d",
2798 __func__, dsp_frames, out->sample_rate);
2799 *frames = dsp_frames;
2800 ret = 0;
2801 /* this is the best we can do */
2802 clock_gettime(CLOCK_MONOTONIC, timestamp);
2803 }
2804 } else {
2805 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002806 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002807 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2808 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002809 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002810 // This adjustment accounts for buffering after app processor.
2811 // It is based on estimated DSP latency per use case, rather than exact.
2812 signed_frames -=
2813 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2814
Eric Laurent949a0892013-09-20 09:20:13 -07002815 // It would be unusual for this value to be negative, but check just in case ...
2816 if (signed_frames >= 0) {
2817 *frames = signed_frames;
2818 ret = 0;
2819 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002820 }
2821 }
2822 }
2823
2824 pthread_mutex_unlock(&out->lock);
2825
2826 return ret;
2827}
2828
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002829static int out_set_callback(struct audio_stream_out *stream,
2830 stream_callback_t callback, void *cookie)
2831{
2832 struct stream_out *out = (struct stream_out *)stream;
2833
2834 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002835 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002836 out->offload_callback = callback;
2837 out->offload_cookie = cookie;
2838 pthread_mutex_unlock(&out->lock);
2839 return 0;
2840}
2841
2842static int out_pause(struct audio_stream_out* stream)
2843{
2844 struct stream_out *out = (struct stream_out *)stream;
2845 int status = -ENOSYS;
2846 ALOGV("%s", __func__);
2847 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002848 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002849 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2850 status = compress_pause(out->compr);
2851 out->offload_state = OFFLOAD_STATE_PAUSED;
2852 }
2853 pthread_mutex_unlock(&out->lock);
2854 }
2855 return status;
2856}
2857
2858static int out_resume(struct audio_stream_out* stream)
2859{
2860 struct stream_out *out = (struct stream_out *)stream;
2861 int status = -ENOSYS;
2862 ALOGV("%s", __func__);
2863 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2864 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002865 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002866 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2867 status = compress_resume(out->compr);
2868 out->offload_state = OFFLOAD_STATE_PLAYING;
2869 }
2870 pthread_mutex_unlock(&out->lock);
2871 }
2872 return status;
2873}
2874
2875static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2876{
2877 struct stream_out *out = (struct stream_out *)stream;
2878 int status = -ENOSYS;
2879 ALOGV("%s", __func__);
2880 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002881 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002882 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2883 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2884 else
2885 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2886 pthread_mutex_unlock(&out->lock);
2887 }
2888 return status;
2889}
2890
2891static int out_flush(struct audio_stream_out* stream)
2892{
2893 struct stream_out *out = (struct stream_out *)stream;
2894 ALOGV("%s", __func__);
2895 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002896 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002897 stop_compressed_output_l(out);
2898 pthread_mutex_unlock(&out->lock);
2899 return 0;
2900 }
2901 return -ENOSYS;
2902}
2903
Eric Laurent0e46adf2016-12-16 12:49:24 -08002904static int out_stop(const struct audio_stream_out* stream)
2905{
2906 struct stream_out *out = (struct stream_out *)stream;
2907 struct audio_device *adev = out->dev;
2908 int ret = -ENOSYS;
2909
2910 ALOGV("%s", __func__);
2911 pthread_mutex_lock(&adev->lock);
2912 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2913 out->playback_started && out->pcm != NULL) {
2914 pcm_stop(out->pcm);
2915 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08002916 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002917 }
2918 pthread_mutex_unlock(&adev->lock);
2919 return ret;
2920}
2921
2922static int out_start(const struct audio_stream_out* stream)
2923{
2924 struct stream_out *out = (struct stream_out *)stream;
2925 struct audio_device *adev = out->dev;
2926 int ret = -ENOSYS;
2927
2928 ALOGV("%s", __func__);
2929 pthread_mutex_lock(&adev->lock);
2930 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2931 !out->playback_started && out->pcm != NULL) {
2932 ret = start_output_stream(out);
2933 if (ret == 0) {
2934 out->playback_started = true;
2935 }
2936 }
2937 pthread_mutex_unlock(&adev->lock);
2938 return ret;
2939}
2940
Phil Burkbc991042017-02-24 08:06:44 -08002941/*
2942 * Modify config->period_count based on min_size_frames
2943 */
2944static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
2945{
2946 int periodCountRequested = (min_size_frames + config->period_size - 1)
2947 / config->period_size;
2948 int periodCount = MMAP_PERIOD_COUNT_MIN;
2949
2950 ALOGV("%s original config.period_size = %d config.period_count = %d",
2951 __func__, config->period_size, config->period_count);
2952
2953 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
2954 periodCount *= 2;
2955 }
2956 config->period_count = periodCount;
2957
2958 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
2959}
2960
Eric Laurent0e46adf2016-12-16 12:49:24 -08002961static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2962 int32_t min_size_frames,
2963 struct audio_mmap_buffer_info *info)
2964{
2965 struct stream_out *out = (struct stream_out *)stream;
2966 struct audio_device *adev = out->dev;
2967 int ret = 0;
2968 unsigned int offset1;
2969 unsigned int frames1;
2970 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07002971 uint32_t mmap_size;
2972 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002973
2974 ALOGV("%s", __func__);
2975 pthread_mutex_lock(&adev->lock);
2976
2977 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002978 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002979 ret = -EINVAL;
2980 goto exit;
2981 }
2982 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08002983 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002984 ret = -ENOSYS;
2985 goto exit;
2986 }
2987 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
2988 if (out->pcm_device_id < 0) {
2989 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2990 __func__, out->pcm_device_id, out->usecase);
2991 ret = -EINVAL;
2992 goto exit;
2993 }
Phil Burkbc991042017-02-24 08:06:44 -08002994
2995 adjust_mmap_period_count(&out->config, min_size_frames);
2996
Eric Laurent0e46adf2016-12-16 12:49:24 -08002997 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2998 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
2999 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3000 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3001 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3002 step = "open";
3003 ret = -ENODEV;
3004 goto exit;
3005 }
3006 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3007 if (ret < 0) {
3008 step = "begin";
3009 goto exit;
3010 }
3011 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003012 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003013 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003014 ret = platform_get_mmap_data_fd(adev->platform,
3015 out->pcm_device_id, 0 /*playback*/,
3016 &info->shared_memory_fd,
3017 &mmap_size);
3018 if (ret < 0) {
3019 // Fall back to non exclusive mode
3020 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3021 } else {
3022 if (mmap_size < buffer_size) {
3023 step = "mmap";
3024 goto exit;
3025 }
3026 // FIXME: indicate exclusive mode support by returning a negative buffer size
3027 info->buffer_size_frames *= -1;
3028 }
3029 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003030
3031 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3032 if (ret < 0) {
3033 step = "commit";
3034 goto exit;
3035 }
Phil Burkbc991042017-02-24 08:06:44 -08003036
3037 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003038 ret = 0;
3039
3040 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3041 __func__, info->shared_memory_address, info->buffer_size_frames);
3042
3043exit:
3044 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003045 if (out->pcm == NULL) {
3046 ALOGE("%s: %s - %d", __func__, step, ret);
3047 } else {
3048 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003049 pcm_close(out->pcm);
3050 out->pcm = NULL;
3051 }
3052 }
3053 pthread_mutex_unlock(&adev->lock);
3054 return ret;
3055}
3056
3057static int out_get_mmap_position(const struct audio_stream_out *stream,
3058 struct audio_mmap_position *position)
3059{
3060 struct stream_out *out = (struct stream_out *)stream;
3061 ALOGVV("%s", __func__);
3062 if (position == NULL) {
3063 return -EINVAL;
3064 }
3065 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
3066 return -ENOSYS;
3067 }
3068 if (out->pcm == NULL) {
3069 return -ENOSYS;
3070 }
3071
3072 struct timespec ts = { 0, 0 };
3073 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
3074 if (ret < 0) {
3075 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
3076 return ret;
3077 }
Andy Hungfc044e12017-03-20 09:24:22 -07003078 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003079 return 0;
3080}
3081
3082
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003083/** audio_stream_in implementation **/
3084static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3085{
3086 struct stream_in *in = (struct stream_in *)stream;
3087
3088 return in->config.rate;
3089}
3090
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003091static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003092{
3093 return -ENOSYS;
3094}
3095
3096static size_t in_get_buffer_size(const struct audio_stream *stream)
3097{
3098 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003099 return in->config.period_size * in->af_period_multiplier *
3100 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003101}
3102
3103static uint32_t in_get_channels(const struct audio_stream *stream)
3104{
3105 struct stream_in *in = (struct stream_in *)stream;
3106
3107 return in->channel_mask;
3108}
3109
vivek mehta4ed66e62016-04-15 23:33:34 -07003110static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003111{
vivek mehta4ed66e62016-04-15 23:33:34 -07003112 struct stream_in *in = (struct stream_in *)stream;
3113 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003114}
3115
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003116static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003117{
3118 return -ENOSYS;
3119}
3120
3121static int in_standby(struct audio_stream *stream)
3122{
3123 struct stream_in *in = (struct stream_in *)stream;
3124 struct audio_device *adev = in->dev;
3125 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003126 bool do_stop = true;
3127
Eric Laurent994a6932013-07-17 11:51:42 -07003128 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003129
3130 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003131
3132 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003133 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003134 audio_extn_sound_trigger_stop_lab(in);
3135 in->standby = true;
3136 }
3137
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003138 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003139 if (adev->adm_deregister_stream)
3140 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3141
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003142 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003143 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003144 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003145 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003146 in->capture_started = false;
3147 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003148 if (in->pcm) {
3149 pcm_close(in->pcm);
3150 in->pcm = NULL;
3151 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003152 adev->enable_voicerx = false;
3153 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003154 if (do_stop) {
3155 status = stop_input_stream(in);
3156 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003157 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003158 }
3159 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003160 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003161 return status;
3162}
3163
Andy Hungd13f0d32017-06-12 13:58:37 -07003164static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003165{
Andy Hungd13f0d32017-06-12 13:58:37 -07003166 struct stream_in *in = (struct stream_in *)stream;
3167
3168 // We try to get the lock for consistency,
3169 // but it isn't necessary for these variables.
3170 // If we're not in standby, we may be blocked on a read.
3171 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3172 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3173 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3174 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3175
3176 if (locked) {
3177 pthread_mutex_unlock(&in->lock);
3178 }
3179
3180 // dump error info
3181 (void)error_log_dump(
3182 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003183 return 0;
3184}
3185
3186static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3187{
3188 struct stream_in *in = (struct stream_in *)stream;
3189 struct audio_device *adev = in->dev;
3190 struct str_parms *parms;
3191 char *str;
3192 char value[32];
3193 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003194 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003195
Eric Laurent994a6932013-07-17 11:51:42 -07003196 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003197 parms = str_parms_create_str(kvpairs);
3198
3199 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3200
Eric Laurenta1478072015-09-21 17:21:52 -07003201 lock_input_stream(in);
3202
Eric Laurent150dbfe2013-02-27 14:31:02 -08003203 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003204 if (ret >= 0) {
3205 val = atoi(value);
3206 /* no audio source uses val == 0 */
3207 if ((in->source != val) && (val != 0)) {
3208 in->source = val;
3209 }
3210 }
3211
3212 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003213
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003214 if (ret >= 0) {
3215 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003216 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003217
3218 // Workaround: If routing to an non existing usb device, fail gracefully
3219 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003220 int card;
3221 if (audio_is_usb_in_device(val) &&
3222 (card = get_alive_usb_card(parms)) >= 0) {
3223
3224 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003225 status = -ENOSYS;
3226 } else {
3227
3228 in->device = val;
3229 /* If recording is in progress, change the tx device to new device */
3230 if (!in->standby) {
3231 ALOGV("update input routing change");
3232 // inform adm before actual routing to prevent glitches.
3233 if (adev->adm_on_routing_change) {
3234 adev->adm_on_routing_change(adev->adm_data,
3235 in->capture_handle);
3236 }
3237 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003238 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003239 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003240 }
3241 }
3242
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003243 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003244 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003245
3246 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003247 ALOGV("%s: exit: status(%d)", __func__, status);
3248 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003249}
3250
Haynes Mathew George569b7482017-05-08 14:44:27 -07003251static char* in_get_parameters(const struct audio_stream *stream,
3252 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003253{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003254 struct stream_in *in = (struct stream_in *)stream;
3255 struct str_parms *query = str_parms_create_str(keys);
3256 char *str;
3257 struct str_parms *reply = str_parms_create();
3258 bool replied = false;
3259
3260 ALOGV("%s: enter: keys - %s", __func__, keys);
3261 replied |= stream_get_parameter_channels(query, reply,
3262 &in->supported_channel_masks[0]);
3263 replied |= stream_get_parameter_formats(query, reply,
3264 &in->supported_formats[0]);
3265 replied |= stream_get_parameter_rates(query, reply,
3266 &in->supported_sample_rates[0]);
3267 if (replied) {
3268 str = str_parms_to_str(reply);
3269 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003270 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003271 }
3272 str_parms_destroy(query);
3273 str_parms_destroy(reply);
3274 ALOGV("%s: exit: returns - %s", __func__, str);
3275 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003276}
3277
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003278static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003279{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003280 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003281}
3282
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003283static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3284{
3285 if (!stream || !parms)
3286 return;
3287
3288 struct stream_in *in = (struct stream_in *)stream;
3289 struct audio_device *adev = in->dev;
3290
3291 card_status_t status;
3292 int card;
3293 if (parse_snd_card_status(parms, &card, &status) < 0)
3294 return;
3295
3296 pthread_mutex_lock(&adev->lock);
3297 bool valid_cb = (card == adev->snd_card);
3298 pthread_mutex_unlock(&adev->lock);
3299
3300 if (!valid_cb)
3301 return;
3302
3303 lock_input_stream(in);
3304 if (in->card_status != status)
3305 in->card_status = status;
3306 pthread_mutex_unlock(&in->lock);
3307
3308 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3309 use_case_table[in->usecase],
3310 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3311
3312 // a better solution would be to report error back to AF and let
3313 // it put the stream to standby
3314 if (status == CARD_STATUS_OFFLINE)
3315 in_standby(&in->stream.common);
3316
3317 return;
3318}
3319
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003320static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3321 size_t bytes)
3322{
3323 struct stream_in *in = (struct stream_in *)stream;
3324 struct audio_device *adev = in->dev;
3325 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003326 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003327 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003328
Eric Laurenta1478072015-09-21 17:21:52 -07003329 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003330 const size_t frame_size = audio_stream_in_frame_size(stream);
3331 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003332
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003333 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003334 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003335 /* Read from sound trigger HAL */
3336 audio_extn_sound_trigger_read(in, buffer, bytes);
3337 pthread_mutex_unlock(&in->lock);
3338 return bytes;
3339 }
3340
Eric Laurent0e46adf2016-12-16 12:49:24 -08003341 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3342 ret = -ENOSYS;
3343 goto exit;
3344 }
3345
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003346 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003347 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003348 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003349 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003350 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003351 goto exit;
3352 }
3353 in->standby = 0;
3354 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003355
Andy Hungd13f0d32017-06-12 13:58:37 -07003356 // errors that occur here are read errors.
3357 error_code = ERROR_CODE_READ;
3358
Haynes Mathew George03c40102016-01-29 17:57:48 -08003359 //what's the duration requested by the client?
3360 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3361 in->config.rate;
3362 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003363
Haynes Mathew George03c40102016-01-29 17:57:48 -08003364 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003365 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003366 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003367 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003368 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003369 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003370 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003371 if (ret < 0) {
3372 ALOGE("Failed to read w/err %s", strerror(errno));
3373 ret = -errno;
3374 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003375 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3376 if (bytes % 4 == 0) {
3377 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3378 int_buf_stream = buffer;
3379 for (size_t itt=0; itt < bytes/4 ; itt++) {
3380 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003381 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003382 } else {
3383 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3384 ret = -EINVAL;
3385 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003386 }
3387 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003388 }
3389
Haynes Mathew George03c40102016-01-29 17:57:48 -08003390 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003391
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003392 /*
3393 * Instead of writing zeroes here, we could trust the hardware
3394 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003395 * 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 -08003396 */
Andy Hungd13f0d32017-06-12 13:58:37 -07003397 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003398 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07003399 in->frames_muted += frames;
3400 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003401
3402exit:
3403 pthread_mutex_unlock(&in->lock);
3404
3405 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07003406 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003407 in_standby(&in->stream.common);
3408 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003409 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003410 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07003411 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08003412 }
3413 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003414 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003415 }
3416 return bytes;
3417}
3418
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003419static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003420{
3421 return 0;
3422}
3423
Andy Hung6ebe5962016-01-15 17:46:57 -08003424static int in_get_capture_position(const struct audio_stream_in *stream,
3425 int64_t *frames, int64_t *time)
3426{
3427 if (stream == NULL || frames == NULL || time == NULL) {
3428 return -EINVAL;
3429 }
3430 struct stream_in *in = (struct stream_in *)stream;
3431 int ret = -ENOSYS;
3432
3433 lock_input_stream(in);
3434 if (in->pcm) {
3435 struct timespec timestamp;
3436 unsigned int avail;
3437 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3438 *frames = in->frames_read + avail;
3439 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3440 ret = 0;
3441 }
3442 }
3443 pthread_mutex_unlock(&in->lock);
3444 return ret;
3445}
3446
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003447static int add_remove_audio_effect(const struct audio_stream *stream,
3448 effect_handle_t effect,
3449 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003450{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003451 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003452 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003453 int status = 0;
3454 effect_descriptor_t desc;
3455
3456 status = (*effect)->get_descriptor(effect, &desc);
3457 if (status != 0)
3458 return status;
3459
Eric Laurenta1478072015-09-21 17:21:52 -07003460 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003461 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003462 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003463 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003464 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003465 in->enable_aec != enable &&
3466 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3467 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003468 if (!enable)
3469 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003470 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3471 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3472 adev->enable_voicerx = enable;
3473 struct audio_usecase *usecase;
3474 struct listnode *node;
3475 list_for_each(node, &adev->usecase_list) {
3476 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07003477 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07003478 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05003479 }
3480 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003481 if (!in->standby)
3482 select_devices(in->dev, in->usecase);
3483 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003484 if (in->enable_ns != enable &&
3485 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3486 in->enable_ns = enable;
3487 if (!in->standby)
3488 select_devices(in->dev, in->usecase);
3489 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003490 pthread_mutex_unlock(&in->dev->lock);
3491 pthread_mutex_unlock(&in->lock);
3492
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003493 return 0;
3494}
3495
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003496static int in_add_audio_effect(const struct audio_stream *stream,
3497 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003498{
Eric Laurent994a6932013-07-17 11:51:42 -07003499 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003500 return add_remove_audio_effect(stream, effect, true);
3501}
3502
3503static int in_remove_audio_effect(const struct audio_stream *stream,
3504 effect_handle_t effect)
3505{
Eric Laurent994a6932013-07-17 11:51:42 -07003506 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003507 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003508}
3509
Eric Laurent0e46adf2016-12-16 12:49:24 -08003510static int in_stop(const struct audio_stream_in* stream)
3511{
3512 struct stream_in *in = (struct stream_in *)stream;
3513 struct audio_device *adev = in->dev;
3514
3515 int ret = -ENOSYS;
3516 ALOGV("%s", __func__);
3517 pthread_mutex_lock(&adev->lock);
3518 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3519 in->capture_started && in->pcm != NULL) {
3520 pcm_stop(in->pcm);
3521 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003522 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003523 }
3524 pthread_mutex_unlock(&adev->lock);
3525 return ret;
3526}
3527
3528static int in_start(const struct audio_stream_in* stream)
3529{
3530 struct stream_in *in = (struct stream_in *)stream;
3531 struct audio_device *adev = in->dev;
3532 int ret = -ENOSYS;
3533
3534 ALOGV("%s in %p", __func__, in);
3535 pthread_mutex_lock(&adev->lock);
3536 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3537 !in->capture_started && in->pcm != NULL) {
3538 if (!in->capture_started) {
3539 ret = start_input_stream(in);
3540 if (ret == 0) {
3541 in->capture_started = true;
3542 }
3543 }
3544 }
3545 pthread_mutex_unlock(&adev->lock);
3546 return ret;
3547}
3548
3549static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3550 int32_t min_size_frames,
3551 struct audio_mmap_buffer_info *info)
3552{
3553 struct stream_in *in = (struct stream_in *)stream;
3554 struct audio_device *adev = in->dev;
3555 int ret = 0;
3556 unsigned int offset1;
3557 unsigned int frames1;
3558 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003559 uint32_t mmap_size;
3560 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003561
3562 pthread_mutex_lock(&adev->lock);
3563 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003564
Eric Laurent0e46adf2016-12-16 12:49:24 -08003565 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003566 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003567 ret = -EINVAL;
3568 goto exit;
3569 }
3570 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003571 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003572 ALOGV("%s in %p", __func__, in);
3573 ret = -ENOSYS;
3574 goto exit;
3575 }
3576 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3577 if (in->pcm_device_id < 0) {
3578 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3579 __func__, in->pcm_device_id, in->usecase);
3580 ret = -EINVAL;
3581 goto exit;
3582 }
Phil Burkbc991042017-02-24 08:06:44 -08003583
3584 adjust_mmap_period_count(&in->config, min_size_frames);
3585
Eric Laurent0e46adf2016-12-16 12:49:24 -08003586 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3587 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3588 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3589 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3590 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3591 step = "open";
3592 ret = -ENODEV;
3593 goto exit;
3594 }
3595
3596 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3597 if (ret < 0) {
3598 step = "begin";
3599 goto exit;
3600 }
3601 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003602 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003603 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003604 ret = platform_get_mmap_data_fd(adev->platform,
3605 in->pcm_device_id, 1 /*capture*/,
3606 &info->shared_memory_fd,
3607 &mmap_size);
3608 if (ret < 0) {
3609 // Fall back to non exclusive mode
3610 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3611 } else {
3612 if (mmap_size < buffer_size) {
3613 step = "mmap";
3614 goto exit;
3615 }
3616 // FIXME: indicate exclusive mode support by returning a negative buffer size
3617 info->buffer_size_frames *= -1;
3618 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08003619
Haynes Mathew George96483a22017-03-28 14:52:47 -07003620 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003621
3622 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3623 if (ret < 0) {
3624 step = "commit";
3625 goto exit;
3626 }
3627
Phil Burkbc991042017-02-24 08:06:44 -08003628 in->standby = false;
3629 ret = 0;
3630
Eric Laurent0e46adf2016-12-16 12:49:24 -08003631 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3632 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003633
3634exit:
3635 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003636 if (in->pcm == NULL) {
3637 ALOGE("%s: %s - %d", __func__, step, ret);
3638 } else {
3639 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003640 pcm_close(in->pcm);
3641 in->pcm = NULL;
3642 }
3643 }
3644 pthread_mutex_unlock(&adev->lock);
3645 return ret;
3646}
3647
3648static int in_get_mmap_position(const struct audio_stream_in *stream,
3649 struct audio_mmap_position *position)
3650{
3651 struct stream_in *in = (struct stream_in *)stream;
3652 ALOGVV("%s", __func__);
3653 if (position == NULL) {
3654 return -EINVAL;
3655 }
3656 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
3657 return -ENOSYS;
3658 }
3659 if (in->pcm == NULL) {
3660 return -ENOSYS;
3661 }
3662 struct timespec ts = { 0, 0 };
3663 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
3664 if (ret < 0) {
3665 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3666 return ret;
3667 }
Andy Hungfc044e12017-03-20 09:24:22 -07003668 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003669 return 0;
3670}
3671
3672
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003673static int adev_open_output_stream(struct audio_hw_device *dev,
3674 audio_io_handle_t handle,
3675 audio_devices_t devices,
3676 audio_output_flags_t flags,
3677 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003678 struct audio_stream_out **stream_out,
3679 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003680{
3681 struct audio_device *adev = (struct audio_device *)dev;
3682 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003683 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003684 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
3685 bool is_usb_dev = audio_is_usb_out_device(devices) &&
3686 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003687
Andy Hungd9653bd2017-08-01 19:31:39 -07003688 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
3689 return -ENOSYS;
3690 }
3691
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003692 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
3693 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003694 *stream_out = NULL;
3695 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3696
3697 if (devices == AUDIO_DEVICE_NONE)
3698 devices = AUDIO_DEVICE_OUT_SPEAKER;
3699
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003700 out->flags = flags;
3701 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003702 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003703 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003704 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003705
3706 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003707 if ((is_hdmi || is_usb_dev) &&
3708 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
3709 (flags == AUDIO_OUTPUT_FLAG_NONE ||
3710 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003711 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003712 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003713 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003714 if (config->sample_rate == 0)
3715 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3716 if (config->channel_mask == 0)
3717 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3718 if (config->format == AUDIO_FORMAT_DEFAULT)
3719 config->format = AUDIO_FORMAT_PCM_16_BIT;
3720 } else if (is_usb_dev) {
3721 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
3722 &config->format,
3723 &out->supported_formats[0],
3724 MAX_SUPPORTED_FORMATS,
3725 &config->channel_mask,
3726 &out->supported_channel_masks[0],
3727 MAX_SUPPORTED_CHANNEL_MASKS,
3728 &config->sample_rate,
3729 &out->supported_sample_rates[0],
3730 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003731 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003732 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003733 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003734 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003735 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003736
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003737
Haynes Mathew George569b7482017-05-08 14:44:27 -07003738 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003739 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003740 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003741 if (is_hdmi) {
3742 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3743 out->config = pcm_config_hdmi_multi;
3744 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3745 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3746 out->config = pcm_config_mmap_playback;
3747 out->stream.start = out_start;
3748 out->stream.stop = out_stop;
3749 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3750 out->stream.get_mmap_position = out_get_mmap_position;
3751 } else {
3752 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3753 out->config = pcm_config_hifi;
3754 }
3755
3756 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003757 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003758 if (is_hdmi) {
3759 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
3760 audio_bytes_per_sample(out->format));
3761 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003762 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003763 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003764 pthread_mutex_lock(&adev->lock);
3765 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3766 pthread_mutex_unlock(&adev->lock);
3767
3768 // reject offload during card offline to allow
3769 // fallback to s/w paths
3770 if (offline) {
3771 ret = -ENODEV;
3772 goto error_open;
3773 }
3774
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003775 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3776 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3777 ALOGE("%s: Unsupported Offload information", __func__);
3778 ret = -EINVAL;
3779 goto error_open;
3780 }
3781 if (!is_supported_format(config->offload_info.format)) {
3782 ALOGE("%s: Unsupported audio format", __func__);
3783 ret = -EINVAL;
3784 goto error_open;
3785 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003786 out->sample_rate = config->offload_info.sample_rate;
3787 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
3788 out->channel_mask = config->offload_info.channel_mask;
3789 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
3790 out->channel_mask = config->channel_mask;
3791 else
3792 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3793
3794 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003795
3796 out->compr_config.codec = (struct snd_codec *)
3797 calloc(1, sizeof(struct snd_codec));
3798
3799 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003800
3801 out->stream.set_callback = out_set_callback;
3802 out->stream.pause = out_pause;
3803 out->stream.resume = out_resume;
3804 out->stream.drain = out_drain;
3805 out->stream.flush = out_flush;
3806
3807 out->compr_config.codec->id =
3808 get_snd_codec_id(config->offload_info.format);
3809 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3810 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003811 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003812 out->compr_config.codec->bit_rate =
3813 config->offload_info.bit_rate;
3814 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003815 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003816 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3817
3818 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3819 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003820
3821 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003822 create_offload_callback_thread(out);
3823 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3824 __func__, config->offload_info.version,
3825 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003826 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07003827 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003828 case 0:
3829 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
3830 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07003831 case 8000:
3832 case 16000:
3833 case 48000:
3834 out->sample_rate = config->sample_rate;
3835 break;
3836 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003837 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
3838 config->sample_rate);
3839 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3840 ret = -EINVAL;
3841 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003842 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003843 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
3844 switch (config->channel_mask) {
3845 case AUDIO_CHANNEL_NONE:
3846 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3847 break;
3848 case AUDIO_CHANNEL_OUT_STEREO:
3849 out->channel_mask = config->channel_mask;
3850 break;
3851 default:
3852 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
3853 config->channel_mask);
3854 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3855 ret = -EINVAL;
3856 break;
3857 }
3858 switch (config->format) {
3859 case AUDIO_FORMAT_DEFAULT:
3860 out->format = AUDIO_FORMAT_PCM_16_BIT;
3861 break;
3862 case AUDIO_FORMAT_PCM_16_BIT:
3863 out->format = config->format;
3864 break;
3865 default:
3866 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
3867 config->format);
3868 config->format = AUDIO_FORMAT_PCM_16_BIT;
3869 ret = -EINVAL;
3870 break;
3871 }
3872 if (ret != 0)
3873 goto error_open;
3874
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003875 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3876 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003877 out->config.rate = out->sample_rate;
3878 out->config.channels =
3879 audio_channel_count_from_out_mask(out->channel_mask);
3880 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003881 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003882 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
3883 switch (config->sample_rate) {
3884 case 0:
3885 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3886 break;
3887 case 8000:
3888 case 16000:
3889 case 32000:
3890 case 48000:
3891 out->sample_rate = config->sample_rate;
3892 break;
3893 default:
3894 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
3895 config->sample_rate);
3896 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3897 ret = -EINVAL;
3898 break;
3899 }
Eric Laurentad2dde92017-09-20 18:27:31 -07003900 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003901 switch (config->channel_mask) {
3902 case AUDIO_CHANNEL_NONE:
3903 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3904 break;
3905 case AUDIO_CHANNEL_OUT_STEREO:
3906 out->channel_mask = config->channel_mask;
3907 break;
3908 default:
3909 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
3910 config->channel_mask);
3911 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3912 ret = -EINVAL;
3913 break;
3914 }
3915 switch (config->format) {
3916 case AUDIO_FORMAT_DEFAULT:
3917 out->format = AUDIO_FORMAT_PCM_16_BIT;
3918 break;
3919 case AUDIO_FORMAT_PCM_16_BIT:
3920 out->format = config->format;
3921 break;
3922 default:
3923 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
3924 config->format);
3925 config->format = AUDIO_FORMAT_PCM_16_BIT;
3926 ret = -EINVAL;
3927 break;
3928 }
3929 if (ret != 0)
3930 goto error_open;
3931
vivek mehtaa68fea62017-06-08 19:04:02 -07003932 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07003933 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
3934 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003935 out->config.rate = out->sample_rate;
3936 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07003937 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003938 out->sample_rate,
3939 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07003940 out->config.channels,
3941 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003942 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07003943 out->config.period_size = buffer_size / frame_size;
3944 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
3945 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003946 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003947 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003948 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3949 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003950 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003951 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3952 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003953 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003954 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003955 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003956 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003957 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003958 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3959 out->config = pcm_config_mmap_playback;
3960 out->stream.start = out_start;
3961 out->stream.stop = out_stop;
3962 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3963 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003964 } else {
3965 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3966 out->config = pcm_config_low_latency;
3967 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003968
3969 if (config->sample_rate == 0) {
3970 out->sample_rate = out->config.rate;
3971 } else {
3972 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003973 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003974 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
3975 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
3976 } else {
3977 out->channel_mask = config->channel_mask;
3978 }
3979 if (config->format == AUDIO_FORMAT_DEFAULT)
3980 out->format = audio_format_from_pcm_format(out->config.format);
3981 else if (!audio_is_linear_pcm(config->format)) {
3982 config->format = AUDIO_FORMAT_PCM_16_BIT;
3983 ret = -EINVAL;
3984 goto error_open;
3985 } else {
3986 out->format = config->format;
3987 }
3988
3989 out->config.rate = out->sample_rate;
3990 out->config.channels =
3991 audio_channel_count_from_out_mask(out->channel_mask);
3992 if (out->format != audio_format_from_pcm_format(out->config.format)) {
3993 out->config.format = pcm_format_from_audio_format(out->format);
3994 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003995 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003996
3997 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
3998 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003999 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004000 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
4001 __func__, config->sample_rate, config->format, config->channel_mask);
4002 config->sample_rate = out->sample_rate;
4003 config->format = out->format;
4004 config->channel_mask = out->channel_mask;
4005 ret = -EINVAL;
4006 goto error_open;
4007 }
4008
Andy Hung6fcba9c2014-03-18 11:53:32 -07004009 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
4010 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004011
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004012 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004013 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004014 adev->primary_output = out;
4015 else {
4016 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004017 ret = -EEXIST;
4018 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004019 }
4020 }
4021
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004022 /* Check if this usecase is already existing */
4023 pthread_mutex_lock(&adev->lock);
4024 if (get_usecase_from_list(adev, out->usecase) != NULL) {
4025 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004026 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004027 ret = -EEXIST;
4028 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004029 }
4030 pthread_mutex_unlock(&adev->lock);
4031
4032 out->stream.common.get_sample_rate = out_get_sample_rate;
4033 out->stream.common.set_sample_rate = out_set_sample_rate;
4034 out->stream.common.get_buffer_size = out_get_buffer_size;
4035 out->stream.common.get_channels = out_get_channels;
4036 out->stream.common.get_format = out_get_format;
4037 out->stream.common.set_format = out_set_format;
4038 out->stream.common.standby = out_standby;
4039 out->stream.common.dump = out_dump;
4040 out->stream.common.set_parameters = out_set_parameters;
4041 out->stream.common.get_parameters = out_get_parameters;
4042 out->stream.common.add_audio_effect = out_add_audio_effect;
4043 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4044 out->stream.get_latency = out_get_latency;
4045 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004046#ifdef NO_AUDIO_OUT
4047 out->stream.write = out_write_for_no_output;
4048#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004049 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004050#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004051 out->stream.get_render_position = out_get_render_position;
4052 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004053 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004054
Eric Laurent0e46adf2016-12-16 12:49:24 -08004055 if (out->realtime)
4056 out->af_period_multiplier = af_period_multiplier;
4057 else
4058 out->af_period_multiplier = 1;
4059
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004060 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004061 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004062 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004063
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004064 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004065 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004066 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4067
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004068 config->format = out->stream.common.get_format(&out->stream.common);
4069 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4070 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4071
Andy Hunga452b0a2017-03-15 14:51:15 -07004072 out->error_log = error_log_create(
4073 ERROR_LOG_ENTRIES,
4074 1000000000 /* aggregate consecutive identical errors within one second in ns */);
4075
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004076 /*
4077 By locking output stream before registering, we allow the callback
4078 to update stream's state only after stream's initial state is set to
4079 adev state.
4080 */
4081 lock_output_stream(out);
4082 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4083 pthread_mutex_lock(&adev->lock);
4084 out->card_status = adev->card_status;
4085 pthread_mutex_unlock(&adev->lock);
4086 pthread_mutex_unlock(&out->lock);
4087
vivek mehta4a824772017-06-08 19:05:49 -07004088 stream_app_type_cfg_init(&out->app_type_cfg);
4089
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004090 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004091
Eric Laurent994a6932013-07-17 11:51:42 -07004092 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004093 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004094
4095error_open:
4096 free(out);
4097 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07004098 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004099 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004100}
4101
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004102static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004103 struct audio_stream_out *stream)
4104{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004105 struct stream_out *out = (struct stream_out *)stream;
4106 struct audio_device *adev = out->dev;
4107
Eric Laurent994a6932013-07-17 11:51:42 -07004108 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004109
4110 // must deregister from sndmonitor first to prevent races
4111 // between the callback and close_stream
4112 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004113 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004114 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
4115 destroy_offload_callback_thread(out);
4116
4117 if (out->compr_config.codec != NULL)
4118 free(out->compr_config.codec);
4119 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004120
4121 if (adev->voice_tx_output == out)
4122 adev->voice_tx_output = NULL;
4123
Andy Hunga452b0a2017-03-15 14:51:15 -07004124 error_log_destroy(out->error_log);
4125 out->error_log = NULL;
4126
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004127 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004128 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004129 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004130 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004131 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004132}
4133
4134static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4135{
4136 struct audio_device *adev = (struct audio_device *)dev;
4137 struct str_parms *parms;
4138 char *str;
4139 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004140 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004141 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07004142 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004143
Joe Onorato188b6222016-03-01 11:02:27 -08004144 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004145
4146 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004147
4148 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004149 status = voice_set_parameters(adev, parms);
4150 if (status != 0) {
4151 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004152 }
4153
4154 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4155 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07004156 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004157 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4158 adev->bluetooth_nrec = true;
4159 else
4160 adev->bluetooth_nrec = false;
4161 }
4162
4163 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4164 if (ret >= 0) {
4165 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4166 adev->screen_off = false;
4167 else
4168 adev->screen_off = true;
4169 }
4170
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004171 ret = str_parms_get_int(parms, "rotation", &val);
4172 if (ret >= 0) {
4173 bool reverse_speakers = false;
4174 switch(val) {
4175 // FIXME: note that the code below assumes that the speakers are in the correct placement
4176 // relative to the user when the device is rotated 90deg from its default rotation. This
4177 // assumption is device-specific, not platform-specific like this code.
4178 case 270:
4179 reverse_speakers = true;
4180 break;
4181 case 0:
4182 case 90:
4183 case 180:
4184 break;
4185 default:
4186 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07004187 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004188 }
Eric Laurent03f09432014-03-25 18:09:11 -07004189 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004190 // check and set swap
4191 // - check if orientation changed and speaker active
4192 // - set rotation and cache the rotation value
4193 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004194 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004195 }
4196
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004197 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4198 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004199 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004200 }
4201
David Linee3fe402017-03-13 10:00:42 -07004202 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4203 if (ret >= 0) {
4204 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004205 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004206 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4207 if (ret >= 0) {
4208 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004209 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004210 }
Eric Laurent99dab492017-06-17 15:19:08 -07004211 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004212 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4213 if (ret >= 0) {
4214 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004215 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004216 }
4217 }
4218 }
4219
4220 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4221 if (ret >= 0) {
4222 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004223 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004224 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4225 if (ret >= 0) {
4226 const int card = atoi(value);
4227
Eric Laurent99dab492017-06-17 15:19:08 -07004228 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004229 }
Eric Laurent99dab492017-06-17 15:19:08 -07004230 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004231 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4232 if (ret >= 0) {
4233 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004234 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004235 }
4236 }
4237 }
4238
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004239 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004240done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004241 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004242 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004243 ALOGV("%s: exit with code(%d)", __func__, status);
4244 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004245}
4246
4247static char* adev_get_parameters(const struct audio_hw_device *dev,
4248 const char *keys)
4249{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004250 struct audio_device *adev = (struct audio_device *)dev;
4251 struct str_parms *reply = str_parms_create();
4252 struct str_parms *query = str_parms_create_str(keys);
4253 char *str;
4254
4255 pthread_mutex_lock(&adev->lock);
4256
4257 voice_get_parameters(adev, query, reply);
4258 str = str_parms_to_str(reply);
4259 str_parms_destroy(query);
4260 str_parms_destroy(reply);
4261
4262 pthread_mutex_unlock(&adev->lock);
4263 ALOGV("%s: exit: returns - %s", __func__, str);
4264 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004265}
4266
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004267static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004268{
4269 return 0;
4270}
4271
Haynes Mathew George5191a852013-09-11 14:19:36 -07004272static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4273{
4274 int ret;
4275 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004276
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004277 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4278
Haynes Mathew George5191a852013-09-11 14:19:36 -07004279 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004280 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004281 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004282
Haynes Mathew George5191a852013-09-11 14:19:36 -07004283 return ret;
4284}
4285
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004286static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004287{
4288 return -ENOSYS;
4289}
4290
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004291static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4292 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004293{
4294 return -ENOSYS;
4295}
4296
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004297static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004298{
4299 return -ENOSYS;
4300}
4301
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004302static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004303{
4304 return -ENOSYS;
4305}
4306
4307static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4308{
4309 struct audio_device *adev = (struct audio_device *)dev;
4310
4311 pthread_mutex_lock(&adev->lock);
4312 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004313 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004314 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004315 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4316 voice_is_in_call(adev)) {
4317 voice_stop_call(adev);
4318 adev->current_call_output = NULL;
4319 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004320 }
4321 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004322
4323 audio_extn_extspk_set_mode(adev->extspk, mode);
4324
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004325 return 0;
4326}
4327
4328static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4329{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004330 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004331 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004332
Eric Laurent2bafff12016-03-17 12:17:23 -07004333 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004334 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004335 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4336 ret = audio_extn_hfp_set_mic_mute(adev, state);
4337 } else {
4338 ret = voice_set_mic_mute(adev, state);
4339 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004340 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004341 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004342
4343 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004344}
4345
4346static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4347{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004348 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004349 return 0;
4350}
4351
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004352static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004353 const struct audio_config *config)
4354{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004355 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004356
Eric Laurent74b55762017-07-09 17:04:53 -07004357 /* Don't know if USB HIFI in this context so use true to be conservative */
4358 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4359 true /*is_usb_hifi */) != 0)
4360 return 0;
4361
vivek mehtaa68fea62017-06-08 19:04:02 -07004362 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4363 config->sample_rate, config->format,
4364 channel_count,
4365 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004366}
4367
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004368static bool adev_input_allow_hifi_record(struct audio_device *adev,
4369 audio_devices_t devices,
4370 audio_input_flags_t flags,
4371 audio_source_t source) {
4372 const bool allowed = true;
4373
4374 if (!audio_is_usb_in_device(devices))
4375 return !allowed;
4376
4377 switch (flags) {
4378 case AUDIO_INPUT_FLAG_NONE:
4379 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4380 break;
4381 default:
4382 return !allowed;
4383 }
4384
4385 switch (source) {
4386 case AUDIO_SOURCE_DEFAULT:
4387 case AUDIO_SOURCE_MIC:
4388 case AUDIO_SOURCE_UNPROCESSED:
4389 break;
4390 default:
4391 return !allowed;
4392 }
4393
4394 switch (adev->mode) {
4395 case 0:
4396 break;
4397 default:
4398 return !allowed;
4399 }
4400
4401 return allowed;
4402}
4403
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004404static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004405 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004406 audio_devices_t devices,
4407 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004408 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004409 audio_input_flags_t flags,
4410 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004411 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004412{
4413 struct audio_device *adev = (struct audio_device *)dev;
4414 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004415 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004416 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004417 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004418 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004419 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4420 devices,
4421 flags,
4422 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004423 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004424 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004425
Andy Hungd9653bd2017-08-01 19:31:39 -07004426 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
4427 return -ENOSYS;
4428 }
4429
Eric Laurent74b55762017-07-09 17:04:53 -07004430 if (!(is_usb_dev && may_use_hifi_record)) {
4431 if (config->sample_rate == 0)
4432 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4433 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4434 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4435 if (config->format == AUDIO_FORMAT_DEFAULT)
4436 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004437
Eric Laurent74b55762017-07-09 17:04:53 -07004438 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
4439
4440 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
4441 return -EINVAL;
4442 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004443
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004444 if (audio_extn_tfa_98xx_is_supported() &&
4445 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004446 return -EINVAL;
4447
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004448 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4449
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004450 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004451 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004452
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004453 in->stream.common.get_sample_rate = in_get_sample_rate;
4454 in->stream.common.set_sample_rate = in_set_sample_rate;
4455 in->stream.common.get_buffer_size = in_get_buffer_size;
4456 in->stream.common.get_channels = in_get_channels;
4457 in->stream.common.get_format = in_get_format;
4458 in->stream.common.set_format = in_set_format;
4459 in->stream.common.standby = in_standby;
4460 in->stream.common.dump = in_dump;
4461 in->stream.common.set_parameters = in_set_parameters;
4462 in->stream.common.get_parameters = in_get_parameters;
4463 in->stream.common.add_audio_effect = in_add_audio_effect;
4464 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4465 in->stream.set_gain = in_set_gain;
4466 in->stream.read = in_read;
4467 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08004468 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004469
4470 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004471 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004472 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004473 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004474 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004475 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004476
Haynes Mathew George569b7482017-05-08 14:44:27 -07004477 if (is_usb_dev && may_use_hifi_record) {
4478 /* HiFi record selects an appropriate format, channel, rate combo
4479 depending on sink capabilities*/
4480 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
4481 &config->format,
4482 &in->supported_formats[0],
4483 MAX_SUPPORTED_FORMATS,
4484 &config->channel_mask,
4485 &in->supported_channel_masks[0],
4486 MAX_SUPPORTED_CHANNEL_MASKS,
4487 &config->sample_rate,
4488 &in->supported_sample_rates[0],
4489 MAX_SUPPORTED_SAMPLE_RATES);
4490 if (ret != 0) {
4491 ret = -EINVAL;
4492 goto err_open;
4493 }
Eric Laurent74b55762017-07-09 17:04:53 -07004494 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004495 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07004496 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07004497 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
4498 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
4499 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4500 bool ret_error = false;
4501 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4502 from HAL is 8_24
4503 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4504 8_24 return error indicating supported format is 8_24
4505 *> In case of any other source requesting 24 bit or float return error
4506 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07004507
vivek mehta57ff9b52016-04-28 14:13:08 -07004508 on error flinger will retry with supported format passed
4509 */
4510 if (source != AUDIO_SOURCE_UNPROCESSED) {
4511 config->format = AUDIO_FORMAT_PCM_16_BIT;
4512 ret_error = true;
4513 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
4514 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
4515 ret_error = true;
4516 }
4517
4518 if (ret_error) {
4519 ret = -EINVAL;
4520 goto err_open;
4521 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004522 }
4523
vivek mehta57ff9b52016-04-28 14:13:08 -07004524 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07004525 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07004526
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004527 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004528 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
4529 if (config->sample_rate == 0)
4530 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4531 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4532 config->sample_rate != 8000) {
4533 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4534 ret = -EINVAL;
4535 goto err_open;
4536 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004537
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004538 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4539 config->format = AUDIO_FORMAT_PCM_16_BIT;
4540 ret = -EINVAL;
4541 goto err_open;
4542 }
4543
4544 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4545 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07004546 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004547 } else if (is_usb_dev && may_use_hifi_record) {
4548 in->usecase = USECASE_AUDIO_RECORD_HIFI;
4549 in->config = pcm_config_audio_capture;
4550 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004551 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4552 config->sample_rate,
4553 config->format,
4554 channel_count,
4555 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004556 in->config.period_size = buffer_size / frame_size;
4557 in->config.rate = config->sample_rate;
4558 in->af_period_multiplier = 1;
4559 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004560 } else {
4561 in->usecase = USECASE_AUDIO_RECORD;
4562 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08004563 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004564 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07004565#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004566 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07004567#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08004568 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004569 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08004570 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004571 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004572 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4573 config->sample_rate,
4574 config->format,
4575 channel_count,
4576 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004577 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004578 in->config.rate = config->sample_rate;
4579 in->af_period_multiplier = 1;
4580 } else {
4581 // period size is left untouched for rt mode playback
4582 in->config = pcm_config_audio_capture_rt;
4583 in->af_period_multiplier = af_period_multiplier;
4584 }
4585 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
4586 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004587 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08004588 in->usecase = USECASE_AUDIO_RECORD_MMAP;
4589 in->config = pcm_config_mmap_capture;
4590 in->stream.start = in_start;
4591 in->stream.stop = in_stop;
4592 in->stream.create_mmap_buffer = in_create_mmap_buffer;
4593 in->stream.get_mmap_position = in_get_mmap_position;
4594 in->af_period_multiplier = 1;
4595 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07004596 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07004597 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07004598 (config->sample_rate == 8000 ||
4599 config->sample_rate == 16000 ||
4600 config->sample_rate == 32000 ||
4601 config->sample_rate == 48000) &&
4602 channel_count == 1) {
4603 in->usecase = USECASE_AUDIO_RECORD_VOIP;
4604 in->config = pcm_config_audio_capture;
4605 frame_size = audio_stream_in_frame_size(&in->stream);
4606 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
4607 config->sample_rate,
4608 config->format,
4609 channel_count, false /*is_low_latency*/);
4610 in->config.period_size = buffer_size / frame_size;
4611 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
4612 in->config.rate = config->sample_rate;
4613 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004614 } else {
4615 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004616 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004617 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4618 config->sample_rate,
4619 config->format,
4620 channel_count,
4621 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004622 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004623 in->config.rate = config->sample_rate;
4624 in->af_period_multiplier = 1;
4625 }
4626 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
4627 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004628 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004629
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004630 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07004631 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004632
Andy Hungd13f0d32017-06-12 13:58:37 -07004633 in->error_log = error_log_create(
4634 ERROR_LOG_ENTRIES,
4635 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
4636
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004637 /* This stream could be for sound trigger lab,
4638 get sound trigger pcm if present */
4639 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004640
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004641 lock_input_stream(in);
4642 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
4643 pthread_mutex_lock(&adev->lock);
4644 in->card_status = adev->card_status;
4645 pthread_mutex_unlock(&adev->lock);
4646 pthread_mutex_unlock(&in->lock);
4647
vivek mehta4a824772017-06-08 19:05:49 -07004648 stream_app_type_cfg_init(&in->app_type_cfg);
4649
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004650 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004651 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004652 return 0;
4653
4654err_open:
4655 free(in);
4656 *stream_in = NULL;
4657 return ret;
4658}
4659
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004660static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004661 struct audio_stream_in *stream)
4662{
Andy Hungd13f0d32017-06-12 13:58:37 -07004663 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004664 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004665
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004666 // must deregister from sndmonitor first to prevent races
4667 // between the callback and close_stream
4668 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004669 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07004670
4671 error_log_destroy(in->error_log);
4672 in->error_log = NULL;
4673
Andy Hung0dbb52b2017-08-09 13:51:38 -07004674 pthread_mutex_destroy(&in->pre_lock);
4675 pthread_mutex_destroy(&in->lock);
4676
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004677 free(stream);
4678
4679 return;
4680}
4681
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004682static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004683{
4684 return 0;
4685}
4686
Andy Hung31aca912014-03-20 17:14:59 -07004687/* verifies input and output devices and their capabilities.
4688 *
4689 * This verification is required when enabling extended bit-depth or
4690 * sampling rates, as not all qcom products support it.
4691 *
4692 * Suitable for calling only on initialization such as adev_open().
4693 * It fills the audio_device use_case_table[] array.
4694 *
4695 * Has a side-effect that it needs to configure audio routing / devices
4696 * in order to power up the devices and read the device parameters.
4697 * It does not acquire any hw device lock. Should restore the devices
4698 * back to "normal state" upon completion.
4699 */
4700static int adev_verify_devices(struct audio_device *adev)
4701{
4702 /* enumeration is a bit difficult because one really wants to pull
4703 * the use_case, device id, etc from the hidden pcm_device_table[].
4704 * In this case there are the following use cases and device ids.
4705 *
4706 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
4707 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004708 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07004709 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
4710 * [USECASE_AUDIO_RECORD] = {0, 0},
4711 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
4712 * [USECASE_VOICE_CALL] = {2, 2},
4713 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004714 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07004715 * USECASE_VOICE_CALL omitted, but possible for either input or output.
4716 */
4717
4718 /* should be the usecases enabled in adev_open_input_stream() */
4719 static const int test_in_usecases[] = {
4720 USECASE_AUDIO_RECORD,
4721 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
4722 };
4723 /* should be the usecases enabled in adev_open_output_stream()*/
4724 static const int test_out_usecases[] = {
4725 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
4726 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
4727 };
4728 static const usecase_type_t usecase_type_by_dir[] = {
4729 PCM_PLAYBACK,
4730 PCM_CAPTURE,
4731 };
4732 static const unsigned flags_by_dir[] = {
4733 PCM_OUT,
4734 PCM_IN,
4735 };
4736
4737 size_t i;
4738 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004739 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07004740 char info[512]; /* for possible debug info */
4741
4742 for (dir = 0; dir < 2; ++dir) {
4743 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
4744 const unsigned flags_dir = flags_by_dir[dir];
4745 const size_t testsize =
4746 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
4747 const int *testcases =
4748 dir ? test_in_usecases : test_out_usecases;
4749 const audio_devices_t audio_device =
4750 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
4751
4752 for (i = 0; i < testsize; ++i) {
4753 const audio_usecase_t audio_usecase = testcases[i];
4754 int device_id;
4755 snd_device_t snd_device;
4756 struct pcm_params **pparams;
4757 struct stream_out out;
4758 struct stream_in in;
4759 struct audio_usecase uc_info;
4760 int retval;
4761
4762 pparams = &adev->use_case_table[audio_usecase];
4763 pcm_params_free(*pparams); /* can accept null input */
4764 *pparams = NULL;
4765
4766 /* find the device ID for the use case (signed, for error) */
4767 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
4768 if (device_id < 0)
4769 continue;
4770
4771 /* prepare structures for device probing */
4772 memset(&uc_info, 0, sizeof(uc_info));
4773 uc_info.id = audio_usecase;
4774 uc_info.type = usecase_type;
4775 if (dir) {
4776 adev->active_input = &in;
4777 memset(&in, 0, sizeof(in));
4778 in.device = audio_device;
4779 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4780 uc_info.stream.in = &in;
4781 } else {
4782 adev->active_input = NULL;
4783 }
4784 memset(&out, 0, sizeof(out));
4785 out.devices = audio_device; /* only field needed in select_devices */
4786 uc_info.stream.out = &out;
4787 uc_info.devices = audio_device;
4788 uc_info.in_snd_device = SND_DEVICE_NONE;
4789 uc_info.out_snd_device = SND_DEVICE_NONE;
4790 list_add_tail(&adev->usecase_list, &uc_info.list);
4791
4792 /* select device - similar to start_(in/out)put_stream() */
4793 retval = select_devices(adev, audio_usecase);
4794 if (retval >= 0) {
4795 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4796#if LOG_NDEBUG == 0
4797 if (*pparams) {
4798 ALOGV("%s: (%s) card %d device %d", __func__,
4799 dir ? "input" : "output", card_id, device_id);
4800 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004801 } else {
4802 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4803 }
4804#endif
4805 }
4806
4807 /* deselect device - similar to stop_(in/out)put_stream() */
4808 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004809 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004810 /* 2. Disable the rx device */
4811 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004812 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004813 list_remove(&uc_info.list);
4814 }
4815 }
4816 adev->active_input = NULL; /* restore adev state */
4817 return 0;
4818}
4819
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004820static int adev_close(hw_device_t *device)
4821{
Andy Hung31aca912014-03-20 17:14:59 -07004822 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004823 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004824
4825 if (!adev)
4826 return 0;
4827
4828 pthread_mutex_lock(&adev_init_lock);
4829
4830 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004831 audio_extn_snd_mon_unregister_listener(adev);
4832 audio_extn_tfa_98xx_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004833 audio_route_free(adev->audio_route);
4834 free(adev->snd_dev_ref_cnt);
4835 platform_deinit(adev->platform);
4836 audio_extn_extspk_deinit(adev->extspk);
4837 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004838 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004839 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4840 pcm_params_free(adev->use_case_table[i]);
4841 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004842 if (adev->adm_deinit)
4843 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004844 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004845 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004846 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004847
4848 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004849
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004850 return 0;
4851}
4852
Glenn Kasten4f993392014-05-14 07:30:48 -07004853/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4854 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4855 * just that it _might_ work.
4856 */
4857static int period_size_is_plausible_for_low_latency(int period_size)
4858{
4859 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004860 case 48:
4861 case 96:
4862 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004863 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004864 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004865 case 240:
4866 case 320:
4867 case 480:
4868 return 1;
4869 default:
4870 return 0;
4871 }
4872}
4873
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004874static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4875{
4876 int card;
4877 card_status_t status;
4878
4879 if (!parms)
4880 return;
4881
4882 if (parse_snd_card_status(parms, &card, &status) < 0)
4883 return;
4884
4885 pthread_mutex_lock(&adev->lock);
4886 bool valid_cb = (card == adev->snd_card);
4887 if (valid_cb) {
4888 if (adev->card_status != status) {
4889 adev->card_status = status;
4890 platform_snd_card_update(adev->platform, status);
4891 }
4892 }
4893 pthread_mutex_unlock(&adev->lock);
4894 return;
4895}
4896
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004897static int adev_open(const hw_module_t *module, const char *name,
4898 hw_device_t **device)
4899{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004900 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004901
Eric Laurent2bafff12016-03-17 12:17:23 -07004902 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004903 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004904 pthread_mutex_lock(&adev_init_lock);
4905 if (audio_device_ref_count != 0) {
4906 *device = &adev->device.common;
4907 audio_device_ref_count++;
4908 ALOGV("%s: returning existing instance of adev", __func__);
4909 ALOGV("%s: exit", __func__);
4910 pthread_mutex_unlock(&adev_init_lock);
4911 return 0;
4912 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004913 adev = calloc(1, sizeof(struct audio_device));
4914
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004915 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4916
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004917 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4918 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4919 adev->device.common.module = (struct hw_module_t *)module;
4920 adev->device.common.close = adev_close;
4921
4922 adev->device.init_check = adev_init_check;
4923 adev->device.set_voice_volume = adev_set_voice_volume;
4924 adev->device.set_master_volume = adev_set_master_volume;
4925 adev->device.get_master_volume = adev_get_master_volume;
4926 adev->device.set_master_mute = adev_set_master_mute;
4927 adev->device.get_master_mute = adev_get_master_mute;
4928 adev->device.set_mode = adev_set_mode;
4929 adev->device.set_mic_mute = adev_set_mic_mute;
4930 adev->device.get_mic_mute = adev_get_mic_mute;
4931 adev->device.set_parameters = adev_set_parameters;
4932 adev->device.get_parameters = adev_get_parameters;
4933 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4934 adev->device.open_output_stream = adev_open_output_stream;
4935 adev->device.close_output_stream = adev_close_output_stream;
4936 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004937
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004938 adev->device.close_input_stream = adev_close_input_stream;
4939 adev->device.dump = adev_dump;
4940
4941 /* Set the default route before the PCM stream is opened */
4942 pthread_mutex_lock(&adev->lock);
4943 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004944 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004945 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004946 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004947 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004948 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004949 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004950 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004951 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004952 pthread_mutex_unlock(&adev->lock);
4953
4954 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004955 adev->platform = platform_init(adev);
4956 if (!adev->platform) {
4957 free(adev->snd_dev_ref_cnt);
4958 free(adev);
4959 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4960 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004961 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004962 return -EINVAL;
4963 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05004964 adev->extspk = audio_extn_extspk_init(adev);
4965
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004966 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4967 if (adev->visualizer_lib == NULL) {
4968 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4969 } else {
4970 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4971 adev->visualizer_start_output =
4972 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4973 "visualizer_hal_start_output");
4974 adev->visualizer_stop_output =
4975 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4976 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07004977 }
4978
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004979 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4980 if (adev->offload_effects_lib == NULL) {
4981 ALOGW("%s: DLOPEN failed for %s", __func__,
4982 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4983 } else {
4984 ALOGV("%s: DLOPEN successful for %s", __func__,
4985 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4986 adev->offload_effects_start_output =
4987 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4988 "offload_effects_bundle_hal_start_output");
4989 adev->offload_effects_stop_output =
4990 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4991 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07004992 }
4993
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004994 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4995 if (adev->adm_lib == NULL) {
4996 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4997 } else {
4998 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4999 adev->adm_init = (adm_init_t)
5000 dlsym(adev->adm_lib, "adm_init");
5001 adev->adm_deinit = (adm_deinit_t)
5002 dlsym(adev->adm_lib, "adm_deinit");
5003 adev->adm_register_input_stream = (adm_register_input_stream_t)
5004 dlsym(adev->adm_lib, "adm_register_input_stream");
5005 adev->adm_register_output_stream = (adm_register_output_stream_t)
5006 dlsym(adev->adm_lib, "adm_register_output_stream");
5007 adev->adm_deregister_stream = (adm_deregister_stream_t)
5008 dlsym(adev->adm_lib, "adm_deregister_stream");
5009 adev->adm_request_focus = (adm_request_focus_t)
5010 dlsym(adev->adm_lib, "adm_request_focus");
5011 adev->adm_abandon_focus = (adm_abandon_focus_t)
5012 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08005013 adev->adm_set_config = (adm_set_config_t)
5014 dlsym(adev->adm_lib, "adm_set_config");
5015 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5016 dlsym(adev->adm_lib, "adm_request_focus_v2");
5017 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5018 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5019 adev->adm_on_routing_change = (adm_on_routing_change_t)
5020 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005021 }
5022
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005023 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005024 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005025
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005026 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005027
Andy Hung31aca912014-03-20 17:14:59 -07005028 if (k_enable_extended_precision)
5029 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005030
Glenn Kasten4f993392014-05-14 07:30:48 -07005031 char value[PROPERTY_VALUE_MAX];
5032 int trial;
5033 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5034 trial = atoi(value);
5035 if (period_size_is_plausible_for_low_latency(trial)) {
5036 pcm_config_low_latency.period_size = trial;
5037 pcm_config_low_latency.start_threshold = trial / 4;
5038 pcm_config_low_latency.avail_min = trial / 4;
5039 configured_low_latency_capture_period_size = trial;
5040 }
5041 }
5042 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5043 trial = atoi(value);
5044 if (period_size_is_plausible_for_low_latency(trial)) {
5045 configured_low_latency_capture_period_size = trial;
5046 }
5047 }
5048
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005049 // commented as full set of app type cfg is sent from platform
5050 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005051 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005052
5053 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5054 af_period_multiplier = atoi(value);
5055 if (af_period_multiplier < 0) {
5056 af_period_multiplier = 2;
5057 } else if (af_period_multiplier > 4) {
5058 af_period_multiplier = 4;
5059 }
5060 ALOGV("new period_multiplier = %d", af_period_multiplier);
5061 }
5062
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005063 audio_extn_tfa_98xx_init(adev);
5064
vivek mehta1a9b7c02015-06-25 11:49:38 -07005065 pthread_mutex_unlock(&adev_init_lock);
5066
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005067 if (adev->adm_init)
5068 adev->adm_data = adev->adm_init();
5069
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005070 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005071 audio_extn_snd_mon_init();
5072 pthread_mutex_lock(&adev->lock);
5073 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
5074 adev->card_status = CARD_STATUS_ONLINE;
5075 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005076 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005077
Eric Laurent2bafff12016-03-17 12:17:23 -07005078 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005079 return 0;
5080}
5081
5082static struct hw_module_methods_t hal_module_methods = {
5083 .open = adev_open,
5084};
5085
5086struct audio_module HAL_MODULE_INFO_SYM = {
5087 .common = {
5088 .tag = HARDWARE_MODULE_TAG,
5089 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5090 .hal_api_version = HARDWARE_HAL_API_VERSION,
5091 .id = AUDIO_HARDWARE_MODULE_ID,
5092 .name = "QCOM Audio HAL",
5093 .author = "Code Aurora Forum",
5094 .methods = &hal_module_methods,
5095 },
5096};