blob: e689b283494625c5a3d652006126436825442e91 [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>
52#include <audio_utils/power.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include "audio_hw.h"
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -080054#include "audio_extn.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070055#include "platform_api.h"
56#include <platform.h>
Vineeta Srivastava4b89e372014-06-19 14:21:42 -070057#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080058
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070059#include "sound/compress_params.h"
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -080060#include "audio_extn/tfa_98xx.h"
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070061
Eric Laurent397db572016-05-11 11:31:47 -070062/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
63 * COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
Marco Nelissen32093f52015-04-08 15:14:02 -070064#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070065// 2 buffers causes problems with high bitrate files
66#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070067/* ToDo: Check and update a proper value in msec */
68#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
69#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
70
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070071#define PROXY_OPEN_RETRY_COUNT 100
72#define PROXY_OPEN_WAIT_TIME 20
73
vivek mehtadae44712015-07-27 14:13:18 -070074#define MIN_CHANNEL_COUNT 1
75#define DEFAULT_CHANNEL_COUNT 2
76
Jean-Michel Trivic0750692015-10-12 12:12:32 -070077#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
78#define MAX_CHANNEL_COUNT 1
79#else
vivek mehtadae44712015-07-27 14:13:18 -070080#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
81#define XSTR(x) STR(x)
82#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070083#endif
vivek mehtadae44712015-07-27 14:13:18 -070084
Haynes Mathew George03c40102016-01-29 17:57:48 -080085#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
86
Glenn Kasten4f993392014-05-14 07:30:48 -070087static unsigned int configured_low_latency_capture_period_size =
88 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
89
Eric Laurent0e46adf2016-12-16 12:49:24 -080090
91#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Phil Burkbc991042017-02-24 08:06:44 -080092#define MMAP_PERIOD_COUNT_MIN 32
93#define MMAP_PERIOD_COUNT_MAX 512
94#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
Eric Laurent0e46adf2016-12-16 12:49:24 -080095
96
Andy Hung31aca912014-03-20 17:14:59 -070097/* This constant enables extended precision handling.
98 * TODO The flag is off until more testing is done.
99 */
100static const bool k_enable_extended_precision = false;
101
Eric Laurentb23d5282013-05-14 15:27:20 -0700102struct pcm_config pcm_config_deep_buffer = {
vivek mehtadae44712015-07-27 14:13:18 -0700103 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700104 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
105 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
106 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
107 .format = PCM_FORMAT_S16_LE,
108 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
109 .stop_threshold = INT_MAX,
110 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
111};
112
113struct pcm_config pcm_config_low_latency = {
vivek mehtadae44712015-07-27 14:13:18 -0700114 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700115 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
116 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
117 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
118 .format = PCM_FORMAT_S16_LE,
119 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
120 .stop_threshold = INT_MAX,
121 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
122};
123
Haynes Mathew George03c40102016-01-29 17:57:48 -0800124static int af_period_multiplier = 4;
125struct pcm_config pcm_config_rt = {
126 .channels = DEFAULT_CHANNEL_COUNT,
127 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
128 .period_size = ULL_PERIOD_SIZE, //1 ms
129 .period_count = 512, //=> buffer size is 512ms
130 .format = PCM_FORMAT_S16_LE,
131 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
132 .stop_threshold = INT_MAX,
133 .silence_threshold = 0,
134 .silence_size = 0,
135 .avail_min = ULL_PERIOD_SIZE, //1 ms
136};
137
Eric Laurentb23d5282013-05-14 15:27:20 -0700138struct pcm_config pcm_config_hdmi_multi = {
139 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
140 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
141 .period_size = HDMI_MULTI_PERIOD_SIZE,
142 .period_count = HDMI_MULTI_PERIOD_COUNT,
143 .format = PCM_FORMAT_S16_LE,
144 .start_threshold = 0,
145 .stop_threshold = INT_MAX,
146 .avail_min = 0,
147};
148
Eric Laurent0e46adf2016-12-16 12:49:24 -0800149struct pcm_config pcm_config_mmap_playback = {
150 .channels = DEFAULT_CHANNEL_COUNT,
151 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
152 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800153 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800154 .format = PCM_FORMAT_S16_LE,
155 .start_threshold = MMAP_PERIOD_SIZE*8,
156 .stop_threshold = INT32_MAX,
157 .silence_threshold = 0,
158 .silence_size = 0,
159 .avail_min = MMAP_PERIOD_SIZE, //1 ms
160};
161
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800162struct pcm_config pcm_config_hifi = {
163 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
164 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
165 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
166 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
167 .format = PCM_FORMAT_S24_3LE,
168 .start_threshold = 0,
169 .stop_threshold = INT_MAX,
170 .avail_min = 0,
171};
172
Eric Laurentb23d5282013-05-14 15:27:20 -0700173struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700174 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700175 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
176 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700177 .stop_threshold = INT_MAX,
178 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700179};
180
Haynes Mathew George03c40102016-01-29 17:57:48 -0800181struct pcm_config pcm_config_audio_capture_rt = {
182 .channels = DEFAULT_CHANNEL_COUNT,
183 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
184 .period_size = ULL_PERIOD_SIZE,
185 .period_count = 512,
186 .format = PCM_FORMAT_S16_LE,
187 .start_threshold = 0,
188 .stop_threshold = INT_MAX,
189 .silence_threshold = 0,
190 .silence_size = 0,
191 .avail_min = ULL_PERIOD_SIZE, //1 ms
192};
193
Eric Laurent0e46adf2016-12-16 12:49:24 -0800194struct pcm_config pcm_config_mmap_capture = {
195 .channels = DEFAULT_CHANNEL_COUNT,
196 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
197 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800198 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800199 .format = PCM_FORMAT_S16_LE,
200 .start_threshold = 0,
201 .stop_threshold = INT_MAX,
202 .silence_threshold = 0,
203 .silence_size = 0,
204 .avail_min = MMAP_PERIOD_SIZE, //1 ms
205};
206
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700207#define AFE_PROXY_CHANNEL_COUNT 2
208#define AFE_PROXY_SAMPLING_RATE 48000
209
210#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
211#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
212
213struct pcm_config pcm_config_afe_proxy_playback = {
214 .channels = AFE_PROXY_CHANNEL_COUNT,
215 .rate = AFE_PROXY_SAMPLING_RATE,
216 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
217 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
218 .format = PCM_FORMAT_S16_LE,
219 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
220 .stop_threshold = INT_MAX,
221 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
222};
223
224#define AFE_PROXY_RECORD_PERIOD_SIZE 768
225#define AFE_PROXY_RECORD_PERIOD_COUNT 4
226
227struct pcm_config pcm_config_afe_proxy_record = {
228 .channels = AFE_PROXY_CHANNEL_COUNT,
229 .rate = AFE_PROXY_SAMPLING_RATE,
230 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
231 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
232 .format = PCM_FORMAT_S16_LE,
233 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
234 .stop_threshold = INT_MAX,
235 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
236};
237
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700238const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700239 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
240 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800241 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700242 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700243 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700244 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800245 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700246
Eric Laurentb23d5282013-05-14 15:27:20 -0700247 [USECASE_AUDIO_RECORD] = "audio-record",
248 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800249 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George569b7482017-05-08 14:44:27 -0700250 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700251
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800252 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
253 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700254
Eric Laurentb23d5282013-05-14 15:27:20 -0700255 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700256 [USECASE_VOICE2_CALL] = "voice2-call",
257 [USECASE_VOLTE_CALL] = "volte-call",
258 [USECASE_QCHAT_CALL] = "qchat-call",
259 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800260 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
261 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700262
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700263 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
264 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
265
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700266 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
267 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
vivek mehta781065c2017-04-04 12:55:01 -0700268
269 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
270 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
271 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
272
Eric Laurentb23d5282013-05-14 15:27:20 -0700273};
274
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800275
276#define STRING_TO_ENUM(string) { #string, string }
277
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800278struct string_to_enum {
279 const char *name;
280 uint32_t value;
281};
282
Haynes Mathew George569b7482017-05-08 14:44:27 -0700283static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800284 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
285 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
286 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George569b7482017-05-08 14:44:27 -0700287 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
288 //TBD - string values for channel_in > 2?
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800289};
290
Haynes Mathew George5191a852013-09-11 14:19:36 -0700291static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700292static struct audio_device *adev = NULL;
Andy Hung9e737de2017-05-22 10:51:22 -0700293static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700294static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700295//cache last MBDRC cal step level
296static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700297
Andy Hung9e737de2017-05-22 10:51:22 -0700298// TODO: Consider moving this to a pthread_once() if we have more
299// static initialization required.
300static bool is_userdebug_or_eng_build() {
301 char value[PROPERTY_VALUE_MAX];
302 (void)property_get("ro.build.type", value, "unknown"); // ignore actual length
303 return strcmp(value, "userdebug") == 0 || strcmp(value, "eng") == 0;
304}
305
Haynes Mathew George03c40102016-01-29 17:57:48 -0800306static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
307 int flags __unused)
308{
309 int dir = 0;
310 switch (uc_id) {
311 case USECASE_AUDIO_RECORD_LOW_LATENCY:
312 dir = 1;
313 case USECASE_AUDIO_PLAYBACK_ULL:
314 break;
315 default:
316 return false;
317 }
318
319 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
320 PCM_PLAYBACK : PCM_CAPTURE);
321 if (adev->adm_is_noirq_avail)
322 return adev->adm_is_noirq_avail(adev->adm_data,
323 adev->snd_card, dev_id, dir);
324 return false;
325}
326
327static void register_out_stream(struct stream_out *out)
328{
329 struct audio_device *adev = out->dev;
330 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
331 return;
332
333 if (!adev->adm_register_output_stream)
334 return;
335
336 adev->adm_register_output_stream(adev->adm_data,
337 out->handle,
338 out->flags);
339
340 if (!adev->adm_set_config)
341 return;
342
343 if (out->realtime) {
344 adev->adm_set_config(adev->adm_data,
345 out->handle,
346 out->pcm, &out->config);
347 }
348}
349
350static void register_in_stream(struct stream_in *in)
351{
352 struct audio_device *adev = in->dev;
353 if (!adev->adm_register_input_stream)
354 return;
355
356 adev->adm_register_input_stream(adev->adm_data,
357 in->capture_handle,
358 in->flags);
359
360 if (!adev->adm_set_config)
361 return;
362
363 if (in->realtime) {
364 adev->adm_set_config(adev->adm_data,
365 in->capture_handle,
366 in->pcm,
367 &in->config);
368 }
369}
370
371static void request_out_focus(struct stream_out *out, long ns)
372{
373 struct audio_device *adev = out->dev;
374
Haynes Mathew George03c40102016-01-29 17:57:48 -0800375 if (adev->adm_request_focus_v2) {
376 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
377 } else if (adev->adm_request_focus) {
378 adev->adm_request_focus(adev->adm_data, out->handle);
379 }
380}
381
382static void request_in_focus(struct stream_in *in, long ns)
383{
384 struct audio_device *adev = in->dev;
385
Haynes Mathew George03c40102016-01-29 17:57:48 -0800386 if (adev->adm_request_focus_v2) {
387 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
388 } else if (adev->adm_request_focus) {
389 adev->adm_request_focus(adev->adm_data, in->capture_handle);
390 }
391}
392
393static void release_out_focus(struct stream_out *out, long ns __unused)
394{
395 struct audio_device *adev = out->dev;
396
397 if (adev->adm_abandon_focus)
398 adev->adm_abandon_focus(adev->adm_data, out->handle);
399}
400
401static void release_in_focus(struct stream_in *in, long ns __unused)
402{
403 struct audio_device *adev = in->dev;
404 if (adev->adm_abandon_focus)
405 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
406}
407
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700408static int parse_snd_card_status(struct str_parms * parms, int * card,
409 card_status_t * status)
410{
411 char value[32]={0};
412 char state[32]={0};
413
414 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
415
416 if (ret < 0)
417 return -1;
418
419 // sscanf should be okay as value is of max length 32.
420 // same as sizeof state.
421 if (sscanf(value, "%d,%s", card, state) < 2)
422 return -1;
423
424 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
425 CARD_STATUS_OFFLINE;
426 return 0;
427}
428
vivek mehta1a9b7c02015-06-25 11:49:38 -0700429__attribute__ ((visibility ("default")))
430bool audio_hw_send_gain_dep_calibration(int level) {
431 bool ret_val = false;
432 ALOGV("%s: enter ... ", __func__);
433
434 pthread_mutex_lock(&adev_init_lock);
435
436 if (adev != NULL && adev->platform != NULL) {
437 pthread_mutex_lock(&adev->lock);
438 ret_val = platform_send_gain_dep_cal(adev->platform, level);
439 pthread_mutex_unlock(&adev->lock);
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700440
441 // if cal set fails, cache level info
442 // if cal set succeds, reset known last cal set
443 if (!ret_val)
444 last_known_cal_step = level;
445 else if (last_known_cal_step != -1)
446 last_known_cal_step = -1;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700447 } else {
448 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
449 }
450
451 pthread_mutex_unlock(&adev_init_lock);
452
453 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
454 return ret_val;
455}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700456
vivek mehtaa8d7c922016-05-25 14:40:44 -0700457__attribute__ ((visibility ("default")))
458int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
459 int table_size) {
460 int ret_val = 0;
461 ALOGV("%s: enter ... ", __func__);
462
463 pthread_mutex_lock(&adev_init_lock);
464 if (adev == NULL) {
465 ALOGW("%s: adev is NULL .... ", __func__);
466 goto done;
467 }
468
469 pthread_mutex_lock(&adev->lock);
470 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
471 pthread_mutex_unlock(&adev->lock);
472done:
473 pthread_mutex_unlock(&adev_init_lock);
474 ALOGV("%s: exit ... ", __func__);
475 return ret_val;
476}
477
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700478static bool is_supported_format(audio_format_t format)
479{
Eric Laurent8251ac82014-07-23 11:00:25 -0700480 switch (format) {
481 case AUDIO_FORMAT_MP3:
482 case AUDIO_FORMAT_AAC_LC:
483 case AUDIO_FORMAT_AAC_HE_V1:
484 case AUDIO_FORMAT_AAC_HE_V2:
485 return true;
486 default:
487 break;
488 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700489 return false;
490}
491
Haynes Mathew George03c40102016-01-29 17:57:48 -0800492static inline bool is_mmap_usecase(audio_usecase_t uc_id)
493{
494 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
495 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
496}
497
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700498static int get_snd_codec_id(audio_format_t format)
499{
500 int id = 0;
501
Eric Laurent8251ac82014-07-23 11:00:25 -0700502 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700503 case AUDIO_FORMAT_MP3:
504 id = SND_AUDIOCODEC_MP3;
505 break;
506 case AUDIO_FORMAT_AAC:
507 id = SND_AUDIOCODEC_AAC;
508 break;
509 default:
510 ALOGE("%s: Unsupported audio format", __func__);
511 }
512
513 return id;
514}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800515
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800516static int audio_ssr_status(struct audio_device *adev)
517{
518 int ret = 0;
519 struct mixer_ctl *ctl;
520 const char *mixer_ctl_name = "Audio SSR Status";
521
522 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
523 ret = mixer_ctl_get_value(ctl, 0);
524 ALOGD("%s: value: %d", __func__, ret);
525 return ret;
526}
527
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800528int enable_audio_route(struct audio_device *adev,
529 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800530{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700531 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800532 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800533
534 if (usecase == NULL)
535 return -EINVAL;
536
537 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
538
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800539 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700540 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800541 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700542 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800543
Yamit Mehtae3b99562016-09-16 22:44:00 +0530544 audio_extn_utils_send_app_type_cfg(adev, usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800545 audio_extn_utils_send_audio_calibration(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800546 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500547 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700548 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700549 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800550
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800551 ALOGV("%s: exit", __func__);
552 return 0;
553}
554
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800555int disable_audio_route(struct audio_device *adev,
556 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800557{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700558 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800559 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800560
561 if (usecase == NULL)
562 return -EINVAL;
563
564 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700565 if (usecase->type == PCM_CAPTURE)
566 snd_device = usecase->in_snd_device;
567 else
568 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800569 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500570 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700571 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700572 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800573
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800574 ALOGV("%s: exit", __func__);
575 return 0;
576}
577
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800578int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700579 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800580{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700581 int i, num_devices = 0;
582 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800583 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800584 if (snd_device < SND_DEVICE_MIN ||
585 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800586 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800587 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800588 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700589
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700590 platform_send_audio_calibration(adev->platform, snd_device);
591
vivek mehtade4849c2016-03-03 17:23:38 -0800592 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700593 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700594 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800595 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700596 }
597
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700598 /* due to the possibility of calibration overwrite between listen
599 and audio, notify sound trigger hal before audio calibration is sent */
600 audio_extn_sound_trigger_update_device_status(snd_device,
601 ST_EVENT_SND_DEVICE_BUSY);
602
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700603 if (audio_extn_spkr_prot_is_enabled())
604 audio_extn_spkr_prot_calib_cancel(adev);
605
zhaoyang yin4211fad2015-06-04 21:13:25 +0800606 audio_extn_dsm_feedback_enable(adev, snd_device, true);
607
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700608 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
609 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
610 audio_extn_spkr_prot_is_enabled()) {
611 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800612 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700613 }
614 if (audio_extn_spkr_prot_start_processing(snd_device)) {
615 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800616 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700617 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700618 } else if (platform_can_split_snd_device(snd_device,
619 &num_devices,
620 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700621 for (i = 0; i < num_devices; i++) {
622 enable_snd_device(adev, new_snd_devices[i]);
623 }
vivek mehtab6506412015-08-07 16:55:17 -0700624 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700625 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800626 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
627 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
628 ALOGE(" %s: Invalid sound device returned", __func__);
629 goto on_error;
630 }
Ed Tam70b5c142016-03-21 19:14:29 -0700631
Eric Laurent2e140aa2016-06-30 17:14:46 -0700632 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800633 audio_route_apply_and_update_path(adev->audio_route, device_name);
634 }
635on_success:
636 adev->snd_dev_ref_cnt[snd_device]++;
637 ret_val = 0;
638on_error:
639 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800640}
641
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800642int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700643 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800644{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700645 int i, num_devices = 0;
646 snd_device_t new_snd_devices[2];
647
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800648 if (snd_device < SND_DEVICE_MIN ||
649 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800650 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800651 return -EINVAL;
652 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700653 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
654 ALOGE("%s: device ref cnt is already 0", __func__);
655 return -EINVAL;
656 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800657 audio_extn_tfa_98xx_disable_speaker(snd_device);
658
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700659 adev->snd_dev_ref_cnt[snd_device]--;
660 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800661 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700662 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
663 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
664 audio_extn_spkr_prot_is_enabled()) {
665 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700666 } else if (platform_can_split_snd_device(snd_device,
667 &num_devices,
668 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700669 for (i = 0; i < num_devices; i++) {
670 disable_snd_device(adev, new_snd_devices[i]);
671 }
vivek mehtab6506412015-08-07 16:55:17 -0700672 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700673 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800674 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
675 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
676 ALOGE(" %s: Invalid sound device returned", __func__);
677 return -EINVAL;
678 }
679
Eric Laurent2e140aa2016-06-30 17:14:46 -0700680 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800681 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700682 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700683 audio_extn_sound_trigger_update_device_status(snd_device,
684 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700685 }
vivek mehtab6506412015-08-07 16:55:17 -0700686
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800687 return 0;
688}
689
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700690/*
691 legend:
692 uc - existing usecase
693 new_uc - new usecase
694 d1, d11, d2 - SND_DEVICE enums
695 a1, a2 - corresponding ANDROID device enums
696 B, B1, B2 - backend strings
697
698case 1
699 uc->dev d1 (a1) B1
700 new_uc->dev d1 (a1), d2 (a2) B1, B2
701
702 resolution: disable and enable uc->dev on d1
703
704case 2
705 uc->dev d1 (a1) B1
706 new_uc->dev d11 (a1) B1
707
708 resolution: need to switch uc since d1 and d11 are related
709 (e.g. speaker and voice-speaker)
710 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
711
712case 3
713 uc->dev d1 (a1) B1
714 new_uc->dev d2 (a2) B2
715
716 resolution: no need to switch uc
717
718case 4
719 uc->dev d1 (a1) B
720 new_uc->dev d2 (a2) B
721
722 resolution: disable enable uc-dev on d2 since backends match
723 we cannot enable two streams on two different devices if they
724 share the same backend. e.g. if offload is on speaker device using
725 QUAD_MI2S backend and a low-latency stream is started on voice-handset
726 using the same backend, offload must also be switched to voice-handset.
727
728case 5
729 uc->dev d1 (a1) B
730 new_uc->dev d1 (a1), d2 (a2) B
731
732 resolution: disable enable uc-dev on d2 since backends match
733 we cannot enable two streams on two different devices if they
734 share the same backend.
735
736case 6
737 uc->dev d1 a1 B1
738 new_uc->dev d2 a1 B2
739
740 resolution: no need to switch
741
742case 7
743
744 uc->dev d1 (a1), d2 (a2) B1, B2
745 new_uc->dev d1 B1
746
747 resolution: no need to switch
748
749*/
750static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
751 struct audio_usecase *new_uc,
752 snd_device_t new_snd_device)
753{
754 audio_devices_t a1 = uc->stream.out->devices;
755 audio_devices_t a2 = new_uc->stream.out->devices;
756
757 snd_device_t d1 = uc->out_snd_device;
758 snd_device_t d2 = new_snd_device;
759
760 // Treat as a special case when a1 and a2 are not disjoint
761 if ((a1 != a2) && (a1 & a2)) {
762 snd_device_t d3[2];
763 int num_devices = 0;
764 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
765 &num_devices,
766 d3);
767 if (ret < 0) {
768 if (ret != -ENOSYS) {
769 ALOGW("%s failed to split snd_device %d",
770 __func__,
771 popcount(a1) > 1 ? d1 : d2);
772 }
773 goto end;
774 }
775
776 // NB: case 7 is hypothetical and isn't a practical usecase yet.
777 // But if it does happen, we need to give priority to d2 if
778 // the combo devices active on the existing usecase share a backend.
779 // This is because we cannot have a usecase active on a combo device
780 // and a new usecase requests one device in this combo pair.
781 if (platform_check_backends_match(d3[0], d3[1])) {
782 return d2; // case 5
783 } else {
784 return d1; // case 1
785 }
786 } else {
787 if (platform_check_backends_match(d1, d2)) {
788 return d2; // case 2, 4
789 } else {
790 return d1; // case 6, 3
791 }
792 }
793
794end:
795 return d2; // return whatever was calculated before.
796}
797
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700798static void check_and_route_playback_usecases(struct audio_device *adev,
799 struct audio_usecase *uc_info,
800 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700801{
802 struct listnode *node;
803 struct audio_usecase *usecase;
804 bool switch_device[AUDIO_USECASE_MAX];
805 int i, num_uc_to_switch = 0;
806
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700807 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
808 uc_info,
809 snd_device);
David Linee3fe402017-03-13 10:00:42 -0700810
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700811 /*
812 * This function is to make sure that all the usecases that are active on
813 * the hardware codec backend are always routed to any one device that is
814 * handled by the hardware codec.
815 * For example, if low-latency and deep-buffer usecases are currently active
816 * on speaker and out_set_parameters(headset) is received on low-latency
817 * output, then we have to make sure deep-buffer is also switched to headset,
818 * because of the limitation that both the devices cannot be enabled
819 * at the same time as they share the same backend.
820 */
821 /* Disable all the usecases on the shared backend other than the
822 specified usecase */
823 for (i = 0; i < AUDIO_USECASE_MAX; i++)
824 switch_device[i] = false;
825
826 list_for_each(node, &adev->usecase_list) {
827 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700828 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
829 continue;
830
831 if (force_routing ||
832 (usecase->out_snd_device != snd_device &&
833 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
834 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700835 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
836 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700837 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700838 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700839 switch_device[usecase->id] = true;
840 num_uc_to_switch++;
841 }
842 }
843
844 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700845 list_for_each(node, &adev->usecase_list) {
846 usecase = node_to_item(node, struct audio_usecase, list);
847 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700848 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900849 }
850 }
851
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700852 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900853 list_for_each(node, &adev->usecase_list) {
854 usecase = node_to_item(node, struct audio_usecase, list);
855 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700856 d_device = derive_playback_snd_device(usecase, uc_info,
857 snd_device);
858 enable_snd_device(adev, d_device);
859 /* Update the out_snd_device before enabling the audio route */
860 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700861 }
862 }
863
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700864 /* Re-route all the usecases on the shared backend other than the
865 specified usecase to new snd devices */
866 list_for_each(node, &adev->usecase_list) {
867 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700868 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700869 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700870 }
871 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700872 }
873}
874
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700875static void check_and_route_capture_usecases(struct audio_device *adev,
876 struct audio_usecase *uc_info,
877 snd_device_t snd_device)
878{
879 struct listnode *node;
880 struct audio_usecase *usecase;
881 bool switch_device[AUDIO_USECASE_MAX];
882 int i, num_uc_to_switch = 0;
883
vivek mehta4ed66e62016-04-15 23:33:34 -0700884 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
885
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700886 /*
887 * This function is to make sure that all the active capture usecases
888 * are always routed to the same input sound device.
889 * For example, if audio-record and voice-call usecases are currently
890 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
891 * is received for voice call then we have to make sure that audio-record
892 * usecase is also switched to earpiece i.e. voice-dmic-ef,
893 * because of the limitation that two devices cannot be enabled
894 * at the same time if they share the same backend.
895 */
896 for (i = 0; i < AUDIO_USECASE_MAX; i++)
897 switch_device[i] = false;
898
899 list_for_each(node, &adev->usecase_list) {
900 usecase = node_to_item(node, struct audio_usecase, list);
901 if (usecase->type != PCM_PLAYBACK &&
902 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700903 usecase->in_snd_device != snd_device &&
904 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700905 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
906 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700907 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700908 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700909 switch_device[usecase->id] = true;
910 num_uc_to_switch++;
911 }
912 }
913
914 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700915 list_for_each(node, &adev->usecase_list) {
916 usecase = node_to_item(node, struct audio_usecase, list);
917 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700918 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700919 }
920 }
921
922 list_for_each(node, &adev->usecase_list) {
923 usecase = node_to_item(node, struct audio_usecase, list);
924 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700925 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700926 }
927 }
928
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700929 /* Re-route all the usecases on the shared backend other than the
930 specified usecase to new snd devices */
931 list_for_each(node, &adev->usecase_list) {
932 usecase = node_to_item(node, struct audio_usecase, list);
933 /* Update the in_snd_device only before enabling the audio route */
934 if (switch_device[usecase->id] ) {
935 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700936 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700937 }
938 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700939 }
940}
941
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800942/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700943static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800944{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700945 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700946 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800947
948 switch (channels) {
949 /*
950 * Do not handle stereo output in Multi-channel cases
951 * Stereo case is handled in normal playback path
952 */
953 case 6:
954 ALOGV("%s: HDMI supports 5.1", __func__);
955 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
956 break;
957 case 8:
958 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
959 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
960 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
961 break;
962 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700963 ALOGE("HDMI does not support multi channel playback");
964 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800965 break;
966 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700967 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800968}
969
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -0700970static ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
971 uint32_t *supported_sample_rates __unused,
972 uint32_t max_rates __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800973{
Haynes Mathew George569b7482017-05-08 14:44:27 -0700974 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
975 supported_sample_rates,
976 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800977#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -0700978 for (ssize_t i=0; i<count; i++) {
979 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
980 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800981 }
982#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -0700983 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800984}
985
Haynes Mathew George569b7482017-05-08 14:44:27 -0700986static int read_usb_sup_channel_masks(bool is_playback,
987 audio_channel_mask_t *supported_channel_masks,
988 uint32_t max_masks __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800989{
Haynes Mathew George569b7482017-05-08 14:44:27 -0700990 int channels = audio_extn_usb_get_max_channels(is_playback);
991 if (is_playback) {
992 supported_channel_masks[0] =
993 channels < 3 ? audio_channel_out_mask_from_count(channels) :
994 audio_channel_mask_for_index_assignment_from_count(channels);
995 } else {
996 supported_channel_masks[0] = audio_channel_in_mask_from_count(channels);
997 }
998 ALOGV("%s: %s supported ch %d", __func__,
999 is_playback ? "P" : "C", channels);
1000 return 1;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001001}
1002
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001003static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001004 audio_format_t *supported_formats,
1005 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001006{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001007 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001008 switch (bitwidth) {
1009 case 24:
1010 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001011 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001012 break;
1013 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001014 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001015 break;
1016 case 16:
1017 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001018 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001019 break;
1020 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001021 ALOGV("%s: %s supported format %d", __func__,
1022 is_playback ? "P" : "C", bitwidth);
1023 return 1;
1024}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001025
Haynes Mathew George569b7482017-05-08 14:44:27 -07001026static int read_usb_sup_params_and_compare(bool is_playback,
1027 audio_format_t *format,
1028 audio_format_t *supported_formats,
1029 uint32_t max_formats,
1030 audio_channel_mask_t *mask,
1031 audio_channel_mask_t *supported_channel_masks,
1032 uint32_t max_masks,
1033 uint32_t *rate,
1034 uint32_t *supported_sample_rates,
1035 uint32_t max_rates) {
1036 int ret = 0;
1037 int num_formats;
1038 int num_masks;
1039 int num_rates;
1040 int i;
1041
1042 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1043 max_formats);
1044 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1045 max_masks);
1046 num_rates = read_usb_sup_sample_rates(is_playback,
1047 supported_sample_rates, max_rates);
1048
1049#define LUT(table, len, what, dflt) \
1050 for (i=0; i<len && (table[i] != what); i++); \
1051 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1052
1053 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1054 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1055 LUT(supported_sample_rates, num_rates, *rate, 0);
1056
1057#undef LUT
1058 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001059}
1060
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001061static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1062{
1063 struct audio_usecase *usecase;
1064 struct listnode *node;
1065
1066 list_for_each(node, &adev->usecase_list) {
1067 usecase = node_to_item(node, struct audio_usecase, list);
1068 if (usecase->type == VOICE_CALL) {
1069 ALOGV("%s: usecase id %d", __func__, usecase->id);
1070 return usecase->id;
1071 }
1072 }
1073 return USECASE_INVALID;
1074}
1075
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001076struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1077 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001078{
1079 struct audio_usecase *usecase;
1080 struct listnode *node;
1081
1082 list_for_each(node, &adev->usecase_list) {
1083 usecase = node_to_item(node, struct audio_usecase, list);
1084 if (usecase->id == uc_id)
1085 return usecase;
1086 }
1087 return NULL;
1088}
1089
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001090int select_devices(struct audio_device *adev,
1091 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001092{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001093 snd_device_t out_snd_device = SND_DEVICE_NONE;
1094 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001095 struct audio_usecase *usecase = NULL;
1096 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001097 struct audio_usecase *hfp_usecase = NULL;
1098 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001099 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001100 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001101
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001102 usecase = get_usecase_from_list(adev, uc_id);
1103 if (usecase == NULL) {
1104 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1105 return -EINVAL;
1106 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001107
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001108 if ((usecase->type == VOICE_CALL) ||
1109 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001110 out_snd_device = platform_get_output_snd_device(adev->platform,
1111 usecase->stream.out->devices);
1112 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001113 usecase->devices = usecase->stream.out->devices;
1114 } else {
1115 /*
1116 * If the voice call is active, use the sound devices of voice call usecase
1117 * so that it would not result any device switch. All the usecases will
1118 * be switched to new device when select_devices() is called for voice call
1119 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001120 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001121 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001122 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001123 vc_usecase = get_usecase_from_list(adev,
1124 get_voice_usecase_id_from_list(adev));
1125 if ((vc_usecase != NULL) &&
1126 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1127 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001128 in_snd_device = vc_usecase->in_snd_device;
1129 out_snd_device = vc_usecase->out_snd_device;
1130 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001131 } else if (audio_extn_hfp_is_active(adev)) {
1132 hfp_ucid = audio_extn_hfp_get_usecase();
1133 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1134 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1135 in_snd_device = hfp_usecase->in_snd_device;
1136 out_snd_device = hfp_usecase->out_snd_device;
1137 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001138 }
1139 if (usecase->type == PCM_PLAYBACK) {
1140 usecase->devices = usecase->stream.out->devices;
1141 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001142 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001143 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001144 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001145 if (usecase->stream.out == adev->primary_output &&
1146 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001147 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1148 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001149 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001150 select_devices(adev, adev->active_input->usecase);
1151 }
1152 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001153 } else if (usecase->type == PCM_CAPTURE) {
1154 usecase->devices = usecase->stream.in->device;
1155 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001156 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001157 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001158 if (adev->active_input &&
1159 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1160 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001161 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001162 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1163 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
1164 } else if (adev->primary_output) {
1165 out_device = adev->primary_output->devices;
1166 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001167 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001168 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001169 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001170 }
1171 }
1172
1173 if (out_snd_device == usecase->out_snd_device &&
1174 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001175 return 0;
1176 }
1177
Eric Laurent2bafff12016-03-17 12:17:23 -07001178 if (out_snd_device != SND_DEVICE_NONE &&
1179 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1180 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1181 __func__,
1182 use_case_table[uc_id],
1183 adev->last_logged_snd_device[uc_id][0],
1184 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1185 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1186 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1187 -1,
1188 out_snd_device,
1189 platform_get_snd_device_name(out_snd_device),
1190 platform_get_snd_device_acdb_id(out_snd_device));
1191 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1192 }
1193 if (in_snd_device != SND_DEVICE_NONE &&
1194 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1195 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1196 __func__,
1197 use_case_table[uc_id],
1198 adev->last_logged_snd_device[uc_id][1],
1199 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1200 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1201 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1202 -1,
1203 in_snd_device,
1204 platform_get_snd_device_name(in_snd_device),
1205 platform_get_snd_device_acdb_id(in_snd_device));
1206 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1207 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001208
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001209 /*
1210 * Limitation: While in call, to do a device switch we need to disable
1211 * and enable both RX and TX devices though one of them is same as current
1212 * device.
1213 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001214 if ((usecase->type == VOICE_CALL) &&
1215 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1216 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001217 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001218 /* Disable sidetone only if voice call already exists */
1219 if (voice_is_call_state_active(adev))
1220 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001221 }
1222
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001223 /* Disable current sound devices */
1224 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001225 disable_audio_route(adev, usecase);
1226 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001227 }
1228
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001229 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001230 disable_audio_route(adev, usecase);
1231 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001232 }
1233
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001234 /* Applicable only on the targets that has external modem.
1235 * New device information should be sent to modem before enabling
1236 * the devices to reduce in-call device switch time.
1237 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001238 if ((usecase->type == VOICE_CALL) &&
1239 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1240 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001241 status = platform_switch_voice_call_enable_device_config(adev->platform,
1242 out_snd_device,
1243 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001244 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001245
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001246 /* Enable new sound devices */
1247 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001248 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1249 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001250 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001251 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001252 }
1253
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001254 if (in_snd_device != SND_DEVICE_NONE) {
1255 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001256 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001257 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001258
Eric Laurentb23d5282013-05-14 15:27:20 -07001259 if (usecase->type == VOICE_CALL)
1260 status = platform_switch_voice_call_device_post(adev->platform,
1261 out_snd_device,
1262 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001263
sangwoo170731f2013-06-08 15:36:36 +09001264 usecase->in_snd_device = in_snd_device;
1265 usecase->out_snd_device = out_snd_device;
1266
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001267 audio_extn_tfa_98xx_set_mode();
1268
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001269 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001270
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001271 /* Applicable only on the targets that has external modem.
1272 * Enable device command should be sent to modem only after
1273 * enabling voice call mixer controls
1274 */
vivek mehta765eb642015-08-07 19:46:06 -07001275 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001276 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1277 out_snd_device,
1278 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001279 /* Enable sidetone only if voice call already exists */
1280 if (voice_is_call_state_active(adev))
1281 voice_set_sidetone(adev, out_snd_device, true);
1282 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001283
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001284 return status;
1285}
1286
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001287static int stop_input_stream(struct stream_in *in)
1288{
1289 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001290 struct audio_usecase *uc_info;
1291 struct audio_device *adev = in->dev;
1292
Eric Laurentc8400632013-02-14 19:04:54 -08001293 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001294
Eric Laurent994a6932013-07-17 11:51:42 -07001295 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001296 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001297 uc_info = get_usecase_from_list(adev, in->usecase);
1298 if (uc_info == NULL) {
1299 ALOGE("%s: Could not find the usecase (%d) in the list",
1300 __func__, in->usecase);
1301 return -EINVAL;
1302 }
1303
vivek mehta781065c2017-04-04 12:55:01 -07001304 /* Close in-call recording streams */
1305 voice_check_and_stop_incall_rec_usecase(adev, in);
1306
Eric Laurent150dbfe2013-02-27 14:31:02 -08001307 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001308 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001309
1310 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001311 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001312
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001313 list_remove(&uc_info->list);
1314 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001315
Eric Laurent994a6932013-07-17 11:51:42 -07001316 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001317 return ret;
1318}
1319
1320int start_input_stream(struct stream_in *in)
1321{
1322 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001323 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001324 struct audio_usecase *uc_info;
1325 struct audio_device *adev = in->dev;
1326
Eric Laurent994a6932013-07-17 11:51:42 -07001327 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001328
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001329 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1330 return -EIO;
1331
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001332 if (in->card_status == CARD_STATUS_OFFLINE ||
1333 adev->card_status == CARD_STATUS_OFFLINE) {
1334 ALOGW("in->card_status or adev->card_status offline, try again");
1335 ret = -EAGAIN;
1336 goto error_config;
1337 }
1338
vivek mehta781065c2017-04-04 12:55:01 -07001339 /* Check if source matches incall recording usecase criteria */
1340 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1341 if (ret)
1342 goto error_config;
1343 else
1344 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1345
Eric Laurentb23d5282013-05-14 15:27:20 -07001346 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001347 if (in->pcm_device_id < 0) {
1348 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1349 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001350 ret = -EINVAL;
1351 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001352 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001353
1354 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001355 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1356 uc_info->id = in->usecase;
1357 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001358 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001359 uc_info->devices = in->device;
1360 uc_info->in_snd_device = SND_DEVICE_NONE;
1361 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001362
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001363 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001364
1365 audio_extn_perf_lock_acquire();
1366
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001367 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001368
Eric Laurent0e46adf2016-12-16 12:49:24 -08001369 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001370 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001371 ALOGE("%s: pcm stream not ready", __func__);
1372 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001373 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001374 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001375 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001376 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1377 goto error_open;
1378 }
1379 } else {
1380 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1381 unsigned int pcm_open_retry_count = 0;
1382
1383 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1384 flags |= PCM_MMAP | PCM_NOIRQ;
1385 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1386 } else if (in->realtime) {
1387 flags |= PCM_MMAP | PCM_NOIRQ;
1388 }
1389
1390 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1391 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1392
1393 while (1) {
1394 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1395 flags, &in->config);
1396 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1397 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1398 if (in->pcm != NULL) {
1399 pcm_close(in->pcm);
1400 in->pcm = NULL;
1401 }
1402 if (pcm_open_retry_count-- == 0) {
1403 ret = -EIO;
1404 goto error_open;
1405 }
1406 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1407 continue;
1408 }
1409 break;
1410 }
1411
1412 ALOGV("%s: pcm_prepare", __func__);
1413 ret = pcm_prepare(in->pcm);
1414 if (ret < 0) {
1415 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001416 pcm_close(in->pcm);
1417 in->pcm = NULL;
1418 goto error_open;
1419 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001420 if (in->realtime) {
1421 ret = pcm_start(in->pcm);
1422 if (ret < 0) {
1423 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1424 pcm_close(in->pcm);
1425 in->pcm = NULL;
1426 goto error_open;
1427 }
1428 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001429 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001430 register_in_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001431 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001432 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001433
Eric Laurent0e46adf2016-12-16 12:49:24 -08001434 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001435
1436error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001437 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001438 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001439
1440error_config:
1441 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001442 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001443
1444 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001445}
1446
Eric Laurenta1478072015-09-21 17:21:52 -07001447void lock_input_stream(struct stream_in *in)
1448{
1449 pthread_mutex_lock(&in->pre_lock);
1450 pthread_mutex_lock(&in->lock);
1451 pthread_mutex_unlock(&in->pre_lock);
1452}
1453
1454void lock_output_stream(struct stream_out *out)
1455{
1456 pthread_mutex_lock(&out->pre_lock);
1457 pthread_mutex_lock(&out->lock);
1458 pthread_mutex_unlock(&out->pre_lock);
1459}
1460
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001461/* must be called with out->lock locked */
1462static int send_offload_cmd_l(struct stream_out* out, int command)
1463{
1464 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1465
1466 ALOGVV("%s %d", __func__, command);
1467
1468 cmd->cmd = command;
1469 list_add_tail(&out->offload_cmd_list, &cmd->node);
1470 pthread_cond_signal(&out->offload_cond);
1471 return 0;
1472}
1473
1474/* must be called iwth out->lock locked */
1475static void stop_compressed_output_l(struct stream_out *out)
1476{
1477 out->offload_state = OFFLOAD_STATE_IDLE;
1478 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001479 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001480 if (out->compr != NULL) {
1481 compress_stop(out->compr);
1482 while (out->offload_thread_blocked) {
1483 pthread_cond_wait(&out->cond, &out->lock);
1484 }
1485 }
1486}
1487
1488static void *offload_thread_loop(void *context)
1489{
1490 struct stream_out *out = (struct stream_out *) context;
1491 struct listnode *item;
1492
1493 out->offload_state = OFFLOAD_STATE_IDLE;
1494 out->playback_started = 0;
1495
1496 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1497 set_sched_policy(0, SP_FOREGROUND);
1498 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1499
1500 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001501 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001502 for (;;) {
1503 struct offload_cmd *cmd = NULL;
1504 stream_callback_event_t event;
1505 bool send_callback = false;
1506
1507 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1508 __func__, list_empty(&out->offload_cmd_list),
1509 out->offload_state);
1510 if (list_empty(&out->offload_cmd_list)) {
1511 ALOGV("%s SLEEPING", __func__);
1512 pthread_cond_wait(&out->offload_cond, &out->lock);
1513 ALOGV("%s RUNNING", __func__);
1514 continue;
1515 }
1516
1517 item = list_head(&out->offload_cmd_list);
1518 cmd = node_to_item(item, struct offload_cmd, node);
1519 list_remove(item);
1520
1521 ALOGVV("%s STATE %d CMD %d out->compr %p",
1522 __func__, out->offload_state, cmd->cmd, out->compr);
1523
1524 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1525 free(cmd);
1526 break;
1527 }
1528
1529 if (out->compr == NULL) {
1530 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001531 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001532 pthread_cond_signal(&out->cond);
1533 continue;
1534 }
1535 out->offload_thread_blocked = true;
1536 pthread_mutex_unlock(&out->lock);
1537 send_callback = false;
1538 switch(cmd->cmd) {
1539 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1540 compress_wait(out->compr, -1);
1541 send_callback = true;
1542 event = STREAM_CBK_EVENT_WRITE_READY;
1543 break;
1544 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001545 compress_next_track(out->compr);
1546 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001547 send_callback = true;
1548 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001549 /* Resend the metadata for next iteration */
1550 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001551 break;
1552 case OFFLOAD_CMD_DRAIN:
1553 compress_drain(out->compr);
1554 send_callback = true;
1555 event = STREAM_CBK_EVENT_DRAIN_READY;
1556 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001557 case OFFLOAD_CMD_ERROR:
1558 send_callback = true;
1559 event = STREAM_CBK_EVENT_ERROR;
1560 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001561 default:
1562 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1563 break;
1564 }
Eric Laurenta1478072015-09-21 17:21:52 -07001565 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001566 out->offload_thread_blocked = false;
1567 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001568 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001569 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001570 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001571 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001572 free(cmd);
1573 }
1574
1575 pthread_cond_signal(&out->cond);
1576 while (!list_empty(&out->offload_cmd_list)) {
1577 item = list_head(&out->offload_cmd_list);
1578 list_remove(item);
1579 free(node_to_item(item, struct offload_cmd, node));
1580 }
1581 pthread_mutex_unlock(&out->lock);
1582
1583 return NULL;
1584}
1585
1586static int create_offload_callback_thread(struct stream_out *out)
1587{
1588 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1589 list_init(&out->offload_cmd_list);
1590 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1591 offload_thread_loop, out);
1592 return 0;
1593}
1594
1595static int destroy_offload_callback_thread(struct stream_out *out)
1596{
Eric Laurenta1478072015-09-21 17:21:52 -07001597 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001598 stop_compressed_output_l(out);
1599 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1600
1601 pthread_mutex_unlock(&out->lock);
1602 pthread_join(out->offload_thread, (void **) NULL);
1603 pthread_cond_destroy(&out->offload_cond);
1604
1605 return 0;
1606}
1607
Eric Laurent07eeafd2013-10-06 12:52:49 -07001608static bool allow_hdmi_channel_config(struct audio_device *adev)
1609{
1610 struct listnode *node;
1611 struct audio_usecase *usecase;
1612 bool ret = true;
1613
1614 list_for_each(node, &adev->usecase_list) {
1615 usecase = node_to_item(node, struct audio_usecase, list);
1616 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1617 /*
1618 * If voice call is already existing, do not proceed further to avoid
1619 * disabling/enabling both RX and TX devices, CSD calls, etc.
1620 * Once the voice call done, the HDMI channels can be configured to
1621 * max channels of remaining use cases.
1622 */
1623 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001624 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001625 __func__);
1626 ret = false;
1627 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001628 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1629 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001630 "no change in HDMI channels", __func__);
1631 ret = false;
1632 break;
1633 }
1634 }
1635 }
1636 return ret;
1637}
1638
1639static int check_and_set_hdmi_channels(struct audio_device *adev,
1640 unsigned int channels)
1641{
1642 struct listnode *node;
1643 struct audio_usecase *usecase;
1644
1645 /* Check if change in HDMI channel config is allowed */
1646 if (!allow_hdmi_channel_config(adev))
1647 return 0;
1648
1649 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001650 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001651 return 0;
1652 }
1653
1654 platform_set_hdmi_channels(adev->platform, channels);
1655 adev->cur_hdmi_channels = channels;
1656
1657 /*
1658 * Deroute all the playback streams routed to HDMI so that
1659 * the back end is deactivated. Note that backend will not
1660 * be deactivated if any one stream is connected to it.
1661 */
1662 list_for_each(node, &adev->usecase_list) {
1663 usecase = node_to_item(node, struct audio_usecase, list);
1664 if (usecase->type == PCM_PLAYBACK &&
1665 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001666 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001667 }
1668 }
1669
1670 /*
1671 * Enable all the streams disabled above. Now the HDMI backend
1672 * will be activated with new channel configuration
1673 */
1674 list_for_each(node, &adev->usecase_list) {
1675 usecase = node_to_item(node, struct audio_usecase, list);
1676 if (usecase->type == PCM_PLAYBACK &&
1677 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001678 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001679 }
1680 }
1681
1682 return 0;
1683}
1684
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001685static int stop_output_stream(struct stream_out *out)
1686{
1687 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001688 struct audio_usecase *uc_info;
1689 struct audio_device *adev = out->dev;
1690
Eric Laurent994a6932013-07-17 11:51:42 -07001691 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001692 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001693 uc_info = get_usecase_from_list(adev, out->usecase);
1694 if (uc_info == NULL) {
1695 ALOGE("%s: Could not find the usecase (%d) in the list",
1696 __func__, out->usecase);
1697 return -EINVAL;
1698 }
1699
Haynes Mathew George41f86652014-06-17 14:22:15 -07001700 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1701 if (adev->visualizer_stop_output != NULL)
1702 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1703 if (adev->offload_effects_stop_output != NULL)
1704 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1705 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001706
Eric Laurent150dbfe2013-02-27 14:31:02 -08001707 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001708 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001709
1710 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001711 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001712
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001713 list_remove(&uc_info->list);
1714 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001715
Eric Laurent0499d4f2014-08-25 22:39:29 -05001716 audio_extn_extspk_update(adev->extspk);
1717
Eric Laurent07eeafd2013-10-06 12:52:49 -07001718 /* Must be called after removing the usecase from list */
1719 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1720 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1721
Eric Laurent994a6932013-07-17 11:51:42 -07001722 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001723 return ret;
1724}
1725
1726int start_output_stream(struct stream_out *out)
1727{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001728 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001729 struct audio_usecase *uc_info;
1730 struct audio_device *adev = out->dev;
1731
Eric Laurent994a6932013-07-17 11:51:42 -07001732 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001733 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001734
1735 if (out->card_status == CARD_STATUS_OFFLINE ||
1736 adev->card_status == CARD_STATUS_OFFLINE) {
1737 ALOGW("out->card_status or adev->card_status offline, try again");
1738 ret = -EAGAIN;
1739 goto error_config;
1740 }
1741
Eric Laurentb23d5282013-05-14 15:27:20 -07001742 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001743 if (out->pcm_device_id < 0) {
1744 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1745 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001746 ret = -EINVAL;
1747 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001748 }
1749
1750 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1751 uc_info->id = out->usecase;
1752 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001753 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001754 uc_info->devices = out->devices;
1755 uc_info->in_snd_device = SND_DEVICE_NONE;
1756 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001757
Eric Laurent07eeafd2013-10-06 12:52:49 -07001758 /* This must be called before adding this usecase to the list */
1759 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1760 check_and_set_hdmi_channels(adev, out->config.channels);
1761
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001762 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001763
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001764 audio_extn_perf_lock_acquire();
1765
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001766 select_devices(adev, out->usecase);
1767
Eric Laurent0499d4f2014-08-25 22:39:29 -05001768 audio_extn_extspk_update(adev->extspk);
1769
Andy Hung31aca912014-03-20 17:14:59 -07001770 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001771 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001772 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1773 out->pcm = NULL;
1774 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1775 COMPRESS_IN, &out->compr_config);
1776 if (out->compr && !is_compress_ready(out->compr)) {
1777 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1778 compress_close(out->compr);
1779 out->compr = NULL;
1780 ret = -EIO;
1781 goto error_open;
1782 }
1783 if (out->offload_callback)
1784 compress_nonblock(out->compr, out->non_blocking);
1785
1786 if (adev->visualizer_start_output != NULL)
1787 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1788 if (adev->offload_effects_start_output != NULL)
1789 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
1790 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001791 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001792 ALOGE("%s: pcm stream not ready", __func__);
1793 goto error_open;
1794 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001795 ret = pcm_start(out->pcm);
1796 if (ret < 0) {
1797 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1798 goto error_open;
1799 }
1800 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07001801 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001802 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001803
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001804 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1805 flags |= PCM_MMAP | PCM_NOIRQ;
1806 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001807 } else if (out->realtime) {
1808 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07001809 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001810
1811 while (1) {
1812 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1813 flags, &out->config);
1814 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1815 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1816 if (out->pcm != NULL) {
1817 pcm_close(out->pcm);
1818 out->pcm = NULL;
1819 }
1820 if (pcm_open_retry_count-- == 0) {
1821 ret = -EIO;
1822 goto error_open;
1823 }
1824 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1825 continue;
1826 }
1827 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001828 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001829 ALOGV("%s: pcm_prepare", __func__);
1830 if (pcm_is_ready(out->pcm)) {
1831 ret = pcm_prepare(out->pcm);
1832 if (ret < 0) {
1833 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1834 pcm_close(out->pcm);
1835 out->pcm = NULL;
1836 goto error_open;
1837 }
1838 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001839 if (out->realtime) {
1840 ret = pcm_start(out->pcm);
1841 if (ret < 0) {
1842 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1843 pcm_close(out->pcm);
1844 out->pcm = NULL;
1845 goto error_open;
1846 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001847 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001848 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001849 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001850 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001851 audio_extn_tfa_98xx_enable_speaker();
1852
Eric Laurent994a6932013-07-17 11:51:42 -07001853 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001854 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001855error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001856 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001857 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001858error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001859 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001860}
1861
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001862static int check_input_parameters(uint32_t sample_rate,
1863 audio_format_t format,
1864 int channel_count)
1865{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001866 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
1867 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
1868 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED)) {
vivek mehtadae44712015-07-27 14:13:18 -07001869 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1870 return -EINVAL;
1871 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001872
vivek mehtadae44712015-07-27 14:13:18 -07001873 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > MAX_CHANNEL_COUNT)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001874 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
vivek mehtadae44712015-07-27 14:13:18 -07001875 channel_count, MIN_CHANNEL_COUNT, MAX_CHANNEL_COUNT);
1876 return -EINVAL;
1877 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001878
1879 switch (sample_rate) {
1880 case 8000:
1881 case 11025:
1882 case 12000:
1883 case 16000:
1884 case 22050:
1885 case 24000:
1886 case 32000:
1887 case 44100:
1888 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001889 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001890 break;
1891 default:
vivek mehtadae44712015-07-27 14:13:18 -07001892 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001893 return -EINVAL;
1894 }
1895
1896 return 0;
1897}
1898
1899static size_t get_input_buffer_size(uint32_t sample_rate,
1900 audio_format_t format,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001901 int channel_count,
1902 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001903{
1904 size_t size = 0;
1905
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001906 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1907 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001908
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001909 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001910 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001911 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07001912
1913 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001914
Glenn Kasten4f993392014-05-14 07:30:48 -07001915 /* make sure the size is multiple of 32 bytes
1916 * At 48 kHz mono 16-bit PCM:
1917 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1918 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1919 */
1920 size += 0x1f;
1921 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001922
1923 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001924}
1925
1926static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1927{
1928 struct stream_out *out = (struct stream_out *)stream;
1929
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001930 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001931}
1932
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001933static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001934{
1935 return -ENOSYS;
1936}
1937
1938static size_t out_get_buffer_size(const struct audio_stream *stream)
1939{
1940 struct stream_out *out = (struct stream_out *)stream;
1941
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001942 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1943 return out->compr_config.fragment_size;
1944 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001945 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07001946 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001947}
1948
1949static uint32_t out_get_channels(const struct audio_stream *stream)
1950{
1951 struct stream_out *out = (struct stream_out *)stream;
1952
1953 return out->channel_mask;
1954}
1955
1956static audio_format_t out_get_format(const struct audio_stream *stream)
1957{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001958 struct stream_out *out = (struct stream_out *)stream;
1959
1960 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001961}
1962
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001963static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001964{
1965 return -ENOSYS;
1966}
1967
1968static int out_standby(struct audio_stream *stream)
1969{
1970 struct stream_out *out = (struct stream_out *)stream;
1971 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08001972 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001973
Eric Laurent994a6932013-07-17 11:51:42 -07001974 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001975 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001976
Eric Laurenta1478072015-09-21 17:21:52 -07001977 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001978 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001979 if (adev->adm_deregister_stream)
1980 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001981 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001982 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001983 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1984 if (out->pcm) {
1985 pcm_close(out->pcm);
1986 out->pcm = NULL;
1987 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001988 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001989 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08001990 out->playback_started = false;
1991 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001992 } else {
1993 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001994 out->gapless_mdata.encoder_delay = 0;
1995 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001996 if (out->compr != NULL) {
1997 compress_close(out->compr);
1998 out->compr = NULL;
1999 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002000 }
Phil Burkbc991042017-02-24 08:06:44 -08002001 if (do_stop) {
2002 stop_output_stream(out);
2003 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002004 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002005 }
2006 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002007 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002008 return 0;
2009}
2010
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002011static int out_on_error(struct audio_stream *stream)
2012{
2013 struct stream_out *out = (struct stream_out *)stream;
2014 struct audio_device *adev = out->dev;
2015 bool do_standby = false;
2016
2017 lock_output_stream(out);
2018 if (!out->standby) {
2019 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2020 stop_compressed_output_l(out);
2021 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2022 } else
2023 do_standby = true;
2024 }
2025 pthread_mutex_unlock(&out->lock);
2026
2027 if (do_standby)
2028 return out_standby(&out->stream.common);
2029
2030 return 0;
2031}
2032
Andy Hung7401c7c2016-09-21 12:41:21 -07002033static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002034{
Andy Hung7401c7c2016-09-21 12:41:21 -07002035 struct stream_out *out = (struct stream_out *)stream;
2036
2037 // We try to get the lock for consistency,
2038 // but it isn't necessary for these variables.
2039 // If we're not in standby, we may be blocked on a write.
2040 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2041 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2042 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2043
2044 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002045 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002046 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002047
2048 // dump error info
2049 (void)error_log_dump(
2050 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hungfc044e12017-03-20 09:24:22 -07002051 // dump power info (out->power_log may be null)
Andy Hung62c9b882017-03-22 16:43:42 -07002052 (void)power_log_dump(
2053 out->power_log, fd, " " /* prefix */, POWER_LOG_LINES, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002054 return 0;
2055}
2056
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002057static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2058{
2059 int ret = 0;
2060 char value[32];
2061 struct compr_gapless_mdata tmp_mdata;
2062
2063 if (!out || !parms) {
2064 return -EINVAL;
2065 }
2066
2067 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2068 if (ret >= 0) {
2069 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2070 } else {
2071 return -EINVAL;
2072 }
2073
2074 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2075 if (ret >= 0) {
2076 tmp_mdata.encoder_padding = atoi(value);
2077 } else {
2078 return -EINVAL;
2079 }
2080
2081 out->gapless_mdata = tmp_mdata;
2082 out->send_new_metadata = 1;
2083 ALOGV("%s new encoder delay %u and padding %u", __func__,
2084 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2085
2086 return 0;
2087}
2088
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002089static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2090{
2091 return out == adev->primary_output || out == adev->voice_tx_output;
2092}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002093
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002094static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2095{
2096 struct stream_out *out = (struct stream_out *)stream;
2097 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002098 struct audio_usecase *usecase;
2099 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002100 struct str_parms *parms;
2101 char value[32];
2102 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002103 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002104 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002105
Eric Laurent2e140aa2016-06-30 17:14:46 -07002106 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002107 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002108 parms = str_parms_create_str(kvpairs);
2109 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2110 if (ret >= 0) {
2111 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07002112 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002113 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002114
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002115 /*
2116 * When HDMI cable is unplugged the music playback is paused and
2117 * the policy manager sends routing=0. But the audioflinger
2118 * continues to write data until standby time (3sec).
2119 * As the HDMI core is turned off, the write gets blocked.
2120 * Avoid this by routing audio to speaker until standby.
2121 */
2122 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2123 val == AUDIO_DEVICE_NONE) {
2124 val = AUDIO_DEVICE_OUT_SPEAKER;
2125 }
2126
2127 /*
2128 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002129 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002130 * the select_devices(). But how do we undo this?
2131 *
2132 * For example, music playback is active on headset (deep-buffer usecase)
2133 * and if we go to ringtones and select a ringtone, low-latency usecase
2134 * will be started on headset+speaker. As we can't enable headset+speaker
2135 * and headset devices at the same time, select_devices() switches the music
2136 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2137 * So when the ringtone playback is completed, how do we undo the same?
2138 *
2139 * We are relying on the out_set_parameters() call on deep-buffer output,
2140 * once the ringtone playback is ended.
2141 * NOTE: We should not check if the current devices are same as new devices.
2142 * Because select_devices() must be called to switch back the music
2143 * playback to headset.
2144 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002145 audio_devices_t new_dev = val;
2146 if (new_dev != AUDIO_DEVICE_NONE) {
2147 bool same_dev = out->devices == new_dev;
2148 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002149
Eric Laurenta7657192014-10-09 21:09:33 -07002150 if (output_drives_call(adev, out)) {
2151 if (!voice_is_in_call(adev)) {
2152 if (adev->mode == AUDIO_MODE_IN_CALL) {
2153 adev->current_call_output = out;
2154 ret = voice_start_call(adev);
2155 }
2156 } else {
2157 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002158 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002159 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002160 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002161
2162 if (!out->standby) {
2163 if (!same_dev) {
2164 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002165 // inform adm before actual routing to prevent glitches.
2166 if (adev->adm_on_routing_change) {
2167 adev->adm_on_routing_change(adev->adm_data,
2168 out->handle);
2169 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002170 }
2171 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002172 audio_extn_tfa_98xx_update();
vivek mehta0d3637a2016-07-24 09:32:02 -07002173 }
2174
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002175 }
2176
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002177 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002178 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002179
2180 /*handles device and call state changes*/
2181 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002182 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002183
2184 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2185 parse_compress_metadata(out, parms);
2186 }
2187
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002188 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002189 ALOGV("%s: exit: code(%d)", __func__, status);
2190 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002191}
2192
Haynes Mathew George569b7482017-05-08 14:44:27 -07002193static bool stream_get_parameter_channels(struct str_parms *query,
2194 struct str_parms *reply,
2195 audio_channel_mask_t *supported_channel_masks) {
2196 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002197 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002198 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002199 size_t i, j;
2200
2201 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2202 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002203 value[0] = '\0';
2204 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002205 while (supported_channel_masks[i] != 0) {
2206 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2207 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002208 if (!first) {
2209 strcat(value, "|");
2210 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002211 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002212 first = false;
2213 break;
2214 }
2215 }
2216 i++;
2217 }
2218 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002219 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002220 return ret >= 0;
2221}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002222
Haynes Mathew George569b7482017-05-08 14:44:27 -07002223static bool stream_get_parameter_formats(struct str_parms *query,
2224 struct str_parms *reply,
2225 audio_format_t *supported_formats) {
2226 int ret = -1;
2227 char value[256];
2228 int i;
2229
2230 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2231 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002232 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002233 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002234 case AUDIO_FORMAT_PCM_16_BIT:
2235 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2236 break;
2237 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2238 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2239 break;
2240 case AUDIO_FORMAT_PCM_32_BIT:
2241 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2242 break;
2243 default:
2244 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002245 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002246 break;
2247 }
2248 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002249 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002250 return ret >= 0;
2251}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002252
Haynes Mathew George569b7482017-05-08 14:44:27 -07002253static bool stream_get_parameter_rates(struct str_parms *query,
2254 struct str_parms *reply,
2255 uint32_t *supported_sample_rates) {
2256
2257 int i;
2258 char value[256];
2259 int ret = -1;
2260 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2261 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002262 value[0] = '\0';
2263 i=0;
2264 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002265 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002266 int avail = sizeof(value) - cursor;
2267 ret = snprintf(value + cursor, avail, "%s%d",
2268 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002269 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002270 if (ret < 0 || ret >= avail) {
2271 // if cursor is at the last element of the array
2272 // overwrite with \0 is duplicate work as
2273 // snprintf already put a \0 in place.
2274 // else
2275 // we had space to write the '|' at value[cursor]
2276 // (which will be overwritten) or no space to fill
2277 // the first element (=> cursor == 0)
2278 value[cursor] = '\0';
2279 break;
2280 }
2281 cursor += ret;
2282 ++i;
2283 }
2284 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2285 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002286 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002287 return ret >= 0;
2288}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002289
Haynes Mathew George569b7482017-05-08 14:44:27 -07002290static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2291{
2292 struct stream_out *out = (struct stream_out *)stream;
2293 struct str_parms *query = str_parms_create_str(keys);
2294 char *str;
2295 struct str_parms *reply = str_parms_create();
2296 bool replied = false;
2297 ALOGV("%s: enter: keys - %s", __func__, keys);
2298
2299 replied |= stream_get_parameter_channels(query, reply,
2300 &out->supported_channel_masks[0]);
2301 replied |= stream_get_parameter_formats(query, reply,
2302 &out->supported_formats[0]);
2303 replied |= stream_get_parameter_rates(query, reply,
2304 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002305 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002306 str = str_parms_to_str(reply);
2307 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002308 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002309 }
2310 str_parms_destroy(query);
2311 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002312 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002313 return str;
2314}
2315
2316static uint32_t out_get_latency(const struct audio_stream_out *stream)
2317{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002318 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002319 struct stream_out *out = (struct stream_out *)stream;
2320
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002321 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2322 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002323 else if ((out->realtime) ||
2324 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002325 // since the buffer won't be filled up faster than realtime,
2326 // return a smaller number
2327 period_ms = (out->af_period_multiplier * out->config.period_size *
2328 1000) / (out->config.rate);
2329 hw_delay = platform_render_latency(out->usecase)/1000;
2330 return period_ms + hw_delay;
2331 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002332
2333 return (out->config.period_count * out->config.period_size * 1000) /
2334 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002335}
2336
2337static int out_set_volume(struct audio_stream_out *stream, float left,
2338 float right)
2339{
Eric Laurenta9024de2013-04-04 09:19:12 -07002340 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002341 int volume[2];
2342
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002343 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002344 /* only take left channel into account: the API is for stereo anyway */
2345 out->muted = (left == 0.0f);
2346 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002347 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2348 const char *mixer_ctl_name = "Compress Playback Volume";
2349 struct audio_device *adev = out->dev;
2350 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002351 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2352 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002353 /* try with the control based on device id */
2354 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2355 PCM_PLAYBACK);
2356 char ctl_name[128] = {0};
2357 snprintf(ctl_name, sizeof(ctl_name),
2358 "Compress Playback %d Volume", pcm_device_id);
2359 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2360 if (!ctl) {
2361 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2362 return -EINVAL;
2363 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002364 }
2365 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2366 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2367 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2368 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002369 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002370
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002371 return -ENOSYS;
2372}
2373
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002374// note: this call is safe only if the stream_cb is
2375// removed first in close_output_stream (as is done now).
2376static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2377{
2378 if (!stream || !parms)
2379 return;
2380
2381 struct stream_out *out = (struct stream_out *)stream;
2382 struct audio_device *adev = out->dev;
2383
2384 card_status_t status;
2385 int card;
2386 if (parse_snd_card_status(parms, &card, &status) < 0)
2387 return;
2388
2389 pthread_mutex_lock(&adev->lock);
2390 bool valid_cb = (card == adev->snd_card);
2391 pthread_mutex_unlock(&adev->lock);
2392
2393 if (!valid_cb)
2394 return;
2395
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002396 lock_output_stream(out);
2397 if (out->card_status != status)
2398 out->card_status = status;
2399 pthread_mutex_unlock(&out->lock);
2400
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002401 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2402 use_case_table[out->usecase],
2403 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2404
2405 if (status == CARD_STATUS_OFFLINE)
2406 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002407
2408 return;
2409}
2410
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002411#ifdef NO_AUDIO_OUT
2412static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002413 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002414{
2415 struct stream_out *out = (struct stream_out *)stream;
2416
2417 /* No Output device supported other than BT for playback.
2418 * Sleep for the amount of buffer duration
2419 */
Eric Laurenta1478072015-09-21 17:21:52 -07002420 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002421 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2422 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002423 out_get_sample_rate(&out->stream.common));
2424 pthread_mutex_unlock(&out->lock);
2425 return bytes;
2426}
2427#endif
2428
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002429static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2430 size_t bytes)
2431{
2432 struct stream_out *out = (struct stream_out *)stream;
2433 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002434 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002435 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002436
Eric Laurenta1478072015-09-21 17:21:52 -07002437 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002438 // this is always nonzero
2439 const int frame_size = audio_stream_out_frame_size(stream);
2440
Eric Laurent0e46adf2016-12-16 12:49:24 -08002441 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2442 error_code = ERROR_CODE_WRITE;
2443 goto exit;
2444 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002445 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002446 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002447 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002448 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002449 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002450 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002451 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002452 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002453 goto exit;
2454 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002455
2456 if (last_known_cal_step != -1) {
2457 ALOGD("%s: retry previous failed cal level set", __func__);
2458 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2459 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002460 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002461
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002462 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002463 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002464 if (out->send_new_metadata) {
2465 ALOGVV("send new gapless metadata");
2466 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2467 out->send_new_metadata = 0;
2468 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002469 unsigned int avail;
2470 struct timespec tstamp;
2471 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2472 /* Do not limit write size if the available frames count is unknown */
2473 if (ret != 0) {
2474 avail = bytes;
2475 }
2476 if (avail == 0) {
2477 ret = 0;
2478 } else {
2479 if (avail > bytes) {
2480 avail = bytes;
2481 }
2482 ret = compress_write(out->compr, buffer, avail);
2483 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2484 __func__, avail, ret);
2485 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002486
Eric Laurent6e895242013-09-05 16:10:57 -07002487 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002488 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2489 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002490 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002491 compress_start(out->compr);
2492 out->playback_started = 1;
2493 out->offload_state = OFFLOAD_STATE_PLAYING;
2494 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002495 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002496 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002497 } else {
2498 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002499 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002500 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002501 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002502 return ret;
2503 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002504 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002505 if (out->pcm) {
2506 if (out->muted)
2507 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002508
Eric Laurent0e46adf2016-12-16 12:49:24 -08002509 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002510
Haynes Mathew George03c40102016-01-29 17:57:48 -08002511 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2512 out->config.rate;
2513 request_out_focus(out, ns);
2514
2515 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2516 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002517 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002518 else
2519 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002520
Haynes Mathew George03c40102016-01-29 17:57:48 -08002521 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002522 } else {
2523 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002524 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002525 }
2526
2527exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002528 // For PCM we always consume the buffer and return #bytes regardless of ret.
2529 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2530 out->written += bytes / (out->config.channels * sizeof(short));
2531 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002532 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07002533
2534 // only get time if needed for logging, as it is a system call on 32 bit devices.
2535 // TODO: Consider always enabling for 64 bit vDSO using compile time check on __LP64__.
2536 const int64_t now_ns = out->power_log != 0 || (ret != 0 && out->error_log != 0)
2537 ? audio_utils_get_real_time_ns() : 0;
Andy Hungfc044e12017-03-20 09:24:22 -07002538
Andy Hung7401c7c2016-09-21 12:41:21 -07002539 if (ret != 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002540 error_log_log(out->error_log, error_code, now_ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002541 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2542 ALOGE_IF(out->pcm != NULL,
2543 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hungfc044e12017-03-20 09:24:22 -07002544 sleeptime_us = bytes * 1000000LL / frame_size /
Andy Hung7401c7c2016-09-21 12:41:21 -07002545 out_get_sample_rate(&out->stream.common);
2546 // usleep not guaranteed for values over 1 second but we don't limit here.
2547 }
2548 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002549
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002550 pthread_mutex_unlock(&out->lock);
2551
2552 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002553 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002554 if (sleeptime_us != 0)
2555 usleep(sleeptime_us);
Andy Hungfc044e12017-03-20 09:24:22 -07002556 } else {
2557 // only log if the data is properly written (out->power_log may be null)
2558 power_log_log(out->power_log, buffer, bytes / frame_size, now_ns);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002559 }
2560 return bytes;
2561}
2562
2563static int out_get_render_position(const struct audio_stream_out *stream,
2564 uint32_t *dsp_frames)
2565{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002566 struct stream_out *out = (struct stream_out *)stream;
2567 *dsp_frames = 0;
2568 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002569 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002570 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002571 unsigned long frames = 0;
2572 // TODO: check return value
2573 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2574 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002575 ALOGVV("%s rendered frames %d sample_rate %d",
2576 __func__, *dsp_frames, out->sample_rate);
2577 }
2578 pthread_mutex_unlock(&out->lock);
2579 return 0;
2580 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002581 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002582}
2583
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002584static int out_add_audio_effect(const struct audio_stream *stream __unused,
2585 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002586{
2587 return 0;
2588}
2589
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002590static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2591 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002592{
2593 return 0;
2594}
2595
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002596static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2597 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002598{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002599 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002600}
2601
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002602static int out_get_presentation_position(const struct audio_stream_out *stream,
2603 uint64_t *frames, struct timespec *timestamp)
2604{
2605 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002606 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07002607 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002608
Eric Laurenta1478072015-09-21 17:21:52 -07002609 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002610
Eric Laurent949a0892013-09-20 09:20:13 -07002611 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2612 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002613 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002614 compress_get_tstamp(out->compr, &dsp_frames,
2615 &out->sample_rate);
2616 ALOGVV("%s rendered frames %ld sample_rate %d",
2617 __func__, dsp_frames, out->sample_rate);
2618 *frames = dsp_frames;
2619 ret = 0;
2620 /* this is the best we can do */
2621 clock_gettime(CLOCK_MONOTONIC, timestamp);
2622 }
2623 } else {
2624 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002625 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002626 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2627 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002628 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002629 // This adjustment accounts for buffering after app processor.
2630 // It is based on estimated DSP latency per use case, rather than exact.
2631 signed_frames -=
2632 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2633
Eric Laurent949a0892013-09-20 09:20:13 -07002634 // It would be unusual for this value to be negative, but check just in case ...
2635 if (signed_frames >= 0) {
2636 *frames = signed_frames;
2637 ret = 0;
2638 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002639 }
2640 }
2641 }
2642
2643 pthread_mutex_unlock(&out->lock);
2644
2645 return ret;
2646}
2647
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002648static int out_set_callback(struct audio_stream_out *stream,
2649 stream_callback_t callback, void *cookie)
2650{
2651 struct stream_out *out = (struct stream_out *)stream;
2652
2653 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002654 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002655 out->offload_callback = callback;
2656 out->offload_cookie = cookie;
2657 pthread_mutex_unlock(&out->lock);
2658 return 0;
2659}
2660
2661static int out_pause(struct audio_stream_out* stream)
2662{
2663 struct stream_out *out = (struct stream_out *)stream;
2664 int status = -ENOSYS;
2665 ALOGV("%s", __func__);
2666 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002667 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002668 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2669 status = compress_pause(out->compr);
2670 out->offload_state = OFFLOAD_STATE_PAUSED;
2671 }
2672 pthread_mutex_unlock(&out->lock);
2673 }
2674 return status;
2675}
2676
2677static int out_resume(struct audio_stream_out* stream)
2678{
2679 struct stream_out *out = (struct stream_out *)stream;
2680 int status = -ENOSYS;
2681 ALOGV("%s", __func__);
2682 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2683 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002684 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002685 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2686 status = compress_resume(out->compr);
2687 out->offload_state = OFFLOAD_STATE_PLAYING;
2688 }
2689 pthread_mutex_unlock(&out->lock);
2690 }
2691 return status;
2692}
2693
2694static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2695{
2696 struct stream_out *out = (struct stream_out *)stream;
2697 int status = -ENOSYS;
2698 ALOGV("%s", __func__);
2699 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002700 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002701 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2702 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2703 else
2704 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2705 pthread_mutex_unlock(&out->lock);
2706 }
2707 return status;
2708}
2709
2710static int out_flush(struct audio_stream_out* stream)
2711{
2712 struct stream_out *out = (struct stream_out *)stream;
2713 ALOGV("%s", __func__);
2714 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002715 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002716 stop_compressed_output_l(out);
2717 pthread_mutex_unlock(&out->lock);
2718 return 0;
2719 }
2720 return -ENOSYS;
2721}
2722
Eric Laurent0e46adf2016-12-16 12:49:24 -08002723static int out_stop(const struct audio_stream_out* stream)
2724{
2725 struct stream_out *out = (struct stream_out *)stream;
2726 struct audio_device *adev = out->dev;
2727 int ret = -ENOSYS;
2728
2729 ALOGV("%s", __func__);
2730 pthread_mutex_lock(&adev->lock);
2731 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2732 out->playback_started && out->pcm != NULL) {
2733 pcm_stop(out->pcm);
2734 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08002735 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002736 }
2737 pthread_mutex_unlock(&adev->lock);
2738 return ret;
2739}
2740
2741static int out_start(const struct audio_stream_out* stream)
2742{
2743 struct stream_out *out = (struct stream_out *)stream;
2744 struct audio_device *adev = out->dev;
2745 int ret = -ENOSYS;
2746
2747 ALOGV("%s", __func__);
2748 pthread_mutex_lock(&adev->lock);
2749 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2750 !out->playback_started && out->pcm != NULL) {
2751 ret = start_output_stream(out);
2752 if (ret == 0) {
2753 out->playback_started = true;
2754 }
2755 }
2756 pthread_mutex_unlock(&adev->lock);
2757 return ret;
2758}
2759
Phil Burkbc991042017-02-24 08:06:44 -08002760/*
2761 * Modify config->period_count based on min_size_frames
2762 */
2763static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
2764{
2765 int periodCountRequested = (min_size_frames + config->period_size - 1)
2766 / config->period_size;
2767 int periodCount = MMAP_PERIOD_COUNT_MIN;
2768
2769 ALOGV("%s original config.period_size = %d config.period_count = %d",
2770 __func__, config->period_size, config->period_count);
2771
2772 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
2773 periodCount *= 2;
2774 }
2775 config->period_count = periodCount;
2776
2777 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
2778}
2779
Eric Laurent0e46adf2016-12-16 12:49:24 -08002780static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2781 int32_t min_size_frames,
2782 struct audio_mmap_buffer_info *info)
2783{
2784 struct stream_out *out = (struct stream_out *)stream;
2785 struct audio_device *adev = out->dev;
2786 int ret = 0;
2787 unsigned int offset1;
2788 unsigned int frames1;
2789 const char *step = "";
2790
2791 ALOGV("%s", __func__);
2792 pthread_mutex_lock(&adev->lock);
2793
2794 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002795 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002796 ret = -EINVAL;
2797 goto exit;
2798 }
2799 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08002800 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002801 ret = -ENOSYS;
2802 goto exit;
2803 }
2804 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
2805 if (out->pcm_device_id < 0) {
2806 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2807 __func__, out->pcm_device_id, out->usecase);
2808 ret = -EINVAL;
2809 goto exit;
2810 }
Phil Burkbc991042017-02-24 08:06:44 -08002811
2812 adjust_mmap_period_count(&out->config, min_size_frames);
2813
Eric Laurent0e46adf2016-12-16 12:49:24 -08002814 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2815 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
2816 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2817 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
2818 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2819 step = "open";
2820 ret = -ENODEV;
2821 goto exit;
2822 }
2823 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
2824 if (ret < 0) {
2825 step = "begin";
2826 goto exit;
2827 }
2828 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
2829 info->burst_size_frames = out->config.period_size;
2830 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
2831
2832 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
2833 info->buffer_size_frames));
2834
2835 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
2836 if (ret < 0) {
2837 step = "commit";
2838 goto exit;
2839 }
Phil Burkbc991042017-02-24 08:06:44 -08002840
2841 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002842 ret = 0;
2843
2844 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
2845 __func__, info->shared_memory_address, info->buffer_size_frames);
2846
2847exit:
2848 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002849 if (out->pcm == NULL) {
2850 ALOGE("%s: %s - %d", __func__, step, ret);
2851 } else {
2852 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08002853 pcm_close(out->pcm);
2854 out->pcm = NULL;
2855 }
2856 }
2857 pthread_mutex_unlock(&adev->lock);
2858 return ret;
2859}
2860
2861static int out_get_mmap_position(const struct audio_stream_out *stream,
2862 struct audio_mmap_position *position)
2863{
2864 struct stream_out *out = (struct stream_out *)stream;
2865 ALOGVV("%s", __func__);
2866 if (position == NULL) {
2867 return -EINVAL;
2868 }
2869 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
2870 return -ENOSYS;
2871 }
2872 if (out->pcm == NULL) {
2873 return -ENOSYS;
2874 }
2875
2876 struct timespec ts = { 0, 0 };
2877 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
2878 if (ret < 0) {
2879 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2880 return ret;
2881 }
Andy Hungfc044e12017-03-20 09:24:22 -07002882 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002883 return 0;
2884}
2885
2886
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002887/** audio_stream_in implementation **/
2888static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2889{
2890 struct stream_in *in = (struct stream_in *)stream;
2891
2892 return in->config.rate;
2893}
2894
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002895static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002896{
2897 return -ENOSYS;
2898}
2899
2900static size_t in_get_buffer_size(const struct audio_stream *stream)
2901{
2902 struct stream_in *in = (struct stream_in *)stream;
2903
Haynes Mathew George03c40102016-01-29 17:57:48 -08002904 return in->config.period_size * in->af_period_multiplier *
2905 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002906}
2907
2908static uint32_t in_get_channels(const struct audio_stream *stream)
2909{
2910 struct stream_in *in = (struct stream_in *)stream;
2911
2912 return in->channel_mask;
2913}
2914
vivek mehta4ed66e62016-04-15 23:33:34 -07002915static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002916{
vivek mehta4ed66e62016-04-15 23:33:34 -07002917 struct stream_in *in = (struct stream_in *)stream;
2918 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002919}
2920
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002921static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002922{
2923 return -ENOSYS;
2924}
2925
2926static int in_standby(struct audio_stream *stream)
2927{
2928 struct stream_in *in = (struct stream_in *)stream;
2929 struct audio_device *adev = in->dev;
2930 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08002931 bool do_stop = true;
2932
Eric Laurent994a6932013-07-17 11:51:42 -07002933 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002934
2935 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002936
2937 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08002938 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002939 audio_extn_sound_trigger_stop_lab(in);
2940 in->standby = true;
2941 }
2942
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002943 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002944 if (adev->adm_deregister_stream)
2945 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2946
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002947 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002948 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002949 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002950 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002951 in->capture_started = false;
2952 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002953 if (in->pcm) {
2954 pcm_close(in->pcm);
2955 in->pcm = NULL;
2956 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002957 adev->enable_voicerx = false;
2958 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08002959 if (do_stop) {
2960 status = stop_input_stream(in);
2961 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002962 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002963 }
2964 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002965 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002966 return status;
2967}
2968
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002969static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002970{
2971 return 0;
2972}
2973
2974static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2975{
2976 struct stream_in *in = (struct stream_in *)stream;
2977 struct audio_device *adev = in->dev;
2978 struct str_parms *parms;
2979 char *str;
2980 char value[32];
2981 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07002982 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002983
Eric Laurent994a6932013-07-17 11:51:42 -07002984 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002985 parms = str_parms_create_str(kvpairs);
2986
2987 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2988
Eric Laurenta1478072015-09-21 17:21:52 -07002989 lock_input_stream(in);
2990
Eric Laurent150dbfe2013-02-27 14:31:02 -08002991 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002992 if (ret >= 0) {
2993 val = atoi(value);
2994 /* no audio source uses val == 0 */
2995 if ((in->source != val) && (val != 0)) {
2996 in->source = val;
2997 }
2998 }
2999
3000 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003001
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003002 if (ret >= 0) {
3003 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003004 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003005 in->device = val;
3006 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08003007 if (!in->standby) {
3008 ALOGV("update input routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003009 // inform adm before actual routing to prevent glitches.
3010 if (adev->adm_on_routing_change) {
3011 adev->adm_on_routing_change(adev->adm_data,
3012 in->capture_handle);
3013 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003014 select_devices(adev, in->usecase);
3015 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003016 }
3017 }
3018
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003019 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003020 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003021
3022 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003023 ALOGV("%s: exit: status(%d)", __func__, status);
3024 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003025}
3026
Haynes Mathew George569b7482017-05-08 14:44:27 -07003027static char* in_get_parameters(const struct audio_stream *stream,
3028 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003029{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003030 struct stream_in *in = (struct stream_in *)stream;
3031 struct str_parms *query = str_parms_create_str(keys);
3032 char *str;
3033 struct str_parms *reply = str_parms_create();
3034 bool replied = false;
3035
3036 ALOGV("%s: enter: keys - %s", __func__, keys);
3037 replied |= stream_get_parameter_channels(query, reply,
3038 &in->supported_channel_masks[0]);
3039 replied |= stream_get_parameter_formats(query, reply,
3040 &in->supported_formats[0]);
3041 replied |= stream_get_parameter_rates(query, reply,
3042 &in->supported_sample_rates[0]);
3043 if (replied) {
3044 str = str_parms_to_str(reply);
3045 } else {
3046 str = strdup(keys);
3047 }
3048 str_parms_destroy(query);
3049 str_parms_destroy(reply);
3050 ALOGV("%s: exit: returns - %s", __func__, str);
3051 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003052}
3053
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003054static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003055{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003056 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003057}
3058
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003059static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3060{
3061 if (!stream || !parms)
3062 return;
3063
3064 struct stream_in *in = (struct stream_in *)stream;
3065 struct audio_device *adev = in->dev;
3066
3067 card_status_t status;
3068 int card;
3069 if (parse_snd_card_status(parms, &card, &status) < 0)
3070 return;
3071
3072 pthread_mutex_lock(&adev->lock);
3073 bool valid_cb = (card == adev->snd_card);
3074 pthread_mutex_unlock(&adev->lock);
3075
3076 if (!valid_cb)
3077 return;
3078
3079 lock_input_stream(in);
3080 if (in->card_status != status)
3081 in->card_status = status;
3082 pthread_mutex_unlock(&in->lock);
3083
3084 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3085 use_case_table[in->usecase],
3086 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3087
3088 // a better solution would be to report error back to AF and let
3089 // it put the stream to standby
3090 if (status == CARD_STATUS_OFFLINE)
3091 in_standby(&in->stream.common);
3092
3093 return;
3094}
3095
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003096static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3097 size_t bytes)
3098{
3099 struct stream_in *in = (struct stream_in *)stream;
3100 struct audio_device *adev = in->dev;
3101 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003102 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003103
Eric Laurenta1478072015-09-21 17:21:52 -07003104 lock_input_stream(in);
3105
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003106 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003107 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003108 /* Read from sound trigger HAL */
3109 audio_extn_sound_trigger_read(in, buffer, bytes);
3110 pthread_mutex_unlock(&in->lock);
3111 return bytes;
3112 }
3113
Eric Laurent0e46adf2016-12-16 12:49:24 -08003114 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3115 ret = -ENOSYS;
3116 goto exit;
3117 }
3118
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003119 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003120 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003121 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003122 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003123 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003124 goto exit;
3125 }
3126 in->standby = 0;
3127 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003128
Haynes Mathew George03c40102016-01-29 17:57:48 -08003129 //what's the duration requested by the client?
3130 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3131 in->config.rate;
3132 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003133
Haynes Mathew George03c40102016-01-29 17:57:48 -08003134 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003135 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003136 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003137 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003138 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003139 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003140 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003141 if (ret < 0) {
3142 ALOGE("Failed to read w/err %s", strerror(errno));
3143 ret = -errno;
3144 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003145 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3146 if (bytes % 4 == 0) {
3147 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3148 int_buf_stream = buffer;
3149 for (size_t itt=0; itt < bytes/4 ; itt++) {
3150 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003151 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003152 } else {
3153 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3154 ret = -EINVAL;
3155 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003156 }
3157 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003158 }
3159
Haynes Mathew George03c40102016-01-29 17:57:48 -08003160 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003161
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003162 /*
3163 * Instead of writing zeroes here, we could trust the hardware
3164 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003165 * 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 -08003166 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003167 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003168 memset(buffer, 0, bytes);
3169
3170exit:
3171 pthread_mutex_unlock(&in->lock);
3172
3173 if (ret != 0) {
3174 in_standby(&in->stream.common);
3175 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Eric Laurentfdf296a2014-07-03 16:41:51 -07003176 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003177 in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003178 memset(buffer, 0, bytes); // clear return data
3179 }
3180 if (bytes > 0) {
Andy Hung6ebe5962016-01-15 17:46:57 -08003181 in->frames_read += bytes / audio_stream_in_frame_size(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003182 }
3183 return bytes;
3184}
3185
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003186static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003187{
3188 return 0;
3189}
3190
Andy Hung6ebe5962016-01-15 17:46:57 -08003191static int in_get_capture_position(const struct audio_stream_in *stream,
3192 int64_t *frames, int64_t *time)
3193{
3194 if (stream == NULL || frames == NULL || time == NULL) {
3195 return -EINVAL;
3196 }
3197 struct stream_in *in = (struct stream_in *)stream;
3198 int ret = -ENOSYS;
3199
3200 lock_input_stream(in);
3201 if (in->pcm) {
3202 struct timespec timestamp;
3203 unsigned int avail;
3204 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3205 *frames = in->frames_read + avail;
3206 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3207 ret = 0;
3208 }
3209 }
3210 pthread_mutex_unlock(&in->lock);
3211 return ret;
3212}
3213
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003214static int add_remove_audio_effect(const struct audio_stream *stream,
3215 effect_handle_t effect,
3216 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003217{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003218 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003219 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003220 int status = 0;
3221 effect_descriptor_t desc;
3222
3223 status = (*effect)->get_descriptor(effect, &desc);
3224 if (status != 0)
3225 return status;
3226
Eric Laurenta1478072015-09-21 17:21:52 -07003227 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003228 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003229 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003230 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003231 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003232 in->enable_aec != enable &&
3233 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3234 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003235 if (!enable)
3236 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003237 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3238 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3239 adev->enable_voicerx = enable;
3240 struct audio_usecase *usecase;
3241 struct listnode *node;
3242 list_for_each(node, &adev->usecase_list) {
3243 usecase = node_to_item(node, struct audio_usecase, list);
3244 if (usecase->type == PCM_PLAYBACK) {
3245 select_devices(adev, usecase->id);
3246 break;
3247 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003248 }
3249 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003250 if (!in->standby)
3251 select_devices(in->dev, in->usecase);
3252 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003253 if (in->enable_ns != enable &&
3254 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3255 in->enable_ns = enable;
3256 if (!in->standby)
3257 select_devices(in->dev, in->usecase);
3258 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003259 pthread_mutex_unlock(&in->dev->lock);
3260 pthread_mutex_unlock(&in->lock);
3261
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003262 return 0;
3263}
3264
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003265static int in_add_audio_effect(const struct audio_stream *stream,
3266 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003267{
Eric Laurent994a6932013-07-17 11:51:42 -07003268 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003269 return add_remove_audio_effect(stream, effect, true);
3270}
3271
3272static int in_remove_audio_effect(const struct audio_stream *stream,
3273 effect_handle_t effect)
3274{
Eric Laurent994a6932013-07-17 11:51:42 -07003275 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003276 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003277}
3278
Eric Laurent0e46adf2016-12-16 12:49:24 -08003279static int in_stop(const struct audio_stream_in* stream)
3280{
3281 struct stream_in *in = (struct stream_in *)stream;
3282 struct audio_device *adev = in->dev;
3283
3284 int ret = -ENOSYS;
3285 ALOGV("%s", __func__);
3286 pthread_mutex_lock(&adev->lock);
3287 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3288 in->capture_started && in->pcm != NULL) {
3289 pcm_stop(in->pcm);
3290 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003291 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003292 }
3293 pthread_mutex_unlock(&adev->lock);
3294 return ret;
3295}
3296
3297static int in_start(const struct audio_stream_in* stream)
3298{
3299 struct stream_in *in = (struct stream_in *)stream;
3300 struct audio_device *adev = in->dev;
3301 int ret = -ENOSYS;
3302
3303 ALOGV("%s in %p", __func__, in);
3304 pthread_mutex_lock(&adev->lock);
3305 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3306 !in->capture_started && in->pcm != NULL) {
3307 if (!in->capture_started) {
3308 ret = start_input_stream(in);
3309 if (ret == 0) {
3310 in->capture_started = true;
3311 }
3312 }
3313 }
3314 pthread_mutex_unlock(&adev->lock);
3315 return ret;
3316}
3317
3318static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3319 int32_t min_size_frames,
3320 struct audio_mmap_buffer_info *info)
3321{
3322 struct stream_in *in = (struct stream_in *)stream;
3323 struct audio_device *adev = in->dev;
3324 int ret = 0;
3325 unsigned int offset1;
3326 unsigned int frames1;
3327 const char *step = "";
3328
3329 pthread_mutex_lock(&adev->lock);
3330 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003331
Eric Laurent0e46adf2016-12-16 12:49:24 -08003332 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003333 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003334 ret = -EINVAL;
3335 goto exit;
3336 }
3337 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003338 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003339 ALOGV("%s in %p", __func__, in);
3340 ret = -ENOSYS;
3341 goto exit;
3342 }
3343 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3344 if (in->pcm_device_id < 0) {
3345 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3346 __func__, in->pcm_device_id, in->usecase);
3347 ret = -EINVAL;
3348 goto exit;
3349 }
Phil Burkbc991042017-02-24 08:06:44 -08003350
3351 adjust_mmap_period_count(&in->config, min_size_frames);
3352
Eric Laurent0e46adf2016-12-16 12:49:24 -08003353 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3354 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3355 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3356 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3357 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3358 step = "open";
3359 ret = -ENODEV;
3360 goto exit;
3361 }
3362
3363 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3364 if (ret < 0) {
3365 step = "begin";
3366 goto exit;
3367 }
3368 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
3369 info->burst_size_frames = in->config.period_size;
3370 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3371
3372 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(in->pcm,
3373 info->buffer_size_frames));
3374
3375 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3376 if (ret < 0) {
3377 step = "commit";
3378 goto exit;
3379 }
3380
Phil Burkbc991042017-02-24 08:06:44 -08003381 in->standby = false;
3382 ret = 0;
3383
Eric Laurent0e46adf2016-12-16 12:49:24 -08003384 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3385 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003386
3387exit:
3388 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003389 if (in->pcm == NULL) {
3390 ALOGE("%s: %s - %d", __func__, step, ret);
3391 } else {
3392 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003393 pcm_close(in->pcm);
3394 in->pcm = NULL;
3395 }
3396 }
3397 pthread_mutex_unlock(&adev->lock);
3398 return ret;
3399}
3400
3401static int in_get_mmap_position(const struct audio_stream_in *stream,
3402 struct audio_mmap_position *position)
3403{
3404 struct stream_in *in = (struct stream_in *)stream;
3405 ALOGVV("%s", __func__);
3406 if (position == NULL) {
3407 return -EINVAL;
3408 }
3409 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
3410 return -ENOSYS;
3411 }
3412 if (in->pcm == NULL) {
3413 return -ENOSYS;
3414 }
3415 struct timespec ts = { 0, 0 };
3416 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
3417 if (ret < 0) {
3418 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3419 return ret;
3420 }
Andy Hungfc044e12017-03-20 09:24:22 -07003421 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003422 return 0;
3423}
3424
3425
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003426static int adev_open_output_stream(struct audio_hw_device *dev,
3427 audio_io_handle_t handle,
3428 audio_devices_t devices,
3429 audio_output_flags_t flags,
3430 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003431 struct audio_stream_out **stream_out,
3432 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003433{
3434 struct audio_device *adev = (struct audio_device *)dev;
3435 struct stream_out *out;
3436 int i, ret;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003437 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
3438 bool is_usb_dev = audio_is_usb_out_device(devices) &&
3439 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
3440 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003441
Eric Laurent994a6932013-07-17 11:51:42 -07003442 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003443 __func__, config->sample_rate, config->channel_mask, devices, flags);
3444 *stream_out = NULL;
3445 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3446
3447 if (devices == AUDIO_DEVICE_NONE)
3448 devices = AUDIO_DEVICE_OUT_SPEAKER;
3449
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003450 out->flags = flags;
3451 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003452 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003453 out->format = config->format;
3454 out->sample_rate = config->sample_rate;
3455 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3456 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003457 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003458
3459 /* Init use case and pcm_config */
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003460 if (audio_is_linear_pcm(out->format) &&
3461 (out->flags == AUDIO_OUTPUT_FLAG_NONE ||
Haynes Mathew George569b7482017-05-08 14:44:27 -07003462 out->flags == AUDIO_OUTPUT_FLAG_DIRECT) && direct_dev) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003463 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003464 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003465 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003466 if (config->sample_rate == 0)
3467 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3468 if (config->channel_mask == 0)
3469 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3470 if (config->format == AUDIO_FORMAT_DEFAULT)
3471 config->format = AUDIO_FORMAT_PCM_16_BIT;
3472 } else if (is_usb_dev) {
3473 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
3474 &config->format,
3475 &out->supported_formats[0],
3476 MAX_SUPPORTED_FORMATS,
3477 &config->channel_mask,
3478 &out->supported_channel_masks[0],
3479 MAX_SUPPORTED_CHANNEL_MASKS,
3480 &config->sample_rate,
3481 &out->supported_sample_rates[0],
3482 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003483 ALOGV("plugged dev USB ret %d", ret);
3484 } else {
3485 ret = -1;
3486 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003487 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003488 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003489 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003490
Haynes Mathew George569b7482017-05-08 14:44:27 -07003491 out->channel_mask = config->channel_mask;
3492 out->sample_rate = config->sample_rate;
3493 out->format = config->format;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003494 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3495 // does this change?
Haynes Mathew George569b7482017-05-08 14:44:27 -07003496 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003497 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003498 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003499 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003500 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003501 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003502 pthread_mutex_lock(&adev->lock);
3503 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3504 pthread_mutex_unlock(&adev->lock);
3505
3506 // reject offload during card offline to allow
3507 // fallback to s/w paths
3508 if (offline) {
3509 ret = -ENODEV;
3510 goto error_open;
3511 }
3512
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003513 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3514 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3515 ALOGE("%s: Unsupported Offload information", __func__);
3516 ret = -EINVAL;
3517 goto error_open;
3518 }
3519 if (!is_supported_format(config->offload_info.format)) {
3520 ALOGE("%s: Unsupported audio format", __func__);
3521 ret = -EINVAL;
3522 goto error_open;
3523 }
3524
3525 out->compr_config.codec = (struct snd_codec *)
3526 calloc(1, sizeof(struct snd_codec));
3527
3528 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3529 if (config->offload_info.channel_mask)
3530 out->channel_mask = config->offload_info.channel_mask;
3531 else if (config->channel_mask)
3532 out->channel_mask = config->channel_mask;
3533 out->format = config->offload_info.format;
3534 out->sample_rate = config->offload_info.sample_rate;
3535
3536 out->stream.set_callback = out_set_callback;
3537 out->stream.pause = out_pause;
3538 out->stream.resume = out_resume;
3539 out->stream.drain = out_drain;
3540 out->stream.flush = out_flush;
3541
3542 out->compr_config.codec->id =
3543 get_snd_codec_id(config->offload_info.format);
3544 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3545 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07003546 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003547 out->compr_config.codec->bit_rate =
3548 config->offload_info.bit_rate;
3549 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003550 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003551 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3552
3553 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3554 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003555
3556 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003557 create_offload_callback_thread(out);
3558 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3559 __func__, config->offload_info.version,
3560 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003561 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07003562 switch (config->sample_rate) {
3563 case 8000:
3564 case 16000:
3565 case 48000:
3566 out->sample_rate = config->sample_rate;
3567 break;
3568 default:
3569 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003570 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003571 out->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003572 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3573 out->config = pcm_config_afe_proxy_playback;
3574 adev->voice_tx_output = out;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003575 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003576 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3577 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3578 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003579 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
3580 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3581 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003582 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3583 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003584 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003585 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003586 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3587 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3588 out->config = pcm_config_mmap_playback;
3589 out->stream.start = out_start;
3590 out->stream.stop = out_stop;
3591 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3592 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003593 } else {
3594 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3595 out->config = pcm_config_low_latency;
3596 }
3597 if (config->format != audio_format_from_pcm_format(out->config.format)) {
3598 if (k_enable_extended_precision
3599 && pcm_params_format_test(adev->use_case_table[out->usecase],
3600 pcm_format_from_audio_format(config->format))) {
3601 out->config.format = pcm_format_from_audio_format(config->format);
3602 /* out->format already set to config->format */
3603 } else {
3604 /* deny the externally proposed config format
3605 * and use the one specified in audio_hw layer configuration.
3606 * Note: out->format is returned by out->stream.common.get_format()
3607 * and is used to set config->format in the code several lines below.
3608 */
3609 out->format = audio_format_from_pcm_format(out->config.format);
3610 }
3611 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003612 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003613 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003614
3615 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
3616 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
3617 (config->channel_mask != 0 && config->channel_mask != out->channel_mask)) {
3618 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
3619 __func__, config->sample_rate, config->format, config->channel_mask);
3620 config->sample_rate = out->sample_rate;
3621 config->format = out->format;
3622 config->channel_mask = out->channel_mask;
3623 ret = -EINVAL;
3624 goto error_open;
3625 }
3626
Andy Hung6fcba9c2014-03-18 11:53:32 -07003627 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3628 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003629
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003630 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003631 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003632 adev->primary_output = out;
3633 else {
3634 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003635 ret = -EEXIST;
3636 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003637 }
3638 }
3639
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003640 /* Check if this usecase is already existing */
3641 pthread_mutex_lock(&adev->lock);
3642 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3643 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003644 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003645 ret = -EEXIST;
3646 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003647 }
3648 pthread_mutex_unlock(&adev->lock);
3649
3650 out->stream.common.get_sample_rate = out_get_sample_rate;
3651 out->stream.common.set_sample_rate = out_set_sample_rate;
3652 out->stream.common.get_buffer_size = out_get_buffer_size;
3653 out->stream.common.get_channels = out_get_channels;
3654 out->stream.common.get_format = out_get_format;
3655 out->stream.common.set_format = out_set_format;
3656 out->stream.common.standby = out_standby;
3657 out->stream.common.dump = out_dump;
3658 out->stream.common.set_parameters = out_set_parameters;
3659 out->stream.common.get_parameters = out_get_parameters;
3660 out->stream.common.add_audio_effect = out_add_audio_effect;
3661 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3662 out->stream.get_latency = out_get_latency;
3663 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003664#ifdef NO_AUDIO_OUT
3665 out->stream.write = out_write_for_no_output;
3666#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003667 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003668#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003669 out->stream.get_render_position = out_get_render_position;
3670 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003671 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003672
Eric Laurent0e46adf2016-12-16 12:49:24 -08003673 if (out->realtime)
3674 out->af_period_multiplier = af_period_multiplier;
3675 else
3676 out->af_period_multiplier = 1;
3677
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003678 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003679 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003680 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003681
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003682 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003683 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003684 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3685
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003686 config->format = out->stream.common.get_format(&out->stream.common);
3687 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3688 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3689
Andy Hunga452b0a2017-03-15 14:51:15 -07003690 out->error_log = error_log_create(
3691 ERROR_LOG_ENTRIES,
3692 1000000000 /* aggregate consecutive identical errors within one second in ns */);
3693
Andy Hungfc044e12017-03-20 09:24:22 -07003694 // power_log may be null if the format is not supported
Andy Hung9e737de2017-05-22 10:51:22 -07003695 // or not a userdebug or eng build.
3696 if (is_userdebug_or_eng_build()) {
3697 const size_t POWER_LOG_FRAMES_PER_ENTRY =
3698 (long long)config->sample_rate * POWER_LOG_SAMPLING_INTERVAL_MS / 1000;
3699
3700 out->power_log = power_log_create(
3701 config->sample_rate,
3702 audio_channel_count_from_out_mask(config->channel_mask),
3703 config->format,
3704 POWER_LOG_ENTRIES,
3705 POWER_LOG_FRAMES_PER_ENTRY);
3706 }
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003707
3708 /*
3709 By locking output stream before registering, we allow the callback
3710 to update stream's state only after stream's initial state is set to
3711 adev state.
3712 */
3713 lock_output_stream(out);
3714 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3715 pthread_mutex_lock(&adev->lock);
3716 out->card_status = adev->card_status;
3717 pthread_mutex_unlock(&adev->lock);
3718 pthread_mutex_unlock(&out->lock);
3719
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003720 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003721
Eric Laurent994a6932013-07-17 11:51:42 -07003722 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003723 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003724
3725error_open:
3726 free(out);
3727 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003728 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003729 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003730}
3731
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003732static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003733 struct audio_stream_out *stream)
3734{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003735 struct stream_out *out = (struct stream_out *)stream;
3736 struct audio_device *adev = out->dev;
3737
Eric Laurent994a6932013-07-17 11:51:42 -07003738 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003739
3740 // must deregister from sndmonitor first to prevent races
3741 // between the callback and close_stream
3742 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003743 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003744 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3745 destroy_offload_callback_thread(out);
3746
3747 if (out->compr_config.codec != NULL)
3748 free(out->compr_config.codec);
3749 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003750
3751 if (adev->voice_tx_output == out)
3752 adev->voice_tx_output = NULL;
3753
Andy Hungfc044e12017-03-20 09:24:22 -07003754 power_log_destroy(out->power_log);
3755 out->power_log = NULL;
3756
Andy Hunga452b0a2017-03-15 14:51:15 -07003757 error_log_destroy(out->error_log);
3758 out->error_log = NULL;
3759
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003760 pthread_cond_destroy(&out->cond);
3761 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003762 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003763 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003764}
3765
3766static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3767{
3768 struct audio_device *adev = (struct audio_device *)dev;
3769 struct str_parms *parms;
3770 char *str;
3771 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003772 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003773 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003774 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003775
Joe Onorato188b6222016-03-01 11:02:27 -08003776 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003777
3778 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003779
3780 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003781 status = voice_set_parameters(adev, parms);
3782 if (status != 0) {
3783 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003784 }
3785
3786 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3787 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003788 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003789 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3790 adev->bluetooth_nrec = true;
3791 else
3792 adev->bluetooth_nrec = false;
3793 }
3794
3795 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3796 if (ret >= 0) {
3797 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3798 adev->screen_off = false;
3799 else
3800 adev->screen_off = true;
3801 }
3802
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003803 ret = str_parms_get_int(parms, "rotation", &val);
3804 if (ret >= 0) {
3805 bool reverse_speakers = false;
3806 switch(val) {
3807 // FIXME: note that the code below assumes that the speakers are in the correct placement
3808 // relative to the user when the device is rotated 90deg from its default rotation. This
3809 // assumption is device-specific, not platform-specific like this code.
3810 case 270:
3811 reverse_speakers = true;
3812 break;
3813 case 0:
3814 case 90:
3815 case 180:
3816 break;
3817 default:
3818 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003819 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003820 }
Eric Laurent03f09432014-03-25 18:09:11 -07003821 if (status == 0) {
Ravi Kumar Alamanda1f60cf82015-04-23 19:45:17 -07003822 platform_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003823 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003824 }
3825
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003826 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3827 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003828 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003829 }
3830
David Linee3fe402017-03-13 10:00:42 -07003831 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3832 if (ret >= 0) {
3833 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
3834 if (device == AUDIO_DEVICE_OUT_USB_DEVICE) {
3835 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3836 if (ret >= 0) {
3837 const int card = atoi(value);
3838 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, card);
3839 }
3840 } else if (device == AUDIO_DEVICE_IN_USB_DEVICE) {
3841 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3842 if (ret >= 0) {
3843 const int card = atoi(value);
3844 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, card);
3845 }
3846 }
3847 }
3848
3849 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3850 if (ret >= 0) {
3851 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
3852 if (device == AUDIO_DEVICE_OUT_USB_DEVICE) {
3853 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3854 if (ret >= 0) {
3855 const int card = atoi(value);
3856
3857 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, card);
3858 }
3859 } else if (device == AUDIO_DEVICE_IN_USB_DEVICE) {
3860 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3861 if (ret >= 0) {
3862 const int card = atoi(value);
3863 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, card);
3864 }
3865 }
3866 }
3867
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08003868 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003869done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003870 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003871 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07003872 ALOGV("%s: exit with code(%d)", __func__, status);
3873 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003874}
3875
3876static char* adev_get_parameters(const struct audio_hw_device *dev,
3877 const char *keys)
3878{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003879 struct audio_device *adev = (struct audio_device *)dev;
3880 struct str_parms *reply = str_parms_create();
3881 struct str_parms *query = str_parms_create_str(keys);
3882 char *str;
3883
3884 pthread_mutex_lock(&adev->lock);
3885
3886 voice_get_parameters(adev, query, reply);
3887 str = str_parms_to_str(reply);
3888 str_parms_destroy(query);
3889 str_parms_destroy(reply);
3890
3891 pthread_mutex_unlock(&adev->lock);
3892 ALOGV("%s: exit: returns - %s", __func__, str);
3893 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003894}
3895
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003896static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003897{
3898 return 0;
3899}
3900
Haynes Mathew George5191a852013-09-11 14:19:36 -07003901static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3902{
3903 int ret;
3904 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003905
Eric Laurent4cc4ce12014-09-10 13:21:01 -05003906 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
3907
Haynes Mathew George5191a852013-09-11 14:19:36 -07003908 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003909 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003910 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003911
Haynes Mathew George5191a852013-09-11 14:19:36 -07003912 return ret;
3913}
3914
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003915static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003916{
3917 return -ENOSYS;
3918}
3919
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003920static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3921 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003922{
3923 return -ENOSYS;
3924}
3925
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003926static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003927{
3928 return -ENOSYS;
3929}
3930
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003931static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003932{
3933 return -ENOSYS;
3934}
3935
3936static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3937{
3938 struct audio_device *adev = (struct audio_device *)dev;
3939
3940 pthread_mutex_lock(&adev->lock);
3941 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07003942 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003943 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07003944 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3945 voice_is_in_call(adev)) {
3946 voice_stop_call(adev);
3947 adev->current_call_output = NULL;
3948 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003949 }
3950 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003951
3952 audio_extn_extspk_set_mode(adev->extspk, mode);
3953
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003954 return 0;
3955}
3956
3957static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3958{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003959 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003960 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003961
Eric Laurent2bafff12016-03-17 12:17:23 -07003962 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003963 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08003964 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
3965 ret = audio_extn_hfp_set_mic_mute(adev, state);
3966 } else {
3967 ret = voice_set_mic_mute(adev, state);
3968 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003969 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00003970 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003971
3972 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003973}
3974
3975static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3976{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003977 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003978 return 0;
3979}
3980
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003981static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003982 const struct audio_config *config)
3983{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003984 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003985
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003986 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3987 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003988}
3989
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07003990static bool adev_input_allow_hifi_record(struct audio_device *adev,
3991 audio_devices_t devices,
3992 audio_input_flags_t flags,
3993 audio_source_t source) {
3994 const bool allowed = true;
3995
3996 if (!audio_is_usb_in_device(devices))
3997 return !allowed;
3998
3999 switch (flags) {
4000 case AUDIO_INPUT_FLAG_NONE:
4001 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4002 break;
4003 default:
4004 return !allowed;
4005 }
4006
4007 switch (source) {
4008 case AUDIO_SOURCE_DEFAULT:
4009 case AUDIO_SOURCE_MIC:
4010 case AUDIO_SOURCE_UNPROCESSED:
4011 break;
4012 default:
4013 return !allowed;
4014 }
4015
4016 switch (adev->mode) {
4017 case 0:
4018 break;
4019 default:
4020 return !allowed;
4021 }
4022
4023 return allowed;
4024}
4025
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004026static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004027 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004028 audio_devices_t devices,
4029 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004030 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004031 audio_input_flags_t flags,
4032 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004033 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004034{
4035 struct audio_device *adev = (struct audio_device *)dev;
4036 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004037 int ret = 0, buffer_size, frame_size;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004038 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004039 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004040 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004041 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4042 devices,
4043 flags,
4044 source);
4045 ALOGE("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004046 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004047
4048 if (config->sample_rate == 0)
4049 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4050 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4051 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4052 if (config->format == AUDIO_FORMAT_DEFAULT)
4053 config->format = AUDIO_FORMAT_PCM_16_BIT;
4054
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004055 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
4056 return -EINVAL;
4057
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004058 if (audio_extn_tfa_98xx_is_supported() &&
4059 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004060 return -EINVAL;
4061
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004062 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4063
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004064 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004065 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004066
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004067 in->stream.common.get_sample_rate = in_get_sample_rate;
4068 in->stream.common.set_sample_rate = in_set_sample_rate;
4069 in->stream.common.get_buffer_size = in_get_buffer_size;
4070 in->stream.common.get_channels = in_get_channels;
4071 in->stream.common.get_format = in_get_format;
4072 in->stream.common.set_format = in_set_format;
4073 in->stream.common.standby = in_standby;
4074 in->stream.common.dump = in_dump;
4075 in->stream.common.set_parameters = in_set_parameters;
4076 in->stream.common.get_parameters = in_get_parameters;
4077 in->stream.common.add_audio_effect = in_add_audio_effect;
4078 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4079 in->stream.set_gain = in_set_gain;
4080 in->stream.read = in_read;
4081 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08004082 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004083
4084 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004085 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004086 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004087 in->standby = 1;
4088 in->channel_mask = config->channel_mask;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004089 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004090 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004091
Haynes Mathew George569b7482017-05-08 14:44:27 -07004092 if (is_usb_dev && may_use_hifi_record) {
4093 /* HiFi record selects an appropriate format, channel, rate combo
4094 depending on sink capabilities*/
4095 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
4096 &config->format,
4097 &in->supported_formats[0],
4098 MAX_SUPPORTED_FORMATS,
4099 &config->channel_mask,
4100 &in->supported_channel_masks[0],
4101 MAX_SUPPORTED_CHANNEL_MASKS,
4102 &config->sample_rate,
4103 &in->supported_sample_rates[0],
4104 MAX_SUPPORTED_SAMPLE_RATES);
4105 if (ret != 0) {
4106 ret = -EINVAL;
4107 goto err_open;
4108 }
4109 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07004110 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07004111 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
4112 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
4113 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4114 bool ret_error = false;
4115 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4116 from HAL is 8_24
4117 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4118 8_24 return error indicating supported format is 8_24
4119 *> In case of any other source requesting 24 bit or float return error
4120 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07004121
vivek mehta57ff9b52016-04-28 14:13:08 -07004122 on error flinger will retry with supported format passed
4123 */
4124 if (source != AUDIO_SOURCE_UNPROCESSED) {
4125 config->format = AUDIO_FORMAT_PCM_16_BIT;
4126 ret_error = true;
4127 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
4128 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
4129 ret_error = true;
4130 }
4131
4132 if (ret_error) {
4133 ret = -EINVAL;
4134 goto err_open;
4135 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004136 }
4137
vivek mehta57ff9b52016-04-28 14:13:08 -07004138 in->format = config->format;
4139
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004140 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004141 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
4142 if (config->sample_rate == 0)
4143 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4144 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4145 config->sample_rate != 8000) {
4146 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4147 ret = -EINVAL;
4148 goto err_open;
4149 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004150
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004151 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4152 config->format = AUDIO_FORMAT_PCM_16_BIT;
4153 ret = -EINVAL;
4154 goto err_open;
4155 }
4156
4157 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4158 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07004159 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004160 } else if (is_usb_dev && may_use_hifi_record) {
4161 in->usecase = USECASE_AUDIO_RECORD_HIFI;
4162 in->config = pcm_config_audio_capture;
4163 frame_size = audio_stream_in_frame_size(&in->stream);
4164 buffer_size = get_input_buffer_size(config->sample_rate,
4165 config->format,
4166 channel_count,
4167 false /*is_low_latency*/);
4168 in->config.period_size = buffer_size / frame_size;
4169 in->config.rate = config->sample_rate;
4170 in->af_period_multiplier = 1;
4171 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004172 } else {
4173 in->usecase = USECASE_AUDIO_RECORD;
4174 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08004175 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004176 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07004177#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004178 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07004179#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08004180 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004181 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08004182 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004183 frame_size = audio_stream_in_frame_size(&in->stream);
4184 buffer_size = get_input_buffer_size(config->sample_rate,
4185 config->format,
4186 channel_count,
Haynes Mathew George569b7482017-05-08 14:44:27 -07004187 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004188 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004189 in->config.rate = config->sample_rate;
4190 in->af_period_multiplier = 1;
4191 } else {
4192 // period size is left untouched for rt mode playback
4193 in->config = pcm_config_audio_capture_rt;
4194 in->af_period_multiplier = af_period_multiplier;
4195 }
4196 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
4197 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004198 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08004199 in->usecase = USECASE_AUDIO_RECORD_MMAP;
4200 in->config = pcm_config_mmap_capture;
4201 in->stream.start = in_start;
4202 in->stream.stop = in_stop;
4203 in->stream.create_mmap_buffer = in_create_mmap_buffer;
4204 in->stream.get_mmap_position = in_get_mmap_position;
4205 in->af_period_multiplier = 1;
4206 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
4207 } else {
4208 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004209 frame_size = audio_stream_in_frame_size(&in->stream);
4210 buffer_size = get_input_buffer_size(config->sample_rate,
4211 config->format,
4212 channel_count,
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004213 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004214 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004215 in->config.rate = config->sample_rate;
4216 in->af_period_multiplier = 1;
4217 }
4218 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
4219 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004220 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004221
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004222 in->config.channels = channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004223
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004224 /* This stream could be for sound trigger lab,
4225 get sound trigger pcm if present */
4226 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004227
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004228 lock_input_stream(in);
4229 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
4230 pthread_mutex_lock(&adev->lock);
4231 in->card_status = adev->card_status;
4232 pthread_mutex_unlock(&adev->lock);
4233 pthread_mutex_unlock(&in->lock);
4234
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004235 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004236 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004237 return 0;
4238
4239err_open:
4240 free(in);
4241 *stream_in = NULL;
4242 return ret;
4243}
4244
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004245static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004246 struct audio_stream_in *stream)
4247{
Eric Laurent994a6932013-07-17 11:51:42 -07004248 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004249
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004250 // must deregister from sndmonitor first to prevent races
4251 // between the callback and close_stream
4252 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004253 in_standby(&stream->common);
4254 free(stream);
4255
4256 return;
4257}
4258
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004259static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004260{
4261 return 0;
4262}
4263
Andy Hung31aca912014-03-20 17:14:59 -07004264/* verifies input and output devices and their capabilities.
4265 *
4266 * This verification is required when enabling extended bit-depth or
4267 * sampling rates, as not all qcom products support it.
4268 *
4269 * Suitable for calling only on initialization such as adev_open().
4270 * It fills the audio_device use_case_table[] array.
4271 *
4272 * Has a side-effect that it needs to configure audio routing / devices
4273 * in order to power up the devices and read the device parameters.
4274 * It does not acquire any hw device lock. Should restore the devices
4275 * back to "normal state" upon completion.
4276 */
4277static int adev_verify_devices(struct audio_device *adev)
4278{
4279 /* enumeration is a bit difficult because one really wants to pull
4280 * the use_case, device id, etc from the hidden pcm_device_table[].
4281 * In this case there are the following use cases and device ids.
4282 *
4283 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
4284 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004285 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07004286 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
4287 * [USECASE_AUDIO_RECORD] = {0, 0},
4288 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
4289 * [USECASE_VOICE_CALL] = {2, 2},
4290 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004291 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07004292 * USECASE_VOICE_CALL omitted, but possible for either input or output.
4293 */
4294
4295 /* should be the usecases enabled in adev_open_input_stream() */
4296 static const int test_in_usecases[] = {
4297 USECASE_AUDIO_RECORD,
4298 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
4299 };
4300 /* should be the usecases enabled in adev_open_output_stream()*/
4301 static const int test_out_usecases[] = {
4302 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
4303 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
4304 };
4305 static const usecase_type_t usecase_type_by_dir[] = {
4306 PCM_PLAYBACK,
4307 PCM_CAPTURE,
4308 };
4309 static const unsigned flags_by_dir[] = {
4310 PCM_OUT,
4311 PCM_IN,
4312 };
4313
4314 size_t i;
4315 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004316 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07004317 char info[512]; /* for possible debug info */
4318
4319 for (dir = 0; dir < 2; ++dir) {
4320 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
4321 const unsigned flags_dir = flags_by_dir[dir];
4322 const size_t testsize =
4323 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
4324 const int *testcases =
4325 dir ? test_in_usecases : test_out_usecases;
4326 const audio_devices_t audio_device =
4327 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
4328
4329 for (i = 0; i < testsize; ++i) {
4330 const audio_usecase_t audio_usecase = testcases[i];
4331 int device_id;
4332 snd_device_t snd_device;
4333 struct pcm_params **pparams;
4334 struct stream_out out;
4335 struct stream_in in;
4336 struct audio_usecase uc_info;
4337 int retval;
4338
4339 pparams = &adev->use_case_table[audio_usecase];
4340 pcm_params_free(*pparams); /* can accept null input */
4341 *pparams = NULL;
4342
4343 /* find the device ID for the use case (signed, for error) */
4344 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
4345 if (device_id < 0)
4346 continue;
4347
4348 /* prepare structures for device probing */
4349 memset(&uc_info, 0, sizeof(uc_info));
4350 uc_info.id = audio_usecase;
4351 uc_info.type = usecase_type;
4352 if (dir) {
4353 adev->active_input = &in;
4354 memset(&in, 0, sizeof(in));
4355 in.device = audio_device;
4356 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4357 uc_info.stream.in = &in;
4358 } else {
4359 adev->active_input = NULL;
4360 }
4361 memset(&out, 0, sizeof(out));
4362 out.devices = audio_device; /* only field needed in select_devices */
4363 uc_info.stream.out = &out;
4364 uc_info.devices = audio_device;
4365 uc_info.in_snd_device = SND_DEVICE_NONE;
4366 uc_info.out_snd_device = SND_DEVICE_NONE;
4367 list_add_tail(&adev->usecase_list, &uc_info.list);
4368
4369 /* select device - similar to start_(in/out)put_stream() */
4370 retval = select_devices(adev, audio_usecase);
4371 if (retval >= 0) {
4372 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4373#if LOG_NDEBUG == 0
4374 if (*pparams) {
4375 ALOGV("%s: (%s) card %d device %d", __func__,
4376 dir ? "input" : "output", card_id, device_id);
4377 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004378 } else {
4379 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4380 }
4381#endif
4382 }
4383
4384 /* deselect device - similar to stop_(in/out)put_stream() */
4385 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004386 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004387 /* 2. Disable the rx device */
4388 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004389 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004390 list_remove(&uc_info.list);
4391 }
4392 }
4393 adev->active_input = NULL; /* restore adev state */
4394 return 0;
4395}
4396
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004397static int adev_close(hw_device_t *device)
4398{
Andy Hung31aca912014-03-20 17:14:59 -07004399 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004400 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004401
4402 if (!adev)
4403 return 0;
4404
Kevin Rocarda5453442017-05-02 15:09:20 -07004405 audio_extn_snd_mon_unregister_listener(adev);
Kevin Rocard8342c2c2017-04-07 18:50:00 -07004406 audio_extn_snd_mon_deinit();
Kevin Rocarda5453442017-05-02 15:09:20 -07004407
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004408 audio_extn_tfa_98xx_deinit();
4409
vivek mehta1a9b7c02015-06-25 11:49:38 -07004410 pthread_mutex_lock(&adev_init_lock);
4411
4412 if ((--audio_device_ref_count) == 0) {
4413 audio_route_free(adev->audio_route);
4414 free(adev->snd_dev_ref_cnt);
4415 platform_deinit(adev->platform);
4416 audio_extn_extspk_deinit(adev->extspk);
4417 audio_extn_sound_trigger_deinit(adev);
4418 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4419 pcm_params_free(adev->use_case_table[i]);
4420 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004421 if (adev->adm_deinit)
4422 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004423 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004424 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004425
4426 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004427
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004428 return 0;
4429}
4430
Glenn Kasten4f993392014-05-14 07:30:48 -07004431/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4432 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4433 * just that it _might_ work.
4434 */
4435static int period_size_is_plausible_for_low_latency(int period_size)
4436{
4437 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004438 case 48:
4439 case 96:
4440 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004441 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004442 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004443 case 240:
4444 case 320:
4445 case 480:
4446 return 1;
4447 default:
4448 return 0;
4449 }
4450}
4451
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004452static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4453{
4454 int card;
4455 card_status_t status;
4456
4457 if (!parms)
4458 return;
4459
4460 if (parse_snd_card_status(parms, &card, &status) < 0)
4461 return;
4462
4463 pthread_mutex_lock(&adev->lock);
4464 bool valid_cb = (card == adev->snd_card);
4465 if (valid_cb) {
4466 if (adev->card_status != status) {
4467 adev->card_status = status;
4468 platform_snd_card_update(adev->platform, status);
4469 }
4470 }
4471 pthread_mutex_unlock(&adev->lock);
4472 return;
4473}
4474
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004475static int adev_open(const hw_module_t *module, const char *name,
4476 hw_device_t **device)
4477{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004478 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004479
Eric Laurent2bafff12016-03-17 12:17:23 -07004480 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004481 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004482 pthread_mutex_lock(&adev_init_lock);
4483 if (audio_device_ref_count != 0) {
4484 *device = &adev->device.common;
4485 audio_device_ref_count++;
4486 ALOGV("%s: returning existing instance of adev", __func__);
4487 ALOGV("%s: exit", __func__);
4488 pthread_mutex_unlock(&adev_init_lock);
4489 return 0;
4490 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004491 adev = calloc(1, sizeof(struct audio_device));
4492
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004493 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4494
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004495 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4496 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4497 adev->device.common.module = (struct hw_module_t *)module;
4498 adev->device.common.close = adev_close;
4499
4500 adev->device.init_check = adev_init_check;
4501 adev->device.set_voice_volume = adev_set_voice_volume;
4502 adev->device.set_master_volume = adev_set_master_volume;
4503 adev->device.get_master_volume = adev_get_master_volume;
4504 adev->device.set_master_mute = adev_set_master_mute;
4505 adev->device.get_master_mute = adev_get_master_mute;
4506 adev->device.set_mode = adev_set_mode;
4507 adev->device.set_mic_mute = adev_set_mic_mute;
4508 adev->device.get_mic_mute = adev_get_mic_mute;
4509 adev->device.set_parameters = adev_set_parameters;
4510 adev->device.get_parameters = adev_get_parameters;
4511 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4512 adev->device.open_output_stream = adev_open_output_stream;
4513 adev->device.close_output_stream = adev_close_output_stream;
4514 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004515
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004516 adev->device.close_input_stream = adev_close_input_stream;
4517 adev->device.dump = adev_dump;
4518
4519 /* Set the default route before the PCM stream is opened */
4520 pthread_mutex_lock(&adev->lock);
4521 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004522 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004523 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004524 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004525 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004526 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004527 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004528 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004529 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004530 pthread_mutex_unlock(&adev->lock);
4531
4532 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004533 adev->platform = platform_init(adev);
4534 if (!adev->platform) {
4535 free(adev->snd_dev_ref_cnt);
4536 free(adev);
4537 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4538 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004539 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004540 return -EINVAL;
4541 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05004542 adev->extspk = audio_extn_extspk_init(adev);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004543 audio_extn_sound_trigger_init(adev);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004544
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004545 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4546 if (adev->visualizer_lib == NULL) {
4547 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4548 } else {
4549 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4550 adev->visualizer_start_output =
4551 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4552 "visualizer_hal_start_output");
4553 adev->visualizer_stop_output =
4554 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4555 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07004556 }
4557
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004558 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4559 if (adev->offload_effects_lib == NULL) {
4560 ALOGW("%s: DLOPEN failed for %s", __func__,
4561 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4562 } else {
4563 ALOGV("%s: DLOPEN successful for %s", __func__,
4564 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4565 adev->offload_effects_start_output =
4566 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4567 "offload_effects_bundle_hal_start_output");
4568 adev->offload_effects_stop_output =
4569 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4570 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07004571 }
4572
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004573 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4574 if (adev->adm_lib == NULL) {
4575 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4576 } else {
4577 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4578 adev->adm_init = (adm_init_t)
4579 dlsym(adev->adm_lib, "adm_init");
4580 adev->adm_deinit = (adm_deinit_t)
4581 dlsym(adev->adm_lib, "adm_deinit");
4582 adev->adm_register_input_stream = (adm_register_input_stream_t)
4583 dlsym(adev->adm_lib, "adm_register_input_stream");
4584 adev->adm_register_output_stream = (adm_register_output_stream_t)
4585 dlsym(adev->adm_lib, "adm_register_output_stream");
4586 adev->adm_deregister_stream = (adm_deregister_stream_t)
4587 dlsym(adev->adm_lib, "adm_deregister_stream");
4588 adev->adm_request_focus = (adm_request_focus_t)
4589 dlsym(adev->adm_lib, "adm_request_focus");
4590 adev->adm_abandon_focus = (adm_abandon_focus_t)
4591 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08004592 adev->adm_set_config = (adm_set_config_t)
4593 dlsym(adev->adm_lib, "adm_set_config");
4594 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4595 dlsym(adev->adm_lib, "adm_request_focus_v2");
4596 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4597 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4598 adev->adm_on_routing_change = (adm_on_routing_change_t)
4599 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004600 }
4601
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004602 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004603 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004604
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004605 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004606
Andy Hung31aca912014-03-20 17:14:59 -07004607 if (k_enable_extended_precision)
4608 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004609
Glenn Kasten4f993392014-05-14 07:30:48 -07004610 char value[PROPERTY_VALUE_MAX];
4611 int trial;
4612 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4613 trial = atoi(value);
4614 if (period_size_is_plausible_for_low_latency(trial)) {
4615 pcm_config_low_latency.period_size = trial;
4616 pcm_config_low_latency.start_threshold = trial / 4;
4617 pcm_config_low_latency.avail_min = trial / 4;
4618 configured_low_latency_capture_period_size = trial;
4619 }
4620 }
4621 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4622 trial = atoi(value);
4623 if (period_size_is_plausible_for_low_latency(trial)) {
4624 configured_low_latency_capture_period_size = trial;
4625 }
4626 }
4627
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004628 // commented as full set of app type cfg is sent from platform
4629 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004630 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004631
4632 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4633 af_period_multiplier = atoi(value);
4634 if (af_period_multiplier < 0) {
4635 af_period_multiplier = 2;
4636 } else if (af_period_multiplier > 4) {
4637 af_period_multiplier = 4;
4638 }
4639 ALOGV("new period_multiplier = %d", af_period_multiplier);
4640 }
4641
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004642 audio_extn_tfa_98xx_init(adev);
4643
vivek mehta1a9b7c02015-06-25 11:49:38 -07004644 pthread_mutex_unlock(&adev_init_lock);
4645
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004646 if (adev->adm_init)
4647 adev->adm_data = adev->adm_init();
4648
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004649 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004650 audio_extn_snd_mon_init();
4651 pthread_mutex_lock(&adev->lock);
4652 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
4653 adev->card_status = CARD_STATUS_ONLINE;
4654 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004655
Eric Laurent2bafff12016-03-17 12:17:23 -07004656 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004657 return 0;
4658}
4659
4660static struct hw_module_methods_t hal_module_methods = {
4661 .open = adev_open,
4662};
4663
4664struct audio_module HAL_MODULE_INFO_SYM = {
4665 .common = {
4666 .tag = HARDWARE_MODULE_TAG,
4667 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4668 .hal_api_version = HARDWARE_HAL_API_VERSION,
4669 .id = AUDIO_HARDWARE_MODULE_ID,
4670 .name = "QCOM Audio HAL",
4671 .author = "Code Aurora Forum",
4672 .methods = &hal_module_methods,
4673 },
4674};