blob: 065d1d04617f5d00748c600934d5e196be523be4 [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
Andy Hungd13f0d32017-06-12 13:58:37 -070096static const int64_t NANOS_PER_SECOND = 1000000000;
Eric Laurent0e46adf2016-12-16 12:49:24 -080097
Andy Hung31aca912014-03-20 17:14:59 -070098/* This constant enables extended precision handling.
99 * TODO The flag is off until more testing is done.
100 */
101static const bool k_enable_extended_precision = false;
102
Eric Laurentb23d5282013-05-14 15:27:20 -0700103struct pcm_config pcm_config_deep_buffer = {
vivek mehtadae44712015-07-27 14:13:18 -0700104 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700105 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
106 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
107 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
108 .format = PCM_FORMAT_S16_LE,
109 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
110 .stop_threshold = INT_MAX,
111 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
112};
113
114struct pcm_config pcm_config_low_latency = {
vivek mehtadae44712015-07-27 14:13:18 -0700115 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700116 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
117 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
118 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
119 .format = PCM_FORMAT_S16_LE,
120 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
121 .stop_threshold = INT_MAX,
122 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
123};
124
Haynes Mathew George03c40102016-01-29 17:57:48 -0800125static int af_period_multiplier = 4;
126struct pcm_config pcm_config_rt = {
127 .channels = DEFAULT_CHANNEL_COUNT,
128 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
129 .period_size = ULL_PERIOD_SIZE, //1 ms
130 .period_count = 512, //=> buffer size is 512ms
131 .format = PCM_FORMAT_S16_LE,
132 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
133 .stop_threshold = INT_MAX,
134 .silence_threshold = 0,
135 .silence_size = 0,
136 .avail_min = ULL_PERIOD_SIZE, //1 ms
137};
138
Eric Laurentb23d5282013-05-14 15:27:20 -0700139struct pcm_config pcm_config_hdmi_multi = {
140 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
141 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
142 .period_size = HDMI_MULTI_PERIOD_SIZE,
143 .period_count = HDMI_MULTI_PERIOD_COUNT,
144 .format = PCM_FORMAT_S16_LE,
145 .start_threshold = 0,
146 .stop_threshold = INT_MAX,
147 .avail_min = 0,
148};
149
Eric Laurent0e46adf2016-12-16 12:49:24 -0800150struct pcm_config pcm_config_mmap_playback = {
151 .channels = DEFAULT_CHANNEL_COUNT,
152 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
153 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800154 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800155 .format = PCM_FORMAT_S16_LE,
156 .start_threshold = MMAP_PERIOD_SIZE*8,
157 .stop_threshold = INT32_MAX,
158 .silence_threshold = 0,
159 .silence_size = 0,
160 .avail_min = MMAP_PERIOD_SIZE, //1 ms
161};
162
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800163struct pcm_config pcm_config_hifi = {
164 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
165 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
166 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
167 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
168 .format = PCM_FORMAT_S24_3LE,
169 .start_threshold = 0,
170 .stop_threshold = INT_MAX,
171 .avail_min = 0,
172};
173
Eric Laurentb23d5282013-05-14 15:27:20 -0700174struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700175 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700176 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
177 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700178 .stop_threshold = INT_MAX,
179 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700180};
181
Haynes Mathew George03c40102016-01-29 17:57:48 -0800182struct pcm_config pcm_config_audio_capture_rt = {
183 .channels = DEFAULT_CHANNEL_COUNT,
184 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
185 .period_size = ULL_PERIOD_SIZE,
186 .period_count = 512,
187 .format = PCM_FORMAT_S16_LE,
188 .start_threshold = 0,
189 .stop_threshold = INT_MAX,
190 .silence_threshold = 0,
191 .silence_size = 0,
192 .avail_min = ULL_PERIOD_SIZE, //1 ms
193};
194
Eric Laurent0e46adf2016-12-16 12:49:24 -0800195struct pcm_config pcm_config_mmap_capture = {
196 .channels = DEFAULT_CHANNEL_COUNT,
197 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
198 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800199 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800200 .format = PCM_FORMAT_S16_LE,
201 .start_threshold = 0,
202 .stop_threshold = INT_MAX,
203 .silence_threshold = 0,
204 .silence_size = 0,
205 .avail_min = MMAP_PERIOD_SIZE, //1 ms
206};
207
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700208#define AFE_PROXY_CHANNEL_COUNT 2
209#define AFE_PROXY_SAMPLING_RATE 48000
210
211#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
212#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
213
214struct pcm_config pcm_config_afe_proxy_playback = {
215 .channels = AFE_PROXY_CHANNEL_COUNT,
216 .rate = AFE_PROXY_SAMPLING_RATE,
217 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
218 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
219 .format = PCM_FORMAT_S16_LE,
220 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
221 .stop_threshold = INT_MAX,
222 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
223};
224
225#define AFE_PROXY_RECORD_PERIOD_SIZE 768
226#define AFE_PROXY_RECORD_PERIOD_COUNT 4
227
228struct pcm_config pcm_config_afe_proxy_record = {
229 .channels = AFE_PROXY_CHANNEL_COUNT,
230 .rate = AFE_PROXY_SAMPLING_RATE,
231 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
232 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
233 .format = PCM_FORMAT_S16_LE,
234 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
235 .stop_threshold = INT_MAX,
236 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
237};
238
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700239const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700240 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
241 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800242 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700243 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700244 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700245 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800246 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700247
Eric Laurentb23d5282013-05-14 15:27:20 -0700248 [USECASE_AUDIO_RECORD] = "audio-record",
249 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800250 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George569b7482017-05-08 14:44:27 -0700251 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700252
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800253 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
254 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700255
Eric Laurentb23d5282013-05-14 15:27:20 -0700256 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700257 [USECASE_VOICE2_CALL] = "voice2-call",
258 [USECASE_VOLTE_CALL] = "volte-call",
259 [USECASE_QCHAT_CALL] = "qchat-call",
260 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800261 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
262 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700263
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700264 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
265 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
266
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700267 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
268 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
vivek mehta781065c2017-04-04 12:55:01 -0700269
270 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
271 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
272 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
273
Eric Laurentb23d5282013-05-14 15:27:20 -0700274};
275
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800276
277#define STRING_TO_ENUM(string) { #string, string }
278
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800279struct string_to_enum {
280 const char *name;
281 uint32_t value;
282};
283
Haynes Mathew George569b7482017-05-08 14:44:27 -0700284static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800285 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
286 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
287 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George569b7482017-05-08 14:44:27 -0700288 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
289 //TBD - string values for channel_in > 2?
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800290};
291
Haynes Mathew George5191a852013-09-11 14:19:36 -0700292static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700293static struct audio_device *adev = NULL;
Andy Hung9e737de2017-05-22 10:51:22 -0700294static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700295static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700296//cache last MBDRC cal step level
297static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700298
Andy Hung9e737de2017-05-22 10:51:22 -0700299// TODO: Consider moving this to a pthread_once() if we have more
300// static initialization required.
301static bool is_userdebug_or_eng_build() {
302 char value[PROPERTY_VALUE_MAX];
303 (void)property_get("ro.build.type", value, "unknown"); // ignore actual length
304 return strcmp(value, "userdebug") == 0 || strcmp(value, "eng") == 0;
305}
306
Haynes Mathew George03c40102016-01-29 17:57:48 -0800307static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
308 int flags __unused)
309{
310 int dir = 0;
311 switch (uc_id) {
312 case USECASE_AUDIO_RECORD_LOW_LATENCY:
313 dir = 1;
314 case USECASE_AUDIO_PLAYBACK_ULL:
315 break;
316 default:
317 return false;
318 }
319
320 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
321 PCM_PLAYBACK : PCM_CAPTURE);
322 if (adev->adm_is_noirq_avail)
323 return adev->adm_is_noirq_avail(adev->adm_data,
324 adev->snd_card, dev_id, dir);
325 return false;
326}
327
328static void register_out_stream(struct stream_out *out)
329{
330 struct audio_device *adev = out->dev;
331 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
332 return;
333
334 if (!adev->adm_register_output_stream)
335 return;
336
337 adev->adm_register_output_stream(adev->adm_data,
338 out->handle,
339 out->flags);
340
341 if (!adev->adm_set_config)
342 return;
343
344 if (out->realtime) {
345 adev->adm_set_config(adev->adm_data,
346 out->handle,
347 out->pcm, &out->config);
348 }
349}
350
351static void register_in_stream(struct stream_in *in)
352{
353 struct audio_device *adev = in->dev;
354 if (!adev->adm_register_input_stream)
355 return;
356
357 adev->adm_register_input_stream(adev->adm_data,
358 in->capture_handle,
359 in->flags);
360
361 if (!adev->adm_set_config)
362 return;
363
364 if (in->realtime) {
365 adev->adm_set_config(adev->adm_data,
366 in->capture_handle,
367 in->pcm,
368 &in->config);
369 }
370}
371
372static void request_out_focus(struct stream_out *out, long ns)
373{
374 struct audio_device *adev = out->dev;
375
Haynes Mathew George03c40102016-01-29 17:57:48 -0800376 if (adev->adm_request_focus_v2) {
377 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
378 } else if (adev->adm_request_focus) {
379 adev->adm_request_focus(adev->adm_data, out->handle);
380 }
381}
382
383static void request_in_focus(struct stream_in *in, long ns)
384{
385 struct audio_device *adev = in->dev;
386
Haynes Mathew George03c40102016-01-29 17:57:48 -0800387 if (adev->adm_request_focus_v2) {
388 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
389 } else if (adev->adm_request_focus) {
390 adev->adm_request_focus(adev->adm_data, in->capture_handle);
391 }
392}
393
394static void release_out_focus(struct stream_out *out, long ns __unused)
395{
396 struct audio_device *adev = out->dev;
397
398 if (adev->adm_abandon_focus)
399 adev->adm_abandon_focus(adev->adm_data, out->handle);
400}
401
402static void release_in_focus(struct stream_in *in, long ns __unused)
403{
404 struct audio_device *adev = in->dev;
405 if (adev->adm_abandon_focus)
406 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
407}
408
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700409static int parse_snd_card_status(struct str_parms * parms, int * card,
410 card_status_t * status)
411{
412 char value[32]={0};
413 char state[32]={0};
414
415 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
416
417 if (ret < 0)
418 return -1;
419
420 // sscanf should be okay as value is of max length 32.
421 // same as sizeof state.
422 if (sscanf(value, "%d,%s", card, state) < 2)
423 return -1;
424
425 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
426 CARD_STATUS_OFFLINE;
427 return 0;
428}
429
vivek mehta1a9b7c02015-06-25 11:49:38 -0700430__attribute__ ((visibility ("default")))
431bool audio_hw_send_gain_dep_calibration(int level) {
432 bool ret_val = false;
433 ALOGV("%s: enter ... ", __func__);
434
435 pthread_mutex_lock(&adev_init_lock);
436
437 if (adev != NULL && adev->platform != NULL) {
438 pthread_mutex_lock(&adev->lock);
439 ret_val = platform_send_gain_dep_cal(adev->platform, level);
440 pthread_mutex_unlock(&adev->lock);
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700441
442 // if cal set fails, cache level info
443 // if cal set succeds, reset known last cal set
444 if (!ret_val)
445 last_known_cal_step = level;
446 else if (last_known_cal_step != -1)
447 last_known_cal_step = -1;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700448 } else {
449 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
450 }
451
452 pthread_mutex_unlock(&adev_init_lock);
453
454 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
455 return ret_val;
456}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700457
vivek mehtaa8d7c922016-05-25 14:40:44 -0700458__attribute__ ((visibility ("default")))
459int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
460 int table_size) {
461 int ret_val = 0;
462 ALOGV("%s: enter ... ", __func__);
463
464 pthread_mutex_lock(&adev_init_lock);
465 if (adev == NULL) {
466 ALOGW("%s: adev is NULL .... ", __func__);
467 goto done;
468 }
469
470 pthread_mutex_lock(&adev->lock);
471 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
472 pthread_mutex_unlock(&adev->lock);
473done:
474 pthread_mutex_unlock(&adev_init_lock);
475 ALOGV("%s: exit ... ", __func__);
476 return ret_val;
477}
478
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700479static bool is_supported_format(audio_format_t format)
480{
Eric Laurent8251ac82014-07-23 11:00:25 -0700481 switch (format) {
482 case AUDIO_FORMAT_MP3:
483 case AUDIO_FORMAT_AAC_LC:
484 case AUDIO_FORMAT_AAC_HE_V1:
485 case AUDIO_FORMAT_AAC_HE_V2:
486 return true;
487 default:
488 break;
489 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700490 return false;
491}
492
Haynes Mathew George03c40102016-01-29 17:57:48 -0800493static inline bool is_mmap_usecase(audio_usecase_t uc_id)
494{
495 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
496 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
497}
498
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700499static int get_snd_codec_id(audio_format_t format)
500{
501 int id = 0;
502
Eric Laurent8251ac82014-07-23 11:00:25 -0700503 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700504 case AUDIO_FORMAT_MP3:
505 id = SND_AUDIOCODEC_MP3;
506 break;
507 case AUDIO_FORMAT_AAC:
508 id = SND_AUDIOCODEC_AAC;
509 break;
510 default:
511 ALOGE("%s: Unsupported audio format", __func__);
512 }
513
514 return id;
515}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800516
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800517static int audio_ssr_status(struct audio_device *adev)
518{
519 int ret = 0;
520 struct mixer_ctl *ctl;
521 const char *mixer_ctl_name = "Audio SSR Status";
522
523 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
524 ret = mixer_ctl_get_value(ctl, 0);
525 ALOGD("%s: value: %d", __func__, ret);
526 return ret;
527}
528
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800529int enable_audio_route(struct audio_device *adev,
530 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800531{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700532 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800533 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800534
535 if (usecase == NULL)
536 return -EINVAL;
537
538 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
539
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800540 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700541 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800542 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700543 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800544
Yamit Mehtae3b99562016-09-16 22:44:00 +0530545 audio_extn_utils_send_app_type_cfg(adev, usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800546 audio_extn_utils_send_audio_calibration(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800547 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500548 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700549 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700550 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800551
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800552 ALOGV("%s: exit", __func__);
553 return 0;
554}
555
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800556int disable_audio_route(struct audio_device *adev,
557 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800558{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700559 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800560 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800561
562 if (usecase == NULL)
563 return -EINVAL;
564
565 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700566 if (usecase->type == PCM_CAPTURE)
567 snd_device = usecase->in_snd_device;
568 else
569 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800570 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500571 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700572 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700573 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800574
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800575 ALOGV("%s: exit", __func__);
576 return 0;
577}
578
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800579int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700580 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800581{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700582 int i, num_devices = 0;
583 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800584 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800585 if (snd_device < SND_DEVICE_MIN ||
586 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800587 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800588 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800589 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700590
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700591 platform_send_audio_calibration(adev->platform, snd_device);
592
vivek mehtade4849c2016-03-03 17:23:38 -0800593 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700594 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700595 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800596 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700597 }
598
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700599 /* due to the possibility of calibration overwrite between listen
600 and audio, notify sound trigger hal before audio calibration is sent */
601 audio_extn_sound_trigger_update_device_status(snd_device,
602 ST_EVENT_SND_DEVICE_BUSY);
603
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700604 if (audio_extn_spkr_prot_is_enabled())
605 audio_extn_spkr_prot_calib_cancel(adev);
606
zhaoyang yin4211fad2015-06-04 21:13:25 +0800607 audio_extn_dsm_feedback_enable(adev, snd_device, true);
608
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700609 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
610 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
611 audio_extn_spkr_prot_is_enabled()) {
612 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800613 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700614 }
615 if (audio_extn_spkr_prot_start_processing(snd_device)) {
616 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800617 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700618 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700619 } else if (platform_can_split_snd_device(snd_device,
620 &num_devices,
621 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700622 for (i = 0; i < num_devices; i++) {
623 enable_snd_device(adev, new_snd_devices[i]);
624 }
vivek mehtab6506412015-08-07 16:55:17 -0700625 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700626 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800627 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
628 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
629 ALOGE(" %s: Invalid sound device returned", __func__);
630 goto on_error;
631 }
Ed Tam70b5c142016-03-21 19:14:29 -0700632
Eric Laurent2e140aa2016-06-30 17:14:46 -0700633 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800634 audio_route_apply_and_update_path(adev->audio_route, device_name);
635 }
636on_success:
637 adev->snd_dev_ref_cnt[snd_device]++;
638 ret_val = 0;
639on_error:
640 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800641}
642
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800643int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700644 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800645{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700646 int i, num_devices = 0;
647 snd_device_t new_snd_devices[2];
648
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800649 if (snd_device < SND_DEVICE_MIN ||
650 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800651 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800652 return -EINVAL;
653 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700654 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
655 ALOGE("%s: device ref cnt is already 0", __func__);
656 return -EINVAL;
657 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800658 audio_extn_tfa_98xx_disable_speaker(snd_device);
659
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700660 adev->snd_dev_ref_cnt[snd_device]--;
661 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800662 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700663 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
664 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
665 audio_extn_spkr_prot_is_enabled()) {
666 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700667 } else if (platform_can_split_snd_device(snd_device,
668 &num_devices,
669 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700670 for (i = 0; i < num_devices; i++) {
671 disable_snd_device(adev, new_snd_devices[i]);
672 }
vivek mehtab6506412015-08-07 16:55:17 -0700673 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700674 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800675 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
676 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
677 ALOGE(" %s: Invalid sound device returned", __func__);
678 return -EINVAL;
679 }
680
Eric Laurent2e140aa2016-06-30 17:14:46 -0700681 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800682 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700683 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700684 audio_extn_sound_trigger_update_device_status(snd_device,
685 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700686 }
vivek mehtab6506412015-08-07 16:55:17 -0700687
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800688 return 0;
689}
690
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700691/*
692 legend:
693 uc - existing usecase
694 new_uc - new usecase
695 d1, d11, d2 - SND_DEVICE enums
696 a1, a2 - corresponding ANDROID device enums
697 B, B1, B2 - backend strings
698
699case 1
700 uc->dev d1 (a1) B1
701 new_uc->dev d1 (a1), d2 (a2) B1, B2
702
703 resolution: disable and enable uc->dev on d1
704
705case 2
706 uc->dev d1 (a1) B1
707 new_uc->dev d11 (a1) B1
708
709 resolution: need to switch uc since d1 and d11 are related
710 (e.g. speaker and voice-speaker)
711 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
712
713case 3
714 uc->dev d1 (a1) B1
715 new_uc->dev d2 (a2) B2
716
717 resolution: no need to switch uc
718
719case 4
720 uc->dev d1 (a1) B
721 new_uc->dev d2 (a2) B
722
723 resolution: disable enable uc-dev on d2 since backends match
724 we cannot enable two streams on two different devices if they
725 share the same backend. e.g. if offload is on speaker device using
726 QUAD_MI2S backend and a low-latency stream is started on voice-handset
727 using the same backend, offload must also be switched to voice-handset.
728
729case 5
730 uc->dev d1 (a1) B
731 new_uc->dev d1 (a1), d2 (a2) B
732
733 resolution: disable enable uc-dev on d2 since backends match
734 we cannot enable two streams on two different devices if they
735 share the same backend.
736
737case 6
738 uc->dev d1 a1 B1
739 new_uc->dev d2 a1 B2
740
741 resolution: no need to switch
742
743case 7
744
745 uc->dev d1 (a1), d2 (a2) B1, B2
746 new_uc->dev d1 B1
747
748 resolution: no need to switch
749
750*/
751static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
752 struct audio_usecase *new_uc,
753 snd_device_t new_snd_device)
754{
755 audio_devices_t a1 = uc->stream.out->devices;
756 audio_devices_t a2 = new_uc->stream.out->devices;
757
758 snd_device_t d1 = uc->out_snd_device;
759 snd_device_t d2 = new_snd_device;
760
761 // Treat as a special case when a1 and a2 are not disjoint
762 if ((a1 != a2) && (a1 & a2)) {
763 snd_device_t d3[2];
764 int num_devices = 0;
765 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
766 &num_devices,
767 d3);
768 if (ret < 0) {
769 if (ret != -ENOSYS) {
770 ALOGW("%s failed to split snd_device %d",
771 __func__,
772 popcount(a1) > 1 ? d1 : d2);
773 }
774 goto end;
775 }
776
777 // NB: case 7 is hypothetical and isn't a practical usecase yet.
778 // But if it does happen, we need to give priority to d2 if
779 // the combo devices active on the existing usecase share a backend.
780 // This is because we cannot have a usecase active on a combo device
781 // and a new usecase requests one device in this combo pair.
782 if (platform_check_backends_match(d3[0], d3[1])) {
783 return d2; // case 5
784 } else {
785 return d1; // case 1
786 }
787 } else {
788 if (platform_check_backends_match(d1, d2)) {
789 return d2; // case 2, 4
790 } else {
791 return d1; // case 6, 3
792 }
793 }
794
795end:
796 return d2; // return whatever was calculated before.
797}
798
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700799static void check_and_route_playback_usecases(struct audio_device *adev,
800 struct audio_usecase *uc_info,
801 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700802{
803 struct listnode *node;
804 struct audio_usecase *usecase;
805 bool switch_device[AUDIO_USECASE_MAX];
806 int i, num_uc_to_switch = 0;
807
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700808 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
809 uc_info,
810 snd_device);
David Linee3fe402017-03-13 10:00:42 -0700811
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700812 /*
813 * This function is to make sure that all the usecases that are active on
814 * the hardware codec backend are always routed to any one device that is
815 * handled by the hardware codec.
816 * For example, if low-latency and deep-buffer usecases are currently active
817 * on speaker and out_set_parameters(headset) is received on low-latency
818 * output, then we have to make sure deep-buffer is also switched to headset,
819 * because of the limitation that both the devices cannot be enabled
820 * at the same time as they share the same backend.
821 */
822 /* Disable all the usecases on the shared backend other than the
823 specified usecase */
824 for (i = 0; i < AUDIO_USECASE_MAX; i++)
825 switch_device[i] = false;
826
827 list_for_each(node, &adev->usecase_list) {
828 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700829 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
830 continue;
831
832 if (force_routing ||
833 (usecase->out_snd_device != snd_device &&
834 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
835 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700836 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
837 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700838 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700839 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700840 switch_device[usecase->id] = true;
841 num_uc_to_switch++;
842 }
843 }
844
845 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700846 list_for_each(node, &adev->usecase_list) {
847 usecase = node_to_item(node, struct audio_usecase, list);
848 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700849 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900850 }
851 }
852
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700853 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900854 list_for_each(node, &adev->usecase_list) {
855 usecase = node_to_item(node, struct audio_usecase, list);
856 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700857 d_device = derive_playback_snd_device(usecase, uc_info,
858 snd_device);
859 enable_snd_device(adev, d_device);
860 /* Update the out_snd_device before enabling the audio route */
861 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700862 }
863 }
864
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700865 /* Re-route all the usecases on the shared backend other than the
866 specified usecase to new snd devices */
867 list_for_each(node, &adev->usecase_list) {
868 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700869 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700870 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700871 }
872 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700873 }
874}
875
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700876static void check_and_route_capture_usecases(struct audio_device *adev,
877 struct audio_usecase *uc_info,
878 snd_device_t snd_device)
879{
880 struct listnode *node;
881 struct audio_usecase *usecase;
882 bool switch_device[AUDIO_USECASE_MAX];
883 int i, num_uc_to_switch = 0;
884
vivek mehta4ed66e62016-04-15 23:33:34 -0700885 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
886
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700887 /*
888 * This function is to make sure that all the active capture usecases
889 * are always routed to the same input sound device.
890 * For example, if audio-record and voice-call usecases are currently
891 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
892 * is received for voice call then we have to make sure that audio-record
893 * usecase is also switched to earpiece i.e. voice-dmic-ef,
894 * because of the limitation that two devices cannot be enabled
895 * at the same time if they share the same backend.
896 */
897 for (i = 0; i < AUDIO_USECASE_MAX; i++)
898 switch_device[i] = false;
899
900 list_for_each(node, &adev->usecase_list) {
901 usecase = node_to_item(node, struct audio_usecase, list);
902 if (usecase->type != PCM_PLAYBACK &&
903 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700904 usecase->in_snd_device != snd_device &&
905 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700906 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
907 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700908 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700909 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700910 switch_device[usecase->id] = true;
911 num_uc_to_switch++;
912 }
913 }
914
915 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700916 list_for_each(node, &adev->usecase_list) {
917 usecase = node_to_item(node, struct audio_usecase, list);
918 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700919 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700920 }
921 }
922
923 list_for_each(node, &adev->usecase_list) {
924 usecase = node_to_item(node, struct audio_usecase, list);
925 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700926 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700927 }
928 }
929
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700930 /* Re-route all the usecases on the shared backend other than the
931 specified usecase to new snd devices */
932 list_for_each(node, &adev->usecase_list) {
933 usecase = node_to_item(node, struct audio_usecase, list);
934 /* Update the in_snd_device only before enabling the audio route */
935 if (switch_device[usecase->id] ) {
936 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700937 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700938 }
939 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700940 }
941}
942
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800943/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700944static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800945{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700946 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700947 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800948
949 switch (channels) {
950 /*
951 * Do not handle stereo output in Multi-channel cases
952 * Stereo case is handled in normal playback path
953 */
954 case 6:
955 ALOGV("%s: HDMI supports 5.1", __func__);
956 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
957 break;
958 case 8:
959 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
960 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
961 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
962 break;
963 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700964 ALOGE("HDMI does not support multi channel playback");
965 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800966 break;
967 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700968 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800969}
970
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -0700971static ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
972 uint32_t *supported_sample_rates __unused,
973 uint32_t max_rates __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800974{
Haynes Mathew George569b7482017-05-08 14:44:27 -0700975 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
976 supported_sample_rates,
977 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800978#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -0700979 for (ssize_t i=0; i<count; i++) {
980 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
981 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800982 }
983#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -0700984 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800985}
986
Haynes Mathew George569b7482017-05-08 14:44:27 -0700987static int read_usb_sup_channel_masks(bool is_playback,
988 audio_channel_mask_t *supported_channel_masks,
989 uint32_t max_masks __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800990{
Haynes Mathew George569b7482017-05-08 14:44:27 -0700991 int channels = audio_extn_usb_get_max_channels(is_playback);
992 if (is_playback) {
993 supported_channel_masks[0] =
994 channels < 3 ? audio_channel_out_mask_from_count(channels) :
995 audio_channel_mask_for_index_assignment_from_count(channels);
996 } else {
997 supported_channel_masks[0] = audio_channel_in_mask_from_count(channels);
998 }
999 ALOGV("%s: %s supported ch %d", __func__,
1000 is_playback ? "P" : "C", channels);
1001 return 1;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001002}
1003
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001004static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001005 audio_format_t *supported_formats,
1006 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001007{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001008 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001009 switch (bitwidth) {
1010 case 24:
1011 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001012 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001013 break;
1014 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001015 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001016 break;
1017 case 16:
1018 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001019 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001020 break;
1021 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001022 ALOGV("%s: %s supported format %d", __func__,
1023 is_playback ? "P" : "C", bitwidth);
1024 return 1;
1025}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001026
Haynes Mathew George569b7482017-05-08 14:44:27 -07001027static int read_usb_sup_params_and_compare(bool is_playback,
1028 audio_format_t *format,
1029 audio_format_t *supported_formats,
1030 uint32_t max_formats,
1031 audio_channel_mask_t *mask,
1032 audio_channel_mask_t *supported_channel_masks,
1033 uint32_t max_masks,
1034 uint32_t *rate,
1035 uint32_t *supported_sample_rates,
1036 uint32_t max_rates) {
1037 int ret = 0;
1038 int num_formats;
1039 int num_masks;
1040 int num_rates;
1041 int i;
1042
1043 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1044 max_formats);
1045 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1046 max_masks);
1047 num_rates = read_usb_sup_sample_rates(is_playback,
1048 supported_sample_rates, max_rates);
1049
1050#define LUT(table, len, what, dflt) \
1051 for (i=0; i<len && (table[i] != what); i++); \
1052 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1053
1054 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1055 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1056 LUT(supported_sample_rates, num_rates, *rate, 0);
1057
1058#undef LUT
1059 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001060}
1061
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001062static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1063{
1064 struct audio_usecase *usecase;
1065 struct listnode *node;
1066
1067 list_for_each(node, &adev->usecase_list) {
1068 usecase = node_to_item(node, struct audio_usecase, list);
1069 if (usecase->type == VOICE_CALL) {
1070 ALOGV("%s: usecase id %d", __func__, usecase->id);
1071 return usecase->id;
1072 }
1073 }
1074 return USECASE_INVALID;
1075}
1076
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001077struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1078 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001079{
1080 struct audio_usecase *usecase;
1081 struct listnode *node;
1082
1083 list_for_each(node, &adev->usecase_list) {
1084 usecase = node_to_item(node, struct audio_usecase, list);
1085 if (usecase->id == uc_id)
1086 return usecase;
1087 }
1088 return NULL;
1089}
1090
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001091int select_devices(struct audio_device *adev,
1092 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001093{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001094 snd_device_t out_snd_device = SND_DEVICE_NONE;
1095 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001096 struct audio_usecase *usecase = NULL;
1097 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001098 struct audio_usecase *hfp_usecase = NULL;
1099 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001100 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001101 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001102
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001103 usecase = get_usecase_from_list(adev, uc_id);
1104 if (usecase == NULL) {
1105 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1106 return -EINVAL;
1107 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001108
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001109 if ((usecase->type == VOICE_CALL) ||
1110 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001111 out_snd_device = platform_get_output_snd_device(adev->platform,
1112 usecase->stream.out->devices);
1113 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001114 usecase->devices = usecase->stream.out->devices;
1115 } else {
1116 /*
1117 * If the voice call is active, use the sound devices of voice call usecase
1118 * so that it would not result any device switch. All the usecases will
1119 * be switched to new device when select_devices() is called for voice call
1120 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001121 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001122 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001123 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001124 vc_usecase = get_usecase_from_list(adev,
1125 get_voice_usecase_id_from_list(adev));
1126 if ((vc_usecase != NULL) &&
1127 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1128 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001129 in_snd_device = vc_usecase->in_snd_device;
1130 out_snd_device = vc_usecase->out_snd_device;
1131 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001132 } else if (audio_extn_hfp_is_active(adev)) {
1133 hfp_ucid = audio_extn_hfp_get_usecase();
1134 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1135 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1136 in_snd_device = hfp_usecase->in_snd_device;
1137 out_snd_device = hfp_usecase->out_snd_device;
1138 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001139 }
1140 if (usecase->type == PCM_PLAYBACK) {
1141 usecase->devices = usecase->stream.out->devices;
1142 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001143 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001144 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001145 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001146 if (usecase->stream.out == adev->primary_output &&
1147 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001148 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1149 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001150 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001151 select_devices(adev, adev->active_input->usecase);
1152 }
1153 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001154 } else if (usecase->type == PCM_CAPTURE) {
1155 usecase->devices = usecase->stream.in->device;
1156 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001157 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001158 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001159 if (adev->active_input &&
1160 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1161 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001162 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001163 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1164 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
1165 } else if (adev->primary_output) {
1166 out_device = adev->primary_output->devices;
1167 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001168 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001169 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001170 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001171 }
1172 }
1173
1174 if (out_snd_device == usecase->out_snd_device &&
1175 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001176 return 0;
1177 }
1178
Eric Laurent2bafff12016-03-17 12:17:23 -07001179 if (out_snd_device != SND_DEVICE_NONE &&
1180 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1181 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1182 __func__,
1183 use_case_table[uc_id],
1184 adev->last_logged_snd_device[uc_id][0],
1185 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1186 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1187 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1188 -1,
1189 out_snd_device,
1190 platform_get_snd_device_name(out_snd_device),
1191 platform_get_snd_device_acdb_id(out_snd_device));
1192 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1193 }
1194 if (in_snd_device != SND_DEVICE_NONE &&
1195 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1196 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1197 __func__,
1198 use_case_table[uc_id],
1199 adev->last_logged_snd_device[uc_id][1],
1200 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1201 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1202 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1203 -1,
1204 in_snd_device,
1205 platform_get_snd_device_name(in_snd_device),
1206 platform_get_snd_device_acdb_id(in_snd_device));
1207 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1208 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001209
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001210 /*
1211 * Limitation: While in call, to do a device switch we need to disable
1212 * and enable both RX and TX devices though one of them is same as current
1213 * device.
1214 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001215 if ((usecase->type == VOICE_CALL) &&
1216 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1217 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001218 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001219 /* Disable sidetone only if voice call already exists */
1220 if (voice_is_call_state_active(adev))
1221 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001222 }
1223
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001224 /* Disable current sound devices */
1225 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001226 disable_audio_route(adev, usecase);
1227 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001228 }
1229
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001230 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001231 disable_audio_route(adev, usecase);
1232 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001233 }
1234
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001235 /* Applicable only on the targets that has external modem.
1236 * New device information should be sent to modem before enabling
1237 * the devices to reduce in-call device switch time.
1238 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001239 if ((usecase->type == VOICE_CALL) &&
1240 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1241 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001242 status = platform_switch_voice_call_enable_device_config(adev->platform,
1243 out_snd_device,
1244 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001245 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001246
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001247 /* Enable new sound devices */
1248 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001249 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1250 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001251 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001252 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001253 }
1254
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001255 if (in_snd_device != SND_DEVICE_NONE) {
1256 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001257 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001258 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001259
Eric Laurentb23d5282013-05-14 15:27:20 -07001260 if (usecase->type == VOICE_CALL)
1261 status = platform_switch_voice_call_device_post(adev->platform,
1262 out_snd_device,
1263 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001264
sangwoo170731f2013-06-08 15:36:36 +09001265 usecase->in_snd_device = in_snd_device;
1266 usecase->out_snd_device = out_snd_device;
1267
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001268 audio_extn_tfa_98xx_set_mode();
1269
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001270 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001271
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001272 /* Applicable only on the targets that has external modem.
1273 * Enable device command should be sent to modem only after
1274 * enabling voice call mixer controls
1275 */
vivek mehta765eb642015-08-07 19:46:06 -07001276 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001277 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1278 out_snd_device,
1279 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001280 /* Enable sidetone only if voice call already exists */
1281 if (voice_is_call_state_active(adev))
1282 voice_set_sidetone(adev, out_snd_device, true);
1283 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001284
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001285 return status;
1286}
1287
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001288static int stop_input_stream(struct stream_in *in)
1289{
1290 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001291 struct audio_usecase *uc_info;
1292 struct audio_device *adev = in->dev;
1293
Eric Laurentc8400632013-02-14 19:04:54 -08001294 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001295
Eric Laurent994a6932013-07-17 11:51:42 -07001296 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001297 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001298 uc_info = get_usecase_from_list(adev, in->usecase);
1299 if (uc_info == NULL) {
1300 ALOGE("%s: Could not find the usecase (%d) in the list",
1301 __func__, in->usecase);
1302 return -EINVAL;
1303 }
1304
vivek mehta781065c2017-04-04 12:55:01 -07001305 /* Close in-call recording streams */
1306 voice_check_and_stop_incall_rec_usecase(adev, in);
1307
Eric Laurent150dbfe2013-02-27 14:31:02 -08001308 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001309 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001310
1311 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001312 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001313
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001314 list_remove(&uc_info->list);
1315 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001316
Eric Laurent994a6932013-07-17 11:51:42 -07001317 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001318 return ret;
1319}
1320
1321int start_input_stream(struct stream_in *in)
1322{
1323 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001324 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001325 struct audio_usecase *uc_info;
1326 struct audio_device *adev = in->dev;
1327
Eric Laurent994a6932013-07-17 11:51:42 -07001328 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001329
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001330 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1331 return -EIO;
1332
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001333 if (in->card_status == CARD_STATUS_OFFLINE ||
1334 adev->card_status == CARD_STATUS_OFFLINE) {
1335 ALOGW("in->card_status or adev->card_status offline, try again");
1336 ret = -EAGAIN;
1337 goto error_config;
1338 }
1339
vivek mehta781065c2017-04-04 12:55:01 -07001340 /* Check if source matches incall recording usecase criteria */
1341 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1342 if (ret)
1343 goto error_config;
1344 else
1345 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1346
Eric Laurentb23d5282013-05-14 15:27:20 -07001347 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001348 if (in->pcm_device_id < 0) {
1349 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1350 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001351 ret = -EINVAL;
1352 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001353 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001354
1355 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001356 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1357 uc_info->id = in->usecase;
1358 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001359 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001360 uc_info->devices = in->device;
1361 uc_info->in_snd_device = SND_DEVICE_NONE;
1362 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001363
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001364 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001365
1366 audio_extn_perf_lock_acquire();
1367
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001368 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001369
Eric Laurent0e46adf2016-12-16 12:49:24 -08001370 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001371 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001372 ALOGE("%s: pcm stream not ready", __func__);
1373 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001374 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001375 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001376 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001377 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1378 goto error_open;
1379 }
1380 } else {
1381 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1382 unsigned int pcm_open_retry_count = 0;
1383
1384 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1385 flags |= PCM_MMAP | PCM_NOIRQ;
1386 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1387 } else if (in->realtime) {
1388 flags |= PCM_MMAP | PCM_NOIRQ;
1389 }
1390
1391 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1392 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1393
1394 while (1) {
1395 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1396 flags, &in->config);
1397 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1398 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1399 if (in->pcm != NULL) {
1400 pcm_close(in->pcm);
1401 in->pcm = NULL;
1402 }
1403 if (pcm_open_retry_count-- == 0) {
1404 ret = -EIO;
1405 goto error_open;
1406 }
1407 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1408 continue;
1409 }
1410 break;
1411 }
1412
1413 ALOGV("%s: pcm_prepare", __func__);
1414 ret = pcm_prepare(in->pcm);
1415 if (ret < 0) {
1416 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001417 pcm_close(in->pcm);
1418 in->pcm = NULL;
1419 goto error_open;
1420 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001421 if (in->realtime) {
1422 ret = pcm_start(in->pcm);
1423 if (ret < 0) {
1424 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1425 pcm_close(in->pcm);
1426 in->pcm = NULL;
1427 goto error_open;
1428 }
1429 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001430 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001431 register_in_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001432 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001433 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001434
Eric Laurent0e46adf2016-12-16 12:49:24 -08001435 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001436
1437error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001438 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001439 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001440
1441error_config:
1442 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001443 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001444
1445 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001446}
1447
Eric Laurenta1478072015-09-21 17:21:52 -07001448void lock_input_stream(struct stream_in *in)
1449{
1450 pthread_mutex_lock(&in->pre_lock);
1451 pthread_mutex_lock(&in->lock);
1452 pthread_mutex_unlock(&in->pre_lock);
1453}
1454
1455void lock_output_stream(struct stream_out *out)
1456{
1457 pthread_mutex_lock(&out->pre_lock);
1458 pthread_mutex_lock(&out->lock);
1459 pthread_mutex_unlock(&out->pre_lock);
1460}
1461
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001462/* must be called with out->lock locked */
1463static int send_offload_cmd_l(struct stream_out* out, int command)
1464{
1465 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1466
1467 ALOGVV("%s %d", __func__, command);
1468
1469 cmd->cmd = command;
1470 list_add_tail(&out->offload_cmd_list, &cmd->node);
1471 pthread_cond_signal(&out->offload_cond);
1472 return 0;
1473}
1474
1475/* must be called iwth out->lock locked */
1476static void stop_compressed_output_l(struct stream_out *out)
1477{
1478 out->offload_state = OFFLOAD_STATE_IDLE;
1479 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001480 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001481 if (out->compr != NULL) {
1482 compress_stop(out->compr);
1483 while (out->offload_thread_blocked) {
1484 pthread_cond_wait(&out->cond, &out->lock);
1485 }
1486 }
1487}
1488
1489static void *offload_thread_loop(void *context)
1490{
1491 struct stream_out *out = (struct stream_out *) context;
1492 struct listnode *item;
1493
1494 out->offload_state = OFFLOAD_STATE_IDLE;
1495 out->playback_started = 0;
1496
1497 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1498 set_sched_policy(0, SP_FOREGROUND);
1499 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1500
1501 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001502 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001503 for (;;) {
1504 struct offload_cmd *cmd = NULL;
1505 stream_callback_event_t event;
1506 bool send_callback = false;
1507
1508 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1509 __func__, list_empty(&out->offload_cmd_list),
1510 out->offload_state);
1511 if (list_empty(&out->offload_cmd_list)) {
1512 ALOGV("%s SLEEPING", __func__);
1513 pthread_cond_wait(&out->offload_cond, &out->lock);
1514 ALOGV("%s RUNNING", __func__);
1515 continue;
1516 }
1517
1518 item = list_head(&out->offload_cmd_list);
1519 cmd = node_to_item(item, struct offload_cmd, node);
1520 list_remove(item);
1521
1522 ALOGVV("%s STATE %d CMD %d out->compr %p",
1523 __func__, out->offload_state, cmd->cmd, out->compr);
1524
1525 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1526 free(cmd);
1527 break;
1528 }
1529
1530 if (out->compr == NULL) {
1531 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001532 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001533 pthread_cond_signal(&out->cond);
1534 continue;
1535 }
1536 out->offload_thread_blocked = true;
1537 pthread_mutex_unlock(&out->lock);
1538 send_callback = false;
1539 switch(cmd->cmd) {
1540 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1541 compress_wait(out->compr, -1);
1542 send_callback = true;
1543 event = STREAM_CBK_EVENT_WRITE_READY;
1544 break;
1545 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001546 compress_next_track(out->compr);
1547 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001548 send_callback = true;
1549 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001550 /* Resend the metadata for next iteration */
1551 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001552 break;
1553 case OFFLOAD_CMD_DRAIN:
1554 compress_drain(out->compr);
1555 send_callback = true;
1556 event = STREAM_CBK_EVENT_DRAIN_READY;
1557 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001558 case OFFLOAD_CMD_ERROR:
1559 send_callback = true;
1560 event = STREAM_CBK_EVENT_ERROR;
1561 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001562 default:
1563 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1564 break;
1565 }
Eric Laurenta1478072015-09-21 17:21:52 -07001566 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001567 out->offload_thread_blocked = false;
1568 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001569 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001570 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001571 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001572 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001573 free(cmd);
1574 }
1575
1576 pthread_cond_signal(&out->cond);
1577 while (!list_empty(&out->offload_cmd_list)) {
1578 item = list_head(&out->offload_cmd_list);
1579 list_remove(item);
1580 free(node_to_item(item, struct offload_cmd, node));
1581 }
1582 pthread_mutex_unlock(&out->lock);
1583
1584 return NULL;
1585}
1586
1587static int create_offload_callback_thread(struct stream_out *out)
1588{
1589 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1590 list_init(&out->offload_cmd_list);
1591 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1592 offload_thread_loop, out);
1593 return 0;
1594}
1595
1596static int destroy_offload_callback_thread(struct stream_out *out)
1597{
Eric Laurenta1478072015-09-21 17:21:52 -07001598 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001599 stop_compressed_output_l(out);
1600 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1601
1602 pthread_mutex_unlock(&out->lock);
1603 pthread_join(out->offload_thread, (void **) NULL);
1604 pthread_cond_destroy(&out->offload_cond);
1605
1606 return 0;
1607}
1608
Eric Laurent07eeafd2013-10-06 12:52:49 -07001609static bool allow_hdmi_channel_config(struct audio_device *adev)
1610{
1611 struct listnode *node;
1612 struct audio_usecase *usecase;
1613 bool ret = true;
1614
1615 list_for_each(node, &adev->usecase_list) {
1616 usecase = node_to_item(node, struct audio_usecase, list);
1617 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1618 /*
1619 * If voice call is already existing, do not proceed further to avoid
1620 * disabling/enabling both RX and TX devices, CSD calls, etc.
1621 * Once the voice call done, the HDMI channels can be configured to
1622 * max channels of remaining use cases.
1623 */
1624 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001625 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001626 __func__);
1627 ret = false;
1628 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001629 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1630 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001631 "no change in HDMI channels", __func__);
1632 ret = false;
1633 break;
1634 }
1635 }
1636 }
1637 return ret;
1638}
1639
1640static int check_and_set_hdmi_channels(struct audio_device *adev,
1641 unsigned int channels)
1642{
1643 struct listnode *node;
1644 struct audio_usecase *usecase;
1645
1646 /* Check if change in HDMI channel config is allowed */
1647 if (!allow_hdmi_channel_config(adev))
1648 return 0;
1649
1650 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001651 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001652 return 0;
1653 }
1654
1655 platform_set_hdmi_channels(adev->platform, channels);
1656 adev->cur_hdmi_channels = channels;
1657
1658 /*
1659 * Deroute all the playback streams routed to HDMI so that
1660 * the back end is deactivated. Note that backend will not
1661 * be deactivated if any one stream is connected to it.
1662 */
1663 list_for_each(node, &adev->usecase_list) {
1664 usecase = node_to_item(node, struct audio_usecase, list);
1665 if (usecase->type == PCM_PLAYBACK &&
1666 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001667 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001668 }
1669 }
1670
1671 /*
1672 * Enable all the streams disabled above. Now the HDMI backend
1673 * will be activated with new channel configuration
1674 */
1675 list_for_each(node, &adev->usecase_list) {
1676 usecase = node_to_item(node, struct audio_usecase, list);
1677 if (usecase->type == PCM_PLAYBACK &&
1678 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001679 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001680 }
1681 }
1682
1683 return 0;
1684}
1685
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001686static int stop_output_stream(struct stream_out *out)
1687{
1688 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001689 struct audio_usecase *uc_info;
1690 struct audio_device *adev = out->dev;
1691
Eric Laurent994a6932013-07-17 11:51:42 -07001692 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001693 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001694 uc_info = get_usecase_from_list(adev, out->usecase);
1695 if (uc_info == NULL) {
1696 ALOGE("%s: Could not find the usecase (%d) in the list",
1697 __func__, out->usecase);
1698 return -EINVAL;
1699 }
1700
Haynes Mathew George41f86652014-06-17 14:22:15 -07001701 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1702 if (adev->visualizer_stop_output != NULL)
1703 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1704 if (adev->offload_effects_stop_output != NULL)
1705 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1706 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001707
Eric Laurent150dbfe2013-02-27 14:31:02 -08001708 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001709 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001710
1711 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001712 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001713
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001714 list_remove(&uc_info->list);
1715 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001716
Eric Laurent0499d4f2014-08-25 22:39:29 -05001717 audio_extn_extspk_update(adev->extspk);
1718
Eric Laurent07eeafd2013-10-06 12:52:49 -07001719 /* Must be called after removing the usecase from list */
1720 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1721 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1722
Eric Laurent994a6932013-07-17 11:51:42 -07001723 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001724 return ret;
1725}
1726
1727int start_output_stream(struct stream_out *out)
1728{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001729 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001730 struct audio_usecase *uc_info;
1731 struct audio_device *adev = out->dev;
1732
Eric Laurent994a6932013-07-17 11:51:42 -07001733 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001734 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001735
1736 if (out->card_status == CARD_STATUS_OFFLINE ||
1737 adev->card_status == CARD_STATUS_OFFLINE) {
1738 ALOGW("out->card_status or adev->card_status offline, try again");
1739 ret = -EAGAIN;
1740 goto error_config;
1741 }
1742
Eric Laurentb23d5282013-05-14 15:27:20 -07001743 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001744 if (out->pcm_device_id < 0) {
1745 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1746 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001747 ret = -EINVAL;
1748 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001749 }
1750
1751 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1752 uc_info->id = out->usecase;
1753 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001754 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001755 uc_info->devices = out->devices;
1756 uc_info->in_snd_device = SND_DEVICE_NONE;
1757 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001758
Eric Laurent07eeafd2013-10-06 12:52:49 -07001759 /* This must be called before adding this usecase to the list */
1760 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1761 check_and_set_hdmi_channels(adev, out->config.channels);
1762
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001763 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001764
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001765 audio_extn_perf_lock_acquire();
1766
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001767 select_devices(adev, out->usecase);
1768
Eric Laurent0499d4f2014-08-25 22:39:29 -05001769 audio_extn_extspk_update(adev->extspk);
1770
Andy Hung31aca912014-03-20 17:14:59 -07001771 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001772 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001773 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1774 out->pcm = NULL;
1775 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1776 COMPRESS_IN, &out->compr_config);
1777 if (out->compr && !is_compress_ready(out->compr)) {
1778 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1779 compress_close(out->compr);
1780 out->compr = NULL;
1781 ret = -EIO;
1782 goto error_open;
1783 }
1784 if (out->offload_callback)
1785 compress_nonblock(out->compr, out->non_blocking);
1786
1787 if (adev->visualizer_start_output != NULL)
1788 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1789 if (adev->offload_effects_start_output != NULL)
1790 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
1791 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001792 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001793 ALOGE("%s: pcm stream not ready", __func__);
1794 goto error_open;
1795 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001796 ret = pcm_start(out->pcm);
1797 if (ret < 0) {
1798 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1799 goto error_open;
1800 }
1801 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07001802 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001803 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001804
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001805 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1806 flags |= PCM_MMAP | PCM_NOIRQ;
1807 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001808 } else if (out->realtime) {
1809 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07001810 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001811
1812 while (1) {
1813 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1814 flags, &out->config);
1815 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1816 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1817 if (out->pcm != NULL) {
1818 pcm_close(out->pcm);
1819 out->pcm = NULL;
1820 }
1821 if (pcm_open_retry_count-- == 0) {
1822 ret = -EIO;
1823 goto error_open;
1824 }
1825 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1826 continue;
1827 }
1828 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001829 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001830 ALOGV("%s: pcm_prepare", __func__);
1831 if (pcm_is_ready(out->pcm)) {
1832 ret = pcm_prepare(out->pcm);
1833 if (ret < 0) {
1834 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1835 pcm_close(out->pcm);
1836 out->pcm = NULL;
1837 goto error_open;
1838 }
1839 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001840 if (out->realtime) {
1841 ret = pcm_start(out->pcm);
1842 if (ret < 0) {
1843 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1844 pcm_close(out->pcm);
1845 out->pcm = NULL;
1846 goto error_open;
1847 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001848 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001849 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001850 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001851 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001852 audio_extn_tfa_98xx_enable_speaker();
1853
Eric Laurent994a6932013-07-17 11:51:42 -07001854 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001855 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001856error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001857 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001858 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001859error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001860 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001861}
1862
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001863static int check_input_parameters(uint32_t sample_rate,
1864 audio_format_t format,
1865 int channel_count)
1866{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001867 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
1868 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
1869 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED)) {
vivek mehtadae44712015-07-27 14:13:18 -07001870 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1871 return -EINVAL;
1872 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001873
vivek mehtadae44712015-07-27 14:13:18 -07001874 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > MAX_CHANNEL_COUNT)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001875 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
vivek mehtadae44712015-07-27 14:13:18 -07001876 channel_count, MIN_CHANNEL_COUNT, MAX_CHANNEL_COUNT);
1877 return -EINVAL;
1878 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001879
1880 switch (sample_rate) {
1881 case 8000:
1882 case 11025:
1883 case 12000:
1884 case 16000:
1885 case 22050:
1886 case 24000:
1887 case 32000:
1888 case 44100:
1889 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001890 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001891 break;
1892 default:
vivek mehtadae44712015-07-27 14:13:18 -07001893 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001894 return -EINVAL;
1895 }
1896
1897 return 0;
1898}
1899
1900static size_t get_input_buffer_size(uint32_t sample_rate,
1901 audio_format_t format,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001902 int channel_count,
1903 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001904{
1905 size_t size = 0;
1906
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001907 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1908 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001909
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001910 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001911 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001912 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07001913
1914 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001915
Glenn Kasten4f993392014-05-14 07:30:48 -07001916 /* make sure the size is multiple of 32 bytes
1917 * At 48 kHz mono 16-bit PCM:
1918 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1919 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1920 */
1921 size += 0x1f;
1922 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001923
1924 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001925}
1926
1927static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1928{
1929 struct stream_out *out = (struct stream_out *)stream;
1930
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001931 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001932}
1933
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001934static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001935{
1936 return -ENOSYS;
1937}
1938
1939static size_t out_get_buffer_size(const struct audio_stream *stream)
1940{
1941 struct stream_out *out = (struct stream_out *)stream;
1942
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001943 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1944 return out->compr_config.fragment_size;
1945 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001946 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07001947 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001948}
1949
1950static uint32_t out_get_channels(const struct audio_stream *stream)
1951{
1952 struct stream_out *out = (struct stream_out *)stream;
1953
1954 return out->channel_mask;
1955}
1956
1957static audio_format_t out_get_format(const struct audio_stream *stream)
1958{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001959 struct stream_out *out = (struct stream_out *)stream;
1960
1961 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001962}
1963
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001964static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001965{
1966 return -ENOSYS;
1967}
1968
1969static int out_standby(struct audio_stream *stream)
1970{
1971 struct stream_out *out = (struct stream_out *)stream;
1972 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08001973 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001974
Eric Laurent994a6932013-07-17 11:51:42 -07001975 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001976 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001977
Eric Laurenta1478072015-09-21 17:21:52 -07001978 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001979 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001980 if (adev->adm_deregister_stream)
1981 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001982 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001983 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001984 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1985 if (out->pcm) {
1986 pcm_close(out->pcm);
1987 out->pcm = NULL;
1988 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001989 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001990 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08001991 out->playback_started = false;
1992 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001993 } else {
1994 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001995 out->gapless_mdata.encoder_delay = 0;
1996 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001997 if (out->compr != NULL) {
1998 compress_close(out->compr);
1999 out->compr = NULL;
2000 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002001 }
Phil Burkbc991042017-02-24 08:06:44 -08002002 if (do_stop) {
2003 stop_output_stream(out);
2004 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002005 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002006 }
2007 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002008 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002009 return 0;
2010}
2011
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002012static int out_on_error(struct audio_stream *stream)
2013{
2014 struct stream_out *out = (struct stream_out *)stream;
2015 struct audio_device *adev = out->dev;
2016 bool do_standby = false;
2017
2018 lock_output_stream(out);
2019 if (!out->standby) {
2020 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2021 stop_compressed_output_l(out);
2022 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2023 } else
2024 do_standby = true;
2025 }
2026 pthread_mutex_unlock(&out->lock);
2027
2028 if (do_standby)
2029 return out_standby(&out->stream.common);
2030
2031 return 0;
2032}
2033
Andy Hung7401c7c2016-09-21 12:41:21 -07002034static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002035{
Andy Hung7401c7c2016-09-21 12:41:21 -07002036 struct stream_out *out = (struct stream_out *)stream;
2037
2038 // We try to get the lock for consistency,
2039 // but it isn't necessary for these variables.
2040 // If we're not in standby, we may be blocked on a write.
2041 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2042 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2043 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2044
2045 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002046 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002047 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002048
2049 // dump error info
2050 (void)error_log_dump(
2051 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hungfc044e12017-03-20 09:24:22 -07002052 // dump power info (out->power_log may be null)
Andy Hung62c9b882017-03-22 16:43:42 -07002053 (void)power_log_dump(
2054 out->power_log, fd, " " /* prefix */, POWER_LOG_LINES, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002055 return 0;
2056}
2057
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002058static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2059{
2060 int ret = 0;
2061 char value[32];
2062 struct compr_gapless_mdata tmp_mdata;
2063
2064 if (!out || !parms) {
2065 return -EINVAL;
2066 }
2067
2068 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2069 if (ret >= 0) {
2070 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2071 } else {
2072 return -EINVAL;
2073 }
2074
2075 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2076 if (ret >= 0) {
2077 tmp_mdata.encoder_padding = atoi(value);
2078 } else {
2079 return -EINVAL;
2080 }
2081
2082 out->gapless_mdata = tmp_mdata;
2083 out->send_new_metadata = 1;
2084 ALOGV("%s new encoder delay %u and padding %u", __func__,
2085 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2086
2087 return 0;
2088}
2089
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002090static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2091{
2092 return out == adev->primary_output || out == adev->voice_tx_output;
2093}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002094
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002095static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2096{
2097 struct stream_out *out = (struct stream_out *)stream;
2098 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002099 struct audio_usecase *usecase;
2100 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002101 struct str_parms *parms;
2102 char value[32];
2103 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002104 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002105 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002106
Eric Laurent2e140aa2016-06-30 17:14:46 -07002107 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002108 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002109 parms = str_parms_create_str(kvpairs);
2110 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2111 if (ret >= 0) {
2112 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07002113 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002114 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002115
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002116 /*
2117 * When HDMI cable is unplugged the music playback is paused and
2118 * the policy manager sends routing=0. But the audioflinger
2119 * continues to write data until standby time (3sec).
2120 * As the HDMI core is turned off, the write gets blocked.
2121 * Avoid this by routing audio to speaker until standby.
2122 */
2123 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2124 val == AUDIO_DEVICE_NONE) {
2125 val = AUDIO_DEVICE_OUT_SPEAKER;
2126 }
2127
2128 /*
2129 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002130 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002131 * the select_devices(). But how do we undo this?
2132 *
2133 * For example, music playback is active on headset (deep-buffer usecase)
2134 * and if we go to ringtones and select a ringtone, low-latency usecase
2135 * will be started on headset+speaker. As we can't enable headset+speaker
2136 * and headset devices at the same time, select_devices() switches the music
2137 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2138 * So when the ringtone playback is completed, how do we undo the same?
2139 *
2140 * We are relying on the out_set_parameters() call on deep-buffer output,
2141 * once the ringtone playback is ended.
2142 * NOTE: We should not check if the current devices are same as new devices.
2143 * Because select_devices() must be called to switch back the music
2144 * playback to headset.
2145 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002146 audio_devices_t new_dev = val;
2147 if (new_dev != AUDIO_DEVICE_NONE) {
2148 bool same_dev = out->devices == new_dev;
2149 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002150
Eric Laurenta7657192014-10-09 21:09:33 -07002151 if (output_drives_call(adev, out)) {
2152 if (!voice_is_in_call(adev)) {
2153 if (adev->mode == AUDIO_MODE_IN_CALL) {
2154 adev->current_call_output = out;
2155 ret = voice_start_call(adev);
2156 }
2157 } else {
2158 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002159 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002160 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002161 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002162
2163 if (!out->standby) {
2164 if (!same_dev) {
2165 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002166 // inform adm before actual routing to prevent glitches.
2167 if (adev->adm_on_routing_change) {
2168 adev->adm_on_routing_change(adev->adm_data,
2169 out->handle);
2170 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002171 }
2172 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002173 audio_extn_tfa_98xx_update();
vivek mehta0d3637a2016-07-24 09:32:02 -07002174 }
2175
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002176 }
2177
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002178 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002179 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002180
2181 /*handles device and call state changes*/
2182 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002183 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002184
2185 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2186 parse_compress_metadata(out, parms);
2187 }
2188
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002189 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002190 ALOGV("%s: exit: code(%d)", __func__, status);
2191 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002192}
2193
Haynes Mathew George569b7482017-05-08 14:44:27 -07002194static bool stream_get_parameter_channels(struct str_parms *query,
2195 struct str_parms *reply,
2196 audio_channel_mask_t *supported_channel_masks) {
2197 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002198 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002199 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002200 size_t i, j;
2201
2202 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2203 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002204 value[0] = '\0';
2205 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002206 while (supported_channel_masks[i] != 0) {
2207 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2208 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002209 if (!first) {
2210 strcat(value, "|");
2211 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002212 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002213 first = false;
2214 break;
2215 }
2216 }
2217 i++;
2218 }
2219 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002220 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002221 return ret >= 0;
2222}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002223
Haynes Mathew George569b7482017-05-08 14:44:27 -07002224static bool stream_get_parameter_formats(struct str_parms *query,
2225 struct str_parms *reply,
2226 audio_format_t *supported_formats) {
2227 int ret = -1;
2228 char value[256];
2229 int i;
2230
2231 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2232 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002233 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002234 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002235 case AUDIO_FORMAT_PCM_16_BIT:
2236 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2237 break;
2238 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2239 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2240 break;
2241 case AUDIO_FORMAT_PCM_32_BIT:
2242 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2243 break;
2244 default:
2245 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002246 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002247 break;
2248 }
2249 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002250 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002251 return ret >= 0;
2252}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002253
Haynes Mathew George569b7482017-05-08 14:44:27 -07002254static bool stream_get_parameter_rates(struct str_parms *query,
2255 struct str_parms *reply,
2256 uint32_t *supported_sample_rates) {
2257
2258 int i;
2259 char value[256];
2260 int ret = -1;
2261 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2262 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002263 value[0] = '\0';
2264 i=0;
2265 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002266 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002267 int avail = sizeof(value) - cursor;
2268 ret = snprintf(value + cursor, avail, "%s%d",
2269 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002270 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002271 if (ret < 0 || ret >= avail) {
2272 // if cursor is at the last element of the array
2273 // overwrite with \0 is duplicate work as
2274 // snprintf already put a \0 in place.
2275 // else
2276 // we had space to write the '|' at value[cursor]
2277 // (which will be overwritten) or no space to fill
2278 // the first element (=> cursor == 0)
2279 value[cursor] = '\0';
2280 break;
2281 }
2282 cursor += ret;
2283 ++i;
2284 }
2285 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2286 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002287 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002288 return ret >= 0;
2289}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002290
Haynes Mathew George569b7482017-05-08 14:44:27 -07002291static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2292{
2293 struct stream_out *out = (struct stream_out *)stream;
2294 struct str_parms *query = str_parms_create_str(keys);
2295 char *str;
2296 struct str_parms *reply = str_parms_create();
2297 bool replied = false;
2298 ALOGV("%s: enter: keys - %s", __func__, keys);
2299
2300 replied |= stream_get_parameter_channels(query, reply,
2301 &out->supported_channel_masks[0]);
2302 replied |= stream_get_parameter_formats(query, reply,
2303 &out->supported_formats[0]);
2304 replied |= stream_get_parameter_rates(query, reply,
2305 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002306 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002307 str = str_parms_to_str(reply);
2308 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002309 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002310 }
2311 str_parms_destroy(query);
2312 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002313 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002314 return str;
2315}
2316
2317static uint32_t out_get_latency(const struct audio_stream_out *stream)
2318{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002319 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002320 struct stream_out *out = (struct stream_out *)stream;
2321
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002322 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2323 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002324 else if ((out->realtime) ||
2325 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002326 // since the buffer won't be filled up faster than realtime,
2327 // return a smaller number
2328 period_ms = (out->af_period_multiplier * out->config.period_size *
2329 1000) / (out->config.rate);
2330 hw_delay = platform_render_latency(out->usecase)/1000;
2331 return period_ms + hw_delay;
2332 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002333
2334 return (out->config.period_count * out->config.period_size * 1000) /
2335 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002336}
2337
2338static int out_set_volume(struct audio_stream_out *stream, float left,
2339 float right)
2340{
Eric Laurenta9024de2013-04-04 09:19:12 -07002341 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002342 int volume[2];
2343
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002344 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002345 /* only take left channel into account: the API is for stereo anyway */
2346 out->muted = (left == 0.0f);
2347 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002348 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2349 const char *mixer_ctl_name = "Compress Playback Volume";
2350 struct audio_device *adev = out->dev;
2351 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002352 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2353 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002354 /* try with the control based on device id */
2355 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2356 PCM_PLAYBACK);
2357 char ctl_name[128] = {0};
2358 snprintf(ctl_name, sizeof(ctl_name),
2359 "Compress Playback %d Volume", pcm_device_id);
2360 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2361 if (!ctl) {
2362 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2363 return -EINVAL;
2364 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002365 }
2366 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2367 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2368 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2369 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002370 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002371
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002372 return -ENOSYS;
2373}
2374
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002375// note: this call is safe only if the stream_cb is
2376// removed first in close_output_stream (as is done now).
2377static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2378{
2379 if (!stream || !parms)
2380 return;
2381
2382 struct stream_out *out = (struct stream_out *)stream;
2383 struct audio_device *adev = out->dev;
2384
2385 card_status_t status;
2386 int card;
2387 if (parse_snd_card_status(parms, &card, &status) < 0)
2388 return;
2389
2390 pthread_mutex_lock(&adev->lock);
2391 bool valid_cb = (card == adev->snd_card);
2392 pthread_mutex_unlock(&adev->lock);
2393
2394 if (!valid_cb)
2395 return;
2396
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002397 lock_output_stream(out);
2398 if (out->card_status != status)
2399 out->card_status = status;
2400 pthread_mutex_unlock(&out->lock);
2401
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002402 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2403 use_case_table[out->usecase],
2404 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2405
2406 if (status == CARD_STATUS_OFFLINE)
2407 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002408
2409 return;
2410}
2411
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002412#ifdef NO_AUDIO_OUT
2413static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002414 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002415{
2416 struct stream_out *out = (struct stream_out *)stream;
2417
2418 /* No Output device supported other than BT for playback.
2419 * Sleep for the amount of buffer duration
2420 */
Eric Laurenta1478072015-09-21 17:21:52 -07002421 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002422 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2423 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002424 out_get_sample_rate(&out->stream.common));
2425 pthread_mutex_unlock(&out->lock);
2426 return bytes;
2427}
2428#endif
2429
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002430static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2431 size_t bytes)
2432{
2433 struct stream_out *out = (struct stream_out *)stream;
2434 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002435 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002436 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002437
Eric Laurenta1478072015-09-21 17:21:52 -07002438 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002439 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07002440 const size_t frame_size = audio_stream_out_frame_size(stream);
2441 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002442
Eric Laurent0e46adf2016-12-16 12:49:24 -08002443 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2444 error_code = ERROR_CODE_WRITE;
2445 goto exit;
2446 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002447 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002448 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002449 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002450 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002451 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002452 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002453 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002454 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002455 goto exit;
2456 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002457
2458 if (last_known_cal_step != -1) {
2459 ALOGD("%s: retry previous failed cal level set", __func__);
2460 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2461 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002462 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002463
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002464 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002465 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002466 if (out->send_new_metadata) {
2467 ALOGVV("send new gapless metadata");
2468 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2469 out->send_new_metadata = 0;
2470 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002471 unsigned int avail;
2472 struct timespec tstamp;
2473 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2474 /* Do not limit write size if the available frames count is unknown */
2475 if (ret != 0) {
2476 avail = bytes;
2477 }
2478 if (avail == 0) {
2479 ret = 0;
2480 } else {
2481 if (avail > bytes) {
2482 avail = bytes;
2483 }
2484 ret = compress_write(out->compr, buffer, avail);
2485 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2486 __func__, avail, ret);
2487 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002488
Eric Laurent6e895242013-09-05 16:10:57 -07002489 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002490 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2491 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002492 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002493 compress_start(out->compr);
2494 out->playback_started = 1;
2495 out->offload_state = OFFLOAD_STATE_PLAYING;
2496 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002497 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002498 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002499 } else {
2500 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002501 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002502 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002503 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002504 return ret;
2505 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002506 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002507 if (out->pcm) {
2508 if (out->muted)
2509 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002510
Eric Laurent0e46adf2016-12-16 12:49:24 -08002511 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002512
Haynes Mathew George03c40102016-01-29 17:57:48 -08002513 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2514 out->config.rate;
2515 request_out_focus(out, ns);
2516
2517 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2518 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002519 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002520 else
2521 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002522
Haynes Mathew George03c40102016-01-29 17:57:48 -08002523 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002524 } else {
2525 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002526 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002527 }
2528
2529exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002530 // For PCM we always consume the buffer and return #bytes regardless of ret.
2531 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07002532 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07002533 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002534 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07002535
2536 // only get time if needed for logging, as it is a system call on 32 bit devices.
2537 // TODO: Consider always enabling for 64 bit vDSO using compile time check on __LP64__.
2538 const int64_t now_ns = out->power_log != 0 || (ret != 0 && out->error_log != 0)
2539 ? audio_utils_get_real_time_ns() : 0;
Andy Hungfc044e12017-03-20 09:24:22 -07002540
Andy Hung7401c7c2016-09-21 12:41:21 -07002541 if (ret != 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002542 error_log_log(out->error_log, error_code, now_ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002543 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2544 ALOGE_IF(out->pcm != NULL,
2545 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07002546 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002547 // usleep not guaranteed for values over 1 second but we don't limit here.
2548 }
2549 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002550
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002551 pthread_mutex_unlock(&out->lock);
2552
2553 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002554 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002555 if (sleeptime_us != 0)
2556 usleep(sleeptime_us);
Andy Hungfc044e12017-03-20 09:24:22 -07002557 } else {
2558 // only log if the data is properly written (out->power_log may be null)
Andy Hung8e7f03f2017-06-12 14:05:22 -07002559 power_log_log(out->power_log, buffer, frames, now_ns);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002560 }
2561 return bytes;
2562}
2563
2564static int out_get_render_position(const struct audio_stream_out *stream,
2565 uint32_t *dsp_frames)
2566{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002567 struct stream_out *out = (struct stream_out *)stream;
2568 *dsp_frames = 0;
2569 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002570 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002571 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002572 unsigned long frames = 0;
2573 // TODO: check return value
2574 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2575 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002576 ALOGVV("%s rendered frames %d sample_rate %d",
2577 __func__, *dsp_frames, out->sample_rate);
2578 }
2579 pthread_mutex_unlock(&out->lock);
2580 return 0;
2581 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002582 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002583}
2584
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002585static int out_add_audio_effect(const struct audio_stream *stream __unused,
2586 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002587{
2588 return 0;
2589}
2590
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002591static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2592 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002593{
2594 return 0;
2595}
2596
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002597static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2598 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002599{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002600 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002601}
2602
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002603static int out_get_presentation_position(const struct audio_stream_out *stream,
2604 uint64_t *frames, struct timespec *timestamp)
2605{
2606 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002607 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07002608 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002609
Eric Laurenta1478072015-09-21 17:21:52 -07002610 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002611
Eric Laurent949a0892013-09-20 09:20:13 -07002612 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2613 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002614 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002615 compress_get_tstamp(out->compr, &dsp_frames,
2616 &out->sample_rate);
2617 ALOGVV("%s rendered frames %ld sample_rate %d",
2618 __func__, dsp_frames, out->sample_rate);
2619 *frames = dsp_frames;
2620 ret = 0;
2621 /* this is the best we can do */
2622 clock_gettime(CLOCK_MONOTONIC, timestamp);
2623 }
2624 } else {
2625 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002626 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002627 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2628 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002629 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002630 // This adjustment accounts for buffering after app processor.
2631 // It is based on estimated DSP latency per use case, rather than exact.
2632 signed_frames -=
2633 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2634
Eric Laurent949a0892013-09-20 09:20:13 -07002635 // It would be unusual for this value to be negative, but check just in case ...
2636 if (signed_frames >= 0) {
2637 *frames = signed_frames;
2638 ret = 0;
2639 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002640 }
2641 }
2642 }
2643
2644 pthread_mutex_unlock(&out->lock);
2645
2646 return ret;
2647}
2648
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002649static int out_set_callback(struct audio_stream_out *stream,
2650 stream_callback_t callback, void *cookie)
2651{
2652 struct stream_out *out = (struct stream_out *)stream;
2653
2654 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002655 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002656 out->offload_callback = callback;
2657 out->offload_cookie = cookie;
2658 pthread_mutex_unlock(&out->lock);
2659 return 0;
2660}
2661
2662static int out_pause(struct audio_stream_out* stream)
2663{
2664 struct stream_out *out = (struct stream_out *)stream;
2665 int status = -ENOSYS;
2666 ALOGV("%s", __func__);
2667 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002668 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002669 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2670 status = compress_pause(out->compr);
2671 out->offload_state = OFFLOAD_STATE_PAUSED;
2672 }
2673 pthread_mutex_unlock(&out->lock);
2674 }
2675 return status;
2676}
2677
2678static int out_resume(struct audio_stream_out* stream)
2679{
2680 struct stream_out *out = (struct stream_out *)stream;
2681 int status = -ENOSYS;
2682 ALOGV("%s", __func__);
2683 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2684 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002685 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002686 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2687 status = compress_resume(out->compr);
2688 out->offload_state = OFFLOAD_STATE_PLAYING;
2689 }
2690 pthread_mutex_unlock(&out->lock);
2691 }
2692 return status;
2693}
2694
2695static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2696{
2697 struct stream_out *out = (struct stream_out *)stream;
2698 int status = -ENOSYS;
2699 ALOGV("%s", __func__);
2700 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002701 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002702 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2703 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2704 else
2705 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2706 pthread_mutex_unlock(&out->lock);
2707 }
2708 return status;
2709}
2710
2711static int out_flush(struct audio_stream_out* stream)
2712{
2713 struct stream_out *out = (struct stream_out *)stream;
2714 ALOGV("%s", __func__);
2715 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002716 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002717 stop_compressed_output_l(out);
2718 pthread_mutex_unlock(&out->lock);
2719 return 0;
2720 }
2721 return -ENOSYS;
2722}
2723
Eric Laurent0e46adf2016-12-16 12:49:24 -08002724static int out_stop(const struct audio_stream_out* stream)
2725{
2726 struct stream_out *out = (struct stream_out *)stream;
2727 struct audio_device *adev = out->dev;
2728 int ret = -ENOSYS;
2729
2730 ALOGV("%s", __func__);
2731 pthread_mutex_lock(&adev->lock);
2732 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2733 out->playback_started && out->pcm != NULL) {
2734 pcm_stop(out->pcm);
2735 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08002736 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002737 }
2738 pthread_mutex_unlock(&adev->lock);
2739 return ret;
2740}
2741
2742static int out_start(const struct audio_stream_out* stream)
2743{
2744 struct stream_out *out = (struct stream_out *)stream;
2745 struct audio_device *adev = out->dev;
2746 int ret = -ENOSYS;
2747
2748 ALOGV("%s", __func__);
2749 pthread_mutex_lock(&adev->lock);
2750 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2751 !out->playback_started && out->pcm != NULL) {
2752 ret = start_output_stream(out);
2753 if (ret == 0) {
2754 out->playback_started = true;
2755 }
2756 }
2757 pthread_mutex_unlock(&adev->lock);
2758 return ret;
2759}
2760
Phil Burkbc991042017-02-24 08:06:44 -08002761/*
2762 * Modify config->period_count based on min_size_frames
2763 */
2764static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
2765{
2766 int periodCountRequested = (min_size_frames + config->period_size - 1)
2767 / config->period_size;
2768 int periodCount = MMAP_PERIOD_COUNT_MIN;
2769
2770 ALOGV("%s original config.period_size = %d config.period_count = %d",
2771 __func__, config->period_size, config->period_count);
2772
2773 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
2774 periodCount *= 2;
2775 }
2776 config->period_count = periodCount;
2777
2778 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
2779}
2780
Eric Laurent0e46adf2016-12-16 12:49:24 -08002781static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2782 int32_t min_size_frames,
2783 struct audio_mmap_buffer_info *info)
2784{
2785 struct stream_out *out = (struct stream_out *)stream;
2786 struct audio_device *adev = out->dev;
2787 int ret = 0;
2788 unsigned int offset1;
2789 unsigned int frames1;
2790 const char *step = "";
2791
2792 ALOGV("%s", __func__);
2793 pthread_mutex_lock(&adev->lock);
2794
2795 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002796 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002797 ret = -EINVAL;
2798 goto exit;
2799 }
2800 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08002801 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002802 ret = -ENOSYS;
2803 goto exit;
2804 }
2805 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
2806 if (out->pcm_device_id < 0) {
2807 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2808 __func__, out->pcm_device_id, out->usecase);
2809 ret = -EINVAL;
2810 goto exit;
2811 }
Phil Burkbc991042017-02-24 08:06:44 -08002812
2813 adjust_mmap_period_count(&out->config, min_size_frames);
2814
Eric Laurent0e46adf2016-12-16 12:49:24 -08002815 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2816 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
2817 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2818 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
2819 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2820 step = "open";
2821 ret = -ENODEV;
2822 goto exit;
2823 }
2824 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
2825 if (ret < 0) {
2826 step = "begin";
2827 goto exit;
2828 }
2829 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
2830 info->burst_size_frames = out->config.period_size;
2831 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
2832
2833 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
2834 info->buffer_size_frames));
2835
2836 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
2837 if (ret < 0) {
2838 step = "commit";
2839 goto exit;
2840 }
Phil Burkbc991042017-02-24 08:06:44 -08002841
2842 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002843 ret = 0;
2844
2845 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
2846 __func__, info->shared_memory_address, info->buffer_size_frames);
2847
2848exit:
2849 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002850 if (out->pcm == NULL) {
2851 ALOGE("%s: %s - %d", __func__, step, ret);
2852 } else {
2853 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08002854 pcm_close(out->pcm);
2855 out->pcm = NULL;
2856 }
2857 }
2858 pthread_mutex_unlock(&adev->lock);
2859 return ret;
2860}
2861
2862static int out_get_mmap_position(const struct audio_stream_out *stream,
2863 struct audio_mmap_position *position)
2864{
2865 struct stream_out *out = (struct stream_out *)stream;
2866 ALOGVV("%s", __func__);
2867 if (position == NULL) {
2868 return -EINVAL;
2869 }
2870 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
2871 return -ENOSYS;
2872 }
2873 if (out->pcm == NULL) {
2874 return -ENOSYS;
2875 }
2876
2877 struct timespec ts = { 0, 0 };
2878 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
2879 if (ret < 0) {
2880 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2881 return ret;
2882 }
Andy Hungfc044e12017-03-20 09:24:22 -07002883 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002884 return 0;
2885}
2886
2887
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002888/** audio_stream_in implementation **/
2889static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2890{
2891 struct stream_in *in = (struct stream_in *)stream;
2892
2893 return in->config.rate;
2894}
2895
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002896static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002897{
2898 return -ENOSYS;
2899}
2900
2901static size_t in_get_buffer_size(const struct audio_stream *stream)
2902{
2903 struct stream_in *in = (struct stream_in *)stream;
2904
Haynes Mathew George03c40102016-01-29 17:57:48 -08002905 return in->config.period_size * in->af_period_multiplier *
2906 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002907}
2908
2909static uint32_t in_get_channels(const struct audio_stream *stream)
2910{
2911 struct stream_in *in = (struct stream_in *)stream;
2912
2913 return in->channel_mask;
2914}
2915
vivek mehta4ed66e62016-04-15 23:33:34 -07002916static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002917{
vivek mehta4ed66e62016-04-15 23:33:34 -07002918 struct stream_in *in = (struct stream_in *)stream;
2919 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002920}
2921
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002922static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002923{
2924 return -ENOSYS;
2925}
2926
2927static int in_standby(struct audio_stream *stream)
2928{
2929 struct stream_in *in = (struct stream_in *)stream;
2930 struct audio_device *adev = in->dev;
2931 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08002932 bool do_stop = true;
2933
Eric Laurent994a6932013-07-17 11:51:42 -07002934 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002935
2936 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002937
2938 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08002939 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002940 audio_extn_sound_trigger_stop_lab(in);
2941 in->standby = true;
2942 }
2943
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002944 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002945 if (adev->adm_deregister_stream)
2946 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2947
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002948 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002949 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002950 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002951 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002952 in->capture_started = false;
2953 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002954 if (in->pcm) {
2955 pcm_close(in->pcm);
2956 in->pcm = NULL;
2957 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002958 adev->enable_voicerx = false;
2959 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08002960 if (do_stop) {
2961 status = stop_input_stream(in);
2962 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002963 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002964 }
2965 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002966 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002967 return status;
2968}
2969
Andy Hungd13f0d32017-06-12 13:58:37 -07002970static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002971{
Andy Hungd13f0d32017-06-12 13:58:37 -07002972 struct stream_in *in = (struct stream_in *)stream;
2973
2974 // We try to get the lock for consistency,
2975 // but it isn't necessary for these variables.
2976 // If we're not in standby, we may be blocked on a read.
2977 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
2978 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
2979 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
2980 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
2981
2982 if (locked) {
2983 pthread_mutex_unlock(&in->lock);
2984 }
2985
2986 // dump error info
2987 (void)error_log_dump(
2988 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002989 return 0;
2990}
2991
2992static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2993{
2994 struct stream_in *in = (struct stream_in *)stream;
2995 struct audio_device *adev = in->dev;
2996 struct str_parms *parms;
2997 char *str;
2998 char value[32];
2999 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003000 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003001
Eric Laurent994a6932013-07-17 11:51:42 -07003002 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003003 parms = str_parms_create_str(kvpairs);
3004
3005 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3006
Eric Laurenta1478072015-09-21 17:21:52 -07003007 lock_input_stream(in);
3008
Eric Laurent150dbfe2013-02-27 14:31:02 -08003009 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003010 if (ret >= 0) {
3011 val = atoi(value);
3012 /* no audio source uses val == 0 */
3013 if ((in->source != val) && (val != 0)) {
3014 in->source = val;
3015 }
3016 }
3017
3018 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003019
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003020 if (ret >= 0) {
3021 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003022 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003023 in->device = val;
3024 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08003025 if (!in->standby) {
3026 ALOGV("update input routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003027 // inform adm before actual routing to prevent glitches.
3028 if (adev->adm_on_routing_change) {
3029 adev->adm_on_routing_change(adev->adm_data,
3030 in->capture_handle);
3031 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003032 select_devices(adev, in->usecase);
3033 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003034 }
3035 }
3036
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003037 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003038 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003039
3040 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003041 ALOGV("%s: exit: status(%d)", __func__, status);
3042 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003043}
3044
Haynes Mathew George569b7482017-05-08 14:44:27 -07003045static char* in_get_parameters(const struct audio_stream *stream,
3046 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003047{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003048 struct stream_in *in = (struct stream_in *)stream;
3049 struct str_parms *query = str_parms_create_str(keys);
3050 char *str;
3051 struct str_parms *reply = str_parms_create();
3052 bool replied = false;
3053
3054 ALOGV("%s: enter: keys - %s", __func__, keys);
3055 replied |= stream_get_parameter_channels(query, reply,
3056 &in->supported_channel_masks[0]);
3057 replied |= stream_get_parameter_formats(query, reply,
3058 &in->supported_formats[0]);
3059 replied |= stream_get_parameter_rates(query, reply,
3060 &in->supported_sample_rates[0]);
3061 if (replied) {
3062 str = str_parms_to_str(reply);
3063 } else {
3064 str = strdup(keys);
3065 }
3066 str_parms_destroy(query);
3067 str_parms_destroy(reply);
3068 ALOGV("%s: exit: returns - %s", __func__, str);
3069 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003070}
3071
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003072static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003073{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003074 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003075}
3076
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003077static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3078{
3079 if (!stream || !parms)
3080 return;
3081
3082 struct stream_in *in = (struct stream_in *)stream;
3083 struct audio_device *adev = in->dev;
3084
3085 card_status_t status;
3086 int card;
3087 if (parse_snd_card_status(parms, &card, &status) < 0)
3088 return;
3089
3090 pthread_mutex_lock(&adev->lock);
3091 bool valid_cb = (card == adev->snd_card);
3092 pthread_mutex_unlock(&adev->lock);
3093
3094 if (!valid_cb)
3095 return;
3096
3097 lock_input_stream(in);
3098 if (in->card_status != status)
3099 in->card_status = status;
3100 pthread_mutex_unlock(&in->lock);
3101
3102 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3103 use_case_table[in->usecase],
3104 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3105
3106 // a better solution would be to report error back to AF and let
3107 // it put the stream to standby
3108 if (status == CARD_STATUS_OFFLINE)
3109 in_standby(&in->stream.common);
3110
3111 return;
3112}
3113
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003114static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3115 size_t bytes)
3116{
3117 struct stream_in *in = (struct stream_in *)stream;
3118 struct audio_device *adev = in->dev;
3119 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003120 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003121 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003122
Eric Laurenta1478072015-09-21 17:21:52 -07003123 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003124 const size_t frame_size = audio_stream_in_frame_size(stream);
3125 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003126
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003127 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003128 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003129 /* Read from sound trigger HAL */
3130 audio_extn_sound_trigger_read(in, buffer, bytes);
3131 pthread_mutex_unlock(&in->lock);
3132 return bytes;
3133 }
3134
Eric Laurent0e46adf2016-12-16 12:49:24 -08003135 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3136 ret = -ENOSYS;
3137 goto exit;
3138 }
3139
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003140 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003141 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003142 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003143 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003144 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003145 goto exit;
3146 }
3147 in->standby = 0;
3148 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003149
Andy Hungd13f0d32017-06-12 13:58:37 -07003150 // errors that occur here are read errors.
3151 error_code = ERROR_CODE_READ;
3152
Haynes Mathew George03c40102016-01-29 17:57:48 -08003153 //what's the duration requested by the client?
3154 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3155 in->config.rate;
3156 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003157
Haynes Mathew George03c40102016-01-29 17:57:48 -08003158 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003159 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003160 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003161 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003162 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003163 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003164 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003165 if (ret < 0) {
3166 ALOGE("Failed to read w/err %s", strerror(errno));
3167 ret = -errno;
3168 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003169 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3170 if (bytes % 4 == 0) {
3171 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3172 int_buf_stream = buffer;
3173 for (size_t itt=0; itt < bytes/4 ; itt++) {
3174 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003175 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003176 } else {
3177 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3178 ret = -EINVAL;
3179 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003180 }
3181 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003182 }
3183
Haynes Mathew George03c40102016-01-29 17:57:48 -08003184 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003185
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003186 /*
3187 * Instead of writing zeroes here, we could trust the hardware
3188 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003189 * 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 -08003190 */
Andy Hungd13f0d32017-06-12 13:58:37 -07003191 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003192 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07003193 in->frames_muted += frames;
3194 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003195
3196exit:
3197 pthread_mutex_unlock(&in->lock);
3198
3199 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07003200 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003201 in_standby(&in->stream.common);
3202 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003203 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003204 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07003205 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08003206 }
3207 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003208 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003209 }
3210 return bytes;
3211}
3212
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003213static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003214{
3215 return 0;
3216}
3217
Andy Hung6ebe5962016-01-15 17:46:57 -08003218static int in_get_capture_position(const struct audio_stream_in *stream,
3219 int64_t *frames, int64_t *time)
3220{
3221 if (stream == NULL || frames == NULL || time == NULL) {
3222 return -EINVAL;
3223 }
3224 struct stream_in *in = (struct stream_in *)stream;
3225 int ret = -ENOSYS;
3226
3227 lock_input_stream(in);
3228 if (in->pcm) {
3229 struct timespec timestamp;
3230 unsigned int avail;
3231 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3232 *frames = in->frames_read + avail;
3233 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3234 ret = 0;
3235 }
3236 }
3237 pthread_mutex_unlock(&in->lock);
3238 return ret;
3239}
3240
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003241static int add_remove_audio_effect(const struct audio_stream *stream,
3242 effect_handle_t effect,
3243 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003244{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003245 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003246 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003247 int status = 0;
3248 effect_descriptor_t desc;
3249
3250 status = (*effect)->get_descriptor(effect, &desc);
3251 if (status != 0)
3252 return status;
3253
Eric Laurenta1478072015-09-21 17:21:52 -07003254 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003255 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003256 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003257 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003258 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003259 in->enable_aec != enable &&
3260 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3261 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003262 if (!enable)
3263 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003264 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3265 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3266 adev->enable_voicerx = enable;
3267 struct audio_usecase *usecase;
3268 struct listnode *node;
3269 list_for_each(node, &adev->usecase_list) {
3270 usecase = node_to_item(node, struct audio_usecase, list);
3271 if (usecase->type == PCM_PLAYBACK) {
3272 select_devices(adev, usecase->id);
3273 break;
3274 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003275 }
3276 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003277 if (!in->standby)
3278 select_devices(in->dev, in->usecase);
3279 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003280 if (in->enable_ns != enable &&
3281 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3282 in->enable_ns = enable;
3283 if (!in->standby)
3284 select_devices(in->dev, in->usecase);
3285 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003286 pthread_mutex_unlock(&in->dev->lock);
3287 pthread_mutex_unlock(&in->lock);
3288
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003289 return 0;
3290}
3291
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003292static int in_add_audio_effect(const struct audio_stream *stream,
3293 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003294{
Eric Laurent994a6932013-07-17 11:51:42 -07003295 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003296 return add_remove_audio_effect(stream, effect, true);
3297}
3298
3299static int in_remove_audio_effect(const struct audio_stream *stream,
3300 effect_handle_t effect)
3301{
Eric Laurent994a6932013-07-17 11:51:42 -07003302 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003303 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003304}
3305
Eric Laurent0e46adf2016-12-16 12:49:24 -08003306static int in_stop(const struct audio_stream_in* stream)
3307{
3308 struct stream_in *in = (struct stream_in *)stream;
3309 struct audio_device *adev = in->dev;
3310
3311 int ret = -ENOSYS;
3312 ALOGV("%s", __func__);
3313 pthread_mutex_lock(&adev->lock);
3314 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3315 in->capture_started && in->pcm != NULL) {
3316 pcm_stop(in->pcm);
3317 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003318 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003319 }
3320 pthread_mutex_unlock(&adev->lock);
3321 return ret;
3322}
3323
3324static int in_start(const struct audio_stream_in* stream)
3325{
3326 struct stream_in *in = (struct stream_in *)stream;
3327 struct audio_device *adev = in->dev;
3328 int ret = -ENOSYS;
3329
3330 ALOGV("%s in %p", __func__, in);
3331 pthread_mutex_lock(&adev->lock);
3332 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3333 !in->capture_started && in->pcm != NULL) {
3334 if (!in->capture_started) {
3335 ret = start_input_stream(in);
3336 if (ret == 0) {
3337 in->capture_started = true;
3338 }
3339 }
3340 }
3341 pthread_mutex_unlock(&adev->lock);
3342 return ret;
3343}
3344
3345static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3346 int32_t min_size_frames,
3347 struct audio_mmap_buffer_info *info)
3348{
3349 struct stream_in *in = (struct stream_in *)stream;
3350 struct audio_device *adev = in->dev;
3351 int ret = 0;
3352 unsigned int offset1;
3353 unsigned int frames1;
3354 const char *step = "";
3355
3356 pthread_mutex_lock(&adev->lock);
3357 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003358
Eric Laurent0e46adf2016-12-16 12:49:24 -08003359 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003360 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003361 ret = -EINVAL;
3362 goto exit;
3363 }
3364 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003365 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003366 ALOGV("%s in %p", __func__, in);
3367 ret = -ENOSYS;
3368 goto exit;
3369 }
3370 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3371 if (in->pcm_device_id < 0) {
3372 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3373 __func__, in->pcm_device_id, in->usecase);
3374 ret = -EINVAL;
3375 goto exit;
3376 }
Phil Burkbc991042017-02-24 08:06:44 -08003377
3378 adjust_mmap_period_count(&in->config, min_size_frames);
3379
Eric Laurent0e46adf2016-12-16 12:49:24 -08003380 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3381 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3382 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3383 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3384 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3385 step = "open";
3386 ret = -ENODEV;
3387 goto exit;
3388 }
3389
3390 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3391 if (ret < 0) {
3392 step = "begin";
3393 goto exit;
3394 }
3395 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
3396 info->burst_size_frames = in->config.period_size;
3397 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3398
3399 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(in->pcm,
3400 info->buffer_size_frames));
3401
3402 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3403 if (ret < 0) {
3404 step = "commit";
3405 goto exit;
3406 }
3407
Phil Burkbc991042017-02-24 08:06:44 -08003408 in->standby = false;
3409 ret = 0;
3410
Eric Laurent0e46adf2016-12-16 12:49:24 -08003411 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3412 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003413
3414exit:
3415 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003416 if (in->pcm == NULL) {
3417 ALOGE("%s: %s - %d", __func__, step, ret);
3418 } else {
3419 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003420 pcm_close(in->pcm);
3421 in->pcm = NULL;
3422 }
3423 }
3424 pthread_mutex_unlock(&adev->lock);
3425 return ret;
3426}
3427
3428static int in_get_mmap_position(const struct audio_stream_in *stream,
3429 struct audio_mmap_position *position)
3430{
3431 struct stream_in *in = (struct stream_in *)stream;
3432 ALOGVV("%s", __func__);
3433 if (position == NULL) {
3434 return -EINVAL;
3435 }
3436 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
3437 return -ENOSYS;
3438 }
3439 if (in->pcm == NULL) {
3440 return -ENOSYS;
3441 }
3442 struct timespec ts = { 0, 0 };
3443 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
3444 if (ret < 0) {
3445 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3446 return ret;
3447 }
Andy Hungfc044e12017-03-20 09:24:22 -07003448 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003449 return 0;
3450}
3451
3452
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003453static int adev_open_output_stream(struct audio_hw_device *dev,
3454 audio_io_handle_t handle,
3455 audio_devices_t devices,
3456 audio_output_flags_t flags,
3457 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003458 struct audio_stream_out **stream_out,
3459 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003460{
3461 struct audio_device *adev = (struct audio_device *)dev;
3462 struct stream_out *out;
3463 int i, ret;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003464 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
3465 bool is_usb_dev = audio_is_usb_out_device(devices) &&
3466 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
3467 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003468
Eric Laurent994a6932013-07-17 11:51:42 -07003469 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003470 __func__, config->sample_rate, config->channel_mask, devices, flags);
3471 *stream_out = NULL;
3472 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3473
3474 if (devices == AUDIO_DEVICE_NONE)
3475 devices = AUDIO_DEVICE_OUT_SPEAKER;
3476
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003477 out->flags = flags;
3478 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003479 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003480 out->format = config->format;
3481 out->sample_rate = config->sample_rate;
3482 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3483 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003484 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003485
3486 /* Init use case and pcm_config */
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003487 if (audio_is_linear_pcm(out->format) &&
3488 (out->flags == AUDIO_OUTPUT_FLAG_NONE ||
Haynes Mathew George569b7482017-05-08 14:44:27 -07003489 out->flags == AUDIO_OUTPUT_FLAG_DIRECT) && direct_dev) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003490 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003491 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003492 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003493 if (config->sample_rate == 0)
3494 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3495 if (config->channel_mask == 0)
3496 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3497 if (config->format == AUDIO_FORMAT_DEFAULT)
3498 config->format = AUDIO_FORMAT_PCM_16_BIT;
3499 } else if (is_usb_dev) {
3500 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
3501 &config->format,
3502 &out->supported_formats[0],
3503 MAX_SUPPORTED_FORMATS,
3504 &config->channel_mask,
3505 &out->supported_channel_masks[0],
3506 MAX_SUPPORTED_CHANNEL_MASKS,
3507 &config->sample_rate,
3508 &out->supported_sample_rates[0],
3509 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003510 ALOGV("plugged dev USB ret %d", ret);
3511 } else {
3512 ret = -1;
3513 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003514 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003515 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003516 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003517
Haynes Mathew George569b7482017-05-08 14:44:27 -07003518 out->channel_mask = config->channel_mask;
3519 out->sample_rate = config->sample_rate;
3520 out->format = config->format;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003521 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3522 // does this change?
Haynes Mathew George569b7482017-05-08 14:44:27 -07003523 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003524 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003525 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003526 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003527 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003528 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003529 pthread_mutex_lock(&adev->lock);
3530 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3531 pthread_mutex_unlock(&adev->lock);
3532
3533 // reject offload during card offline to allow
3534 // fallback to s/w paths
3535 if (offline) {
3536 ret = -ENODEV;
3537 goto error_open;
3538 }
3539
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003540 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3541 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3542 ALOGE("%s: Unsupported Offload information", __func__);
3543 ret = -EINVAL;
3544 goto error_open;
3545 }
3546 if (!is_supported_format(config->offload_info.format)) {
3547 ALOGE("%s: Unsupported audio format", __func__);
3548 ret = -EINVAL;
3549 goto error_open;
3550 }
3551
3552 out->compr_config.codec = (struct snd_codec *)
3553 calloc(1, sizeof(struct snd_codec));
3554
3555 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3556 if (config->offload_info.channel_mask)
3557 out->channel_mask = config->offload_info.channel_mask;
3558 else if (config->channel_mask)
3559 out->channel_mask = config->channel_mask;
3560 out->format = config->offload_info.format;
3561 out->sample_rate = config->offload_info.sample_rate;
3562
3563 out->stream.set_callback = out_set_callback;
3564 out->stream.pause = out_pause;
3565 out->stream.resume = out_resume;
3566 out->stream.drain = out_drain;
3567 out->stream.flush = out_flush;
3568
3569 out->compr_config.codec->id =
3570 get_snd_codec_id(config->offload_info.format);
3571 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3572 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07003573 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003574 out->compr_config.codec->bit_rate =
3575 config->offload_info.bit_rate;
3576 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003577 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003578 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3579
3580 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3581 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003582
3583 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003584 create_offload_callback_thread(out);
3585 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3586 __func__, config->offload_info.version,
3587 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003588 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07003589 switch (config->sample_rate) {
3590 case 8000:
3591 case 16000:
3592 case 48000:
3593 out->sample_rate = config->sample_rate;
3594 break;
3595 default:
3596 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003597 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003598 out->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003599 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3600 out->config = pcm_config_afe_proxy_playback;
3601 adev->voice_tx_output = out;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003602 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003603 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3604 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3605 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003606 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
3607 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3608 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003609 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3610 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003611 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003612 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003613 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3614 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3615 out->config = pcm_config_mmap_playback;
3616 out->stream.start = out_start;
3617 out->stream.stop = out_stop;
3618 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3619 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003620 } else {
3621 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3622 out->config = pcm_config_low_latency;
3623 }
3624 if (config->format != audio_format_from_pcm_format(out->config.format)) {
3625 if (k_enable_extended_precision
3626 && pcm_params_format_test(adev->use_case_table[out->usecase],
3627 pcm_format_from_audio_format(config->format))) {
3628 out->config.format = pcm_format_from_audio_format(config->format);
3629 /* out->format already set to config->format */
3630 } else {
3631 /* deny the externally proposed config format
3632 * and use the one specified in audio_hw layer configuration.
3633 * Note: out->format is returned by out->stream.common.get_format()
3634 * and is used to set config->format in the code several lines below.
3635 */
3636 out->format = audio_format_from_pcm_format(out->config.format);
3637 }
3638 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003639 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003640 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003641
3642 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
3643 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
3644 (config->channel_mask != 0 && config->channel_mask != out->channel_mask)) {
3645 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
3646 __func__, config->sample_rate, config->format, config->channel_mask);
3647 config->sample_rate = out->sample_rate;
3648 config->format = out->format;
3649 config->channel_mask = out->channel_mask;
3650 ret = -EINVAL;
3651 goto error_open;
3652 }
3653
Andy Hung6fcba9c2014-03-18 11:53:32 -07003654 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3655 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003656
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003657 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003658 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003659 adev->primary_output = out;
3660 else {
3661 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003662 ret = -EEXIST;
3663 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003664 }
3665 }
3666
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003667 /* Check if this usecase is already existing */
3668 pthread_mutex_lock(&adev->lock);
3669 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3670 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003671 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003672 ret = -EEXIST;
3673 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003674 }
3675 pthread_mutex_unlock(&adev->lock);
3676
3677 out->stream.common.get_sample_rate = out_get_sample_rate;
3678 out->stream.common.set_sample_rate = out_set_sample_rate;
3679 out->stream.common.get_buffer_size = out_get_buffer_size;
3680 out->stream.common.get_channels = out_get_channels;
3681 out->stream.common.get_format = out_get_format;
3682 out->stream.common.set_format = out_set_format;
3683 out->stream.common.standby = out_standby;
3684 out->stream.common.dump = out_dump;
3685 out->stream.common.set_parameters = out_set_parameters;
3686 out->stream.common.get_parameters = out_get_parameters;
3687 out->stream.common.add_audio_effect = out_add_audio_effect;
3688 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3689 out->stream.get_latency = out_get_latency;
3690 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003691#ifdef NO_AUDIO_OUT
3692 out->stream.write = out_write_for_no_output;
3693#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003694 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003695#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003696 out->stream.get_render_position = out_get_render_position;
3697 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003698 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003699
Eric Laurent0e46adf2016-12-16 12:49:24 -08003700 if (out->realtime)
3701 out->af_period_multiplier = af_period_multiplier;
3702 else
3703 out->af_period_multiplier = 1;
3704
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003705 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003706 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003707 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003708
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003709 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003710 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003711 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3712
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003713 config->format = out->stream.common.get_format(&out->stream.common);
3714 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3715 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3716
Andy Hunga452b0a2017-03-15 14:51:15 -07003717 out->error_log = error_log_create(
3718 ERROR_LOG_ENTRIES,
3719 1000000000 /* aggregate consecutive identical errors within one second in ns */);
3720
Andy Hungfc044e12017-03-20 09:24:22 -07003721 // power_log may be null if the format is not supported
Andy Hung9e737de2017-05-22 10:51:22 -07003722 // or not a userdebug or eng build.
Andy Hunge12f7302017-06-07 15:07:37 -07003723 if (is_userdebug_or_eng_build()) {
Andy Hung9e737de2017-05-22 10:51:22 -07003724 const size_t POWER_LOG_FRAMES_PER_ENTRY =
3725 (long long)config->sample_rate * POWER_LOG_SAMPLING_INTERVAL_MS / 1000;
3726
3727 out->power_log = power_log_create(
3728 config->sample_rate,
3729 audio_channel_count_from_out_mask(config->channel_mask),
3730 config->format,
3731 POWER_LOG_ENTRIES,
3732 POWER_LOG_FRAMES_PER_ENTRY);
3733 }
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003734
3735 /*
3736 By locking output stream before registering, we allow the callback
3737 to update stream's state only after stream's initial state is set to
3738 adev state.
3739 */
3740 lock_output_stream(out);
3741 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3742 pthread_mutex_lock(&adev->lock);
3743 out->card_status = adev->card_status;
3744 pthread_mutex_unlock(&adev->lock);
3745 pthread_mutex_unlock(&out->lock);
3746
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003747 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003748
Eric Laurent994a6932013-07-17 11:51:42 -07003749 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003750 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003751
3752error_open:
3753 free(out);
3754 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003755 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003756 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003757}
3758
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003759static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003760 struct audio_stream_out *stream)
3761{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003762 struct stream_out *out = (struct stream_out *)stream;
3763 struct audio_device *adev = out->dev;
3764
Eric Laurent994a6932013-07-17 11:51:42 -07003765 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003766
3767 // must deregister from sndmonitor first to prevent races
3768 // between the callback and close_stream
3769 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003770 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003771 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3772 destroy_offload_callback_thread(out);
3773
3774 if (out->compr_config.codec != NULL)
3775 free(out->compr_config.codec);
3776 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003777
3778 if (adev->voice_tx_output == out)
3779 adev->voice_tx_output = NULL;
3780
Andy Hungfc044e12017-03-20 09:24:22 -07003781 power_log_destroy(out->power_log);
3782 out->power_log = NULL;
3783
Andy Hunga452b0a2017-03-15 14:51:15 -07003784 error_log_destroy(out->error_log);
3785 out->error_log = NULL;
3786
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003787 pthread_cond_destroy(&out->cond);
3788 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003789 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003790 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003791}
3792
3793static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3794{
3795 struct audio_device *adev = (struct audio_device *)dev;
3796 struct str_parms *parms;
3797 char *str;
3798 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003799 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003800 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003801 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003802
Joe Onorato188b6222016-03-01 11:02:27 -08003803 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003804
3805 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003806
3807 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003808 status = voice_set_parameters(adev, parms);
3809 if (status != 0) {
3810 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003811 }
3812
3813 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3814 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003815 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003816 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3817 adev->bluetooth_nrec = true;
3818 else
3819 adev->bluetooth_nrec = false;
3820 }
3821
3822 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3823 if (ret >= 0) {
3824 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3825 adev->screen_off = false;
3826 else
3827 adev->screen_off = true;
3828 }
3829
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003830 ret = str_parms_get_int(parms, "rotation", &val);
3831 if (ret >= 0) {
3832 bool reverse_speakers = false;
3833 switch(val) {
3834 // FIXME: note that the code below assumes that the speakers are in the correct placement
3835 // relative to the user when the device is rotated 90deg from its default rotation. This
3836 // assumption is device-specific, not platform-specific like this code.
3837 case 270:
3838 reverse_speakers = true;
3839 break;
3840 case 0:
3841 case 90:
3842 case 180:
3843 break;
3844 default:
3845 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003846 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003847 }
Eric Laurent03f09432014-03-25 18:09:11 -07003848 if (status == 0) {
Ravi Kumar Alamanda1f60cf82015-04-23 19:45:17 -07003849 platform_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003850 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003851 }
3852
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003853 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3854 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003855 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003856 }
3857
David Linee3fe402017-03-13 10:00:42 -07003858 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3859 if (ret >= 0) {
3860 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
3861 if (device == AUDIO_DEVICE_OUT_USB_DEVICE) {
3862 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3863 if (ret >= 0) {
3864 const int card = atoi(value);
3865 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, card);
3866 }
3867 } else if (device == AUDIO_DEVICE_IN_USB_DEVICE) {
3868 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3869 if (ret >= 0) {
3870 const int card = atoi(value);
3871 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, card);
3872 }
3873 }
3874 }
3875
3876 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3877 if (ret >= 0) {
3878 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
3879 if (device == AUDIO_DEVICE_OUT_USB_DEVICE) {
3880 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3881 if (ret >= 0) {
3882 const int card = atoi(value);
3883
3884 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, card);
3885 }
3886 } else if (device == AUDIO_DEVICE_IN_USB_DEVICE) {
3887 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3888 if (ret >= 0) {
3889 const int card = atoi(value);
3890 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, card);
3891 }
3892 }
3893 }
3894
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08003895 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003896done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003897 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003898 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07003899 ALOGV("%s: exit with code(%d)", __func__, status);
3900 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003901}
3902
3903static char* adev_get_parameters(const struct audio_hw_device *dev,
3904 const char *keys)
3905{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003906 struct audio_device *adev = (struct audio_device *)dev;
3907 struct str_parms *reply = str_parms_create();
3908 struct str_parms *query = str_parms_create_str(keys);
3909 char *str;
3910
3911 pthread_mutex_lock(&adev->lock);
3912
3913 voice_get_parameters(adev, query, reply);
3914 str = str_parms_to_str(reply);
3915 str_parms_destroy(query);
3916 str_parms_destroy(reply);
3917
3918 pthread_mutex_unlock(&adev->lock);
3919 ALOGV("%s: exit: returns - %s", __func__, str);
3920 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003921}
3922
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003923static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003924{
3925 return 0;
3926}
3927
Haynes Mathew George5191a852013-09-11 14:19:36 -07003928static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3929{
3930 int ret;
3931 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003932
Eric Laurent4cc4ce12014-09-10 13:21:01 -05003933 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
3934
Haynes Mathew George5191a852013-09-11 14:19:36 -07003935 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003936 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003937 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003938
Haynes Mathew George5191a852013-09-11 14:19:36 -07003939 return ret;
3940}
3941
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003942static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003943{
3944 return -ENOSYS;
3945}
3946
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003947static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3948 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003949{
3950 return -ENOSYS;
3951}
3952
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003953static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003954{
3955 return -ENOSYS;
3956}
3957
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003958static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003959{
3960 return -ENOSYS;
3961}
3962
3963static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3964{
3965 struct audio_device *adev = (struct audio_device *)dev;
3966
3967 pthread_mutex_lock(&adev->lock);
3968 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07003969 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003970 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07003971 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3972 voice_is_in_call(adev)) {
3973 voice_stop_call(adev);
3974 adev->current_call_output = NULL;
3975 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003976 }
3977 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003978
3979 audio_extn_extspk_set_mode(adev->extspk, mode);
3980
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003981 return 0;
3982}
3983
3984static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3985{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003986 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003987 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003988
Eric Laurent2bafff12016-03-17 12:17:23 -07003989 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003990 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08003991 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
3992 ret = audio_extn_hfp_set_mic_mute(adev, state);
3993 } else {
3994 ret = voice_set_mic_mute(adev, state);
3995 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003996 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00003997 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003998
3999 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004000}
4001
4002static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4003{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004004 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004005 return 0;
4006}
4007
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004008static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004009 const struct audio_config *config)
4010{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004011 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004012
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004013 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4014 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004015}
4016
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004017static bool adev_input_allow_hifi_record(struct audio_device *adev,
4018 audio_devices_t devices,
4019 audio_input_flags_t flags,
4020 audio_source_t source) {
4021 const bool allowed = true;
4022
4023 if (!audio_is_usb_in_device(devices))
4024 return !allowed;
4025
4026 switch (flags) {
4027 case AUDIO_INPUT_FLAG_NONE:
4028 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4029 break;
4030 default:
4031 return !allowed;
4032 }
4033
4034 switch (source) {
4035 case AUDIO_SOURCE_DEFAULT:
4036 case AUDIO_SOURCE_MIC:
4037 case AUDIO_SOURCE_UNPROCESSED:
4038 break;
4039 default:
4040 return !allowed;
4041 }
4042
4043 switch (adev->mode) {
4044 case 0:
4045 break;
4046 default:
4047 return !allowed;
4048 }
4049
4050 return allowed;
4051}
4052
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004053static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004054 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004055 audio_devices_t devices,
4056 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004057 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004058 audio_input_flags_t flags,
4059 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004060 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004061{
4062 struct audio_device *adev = (struct audio_device *)dev;
4063 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004064 int ret = 0, buffer_size, frame_size;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004065 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004066 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004067 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004068 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4069 devices,
4070 flags,
4071 source);
4072 ALOGE("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004073 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004074
4075 if (config->sample_rate == 0)
4076 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4077 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4078 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4079 if (config->format == AUDIO_FORMAT_DEFAULT)
4080 config->format = AUDIO_FORMAT_PCM_16_BIT;
4081
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004082 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
4083 return -EINVAL;
4084
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004085 if (audio_extn_tfa_98xx_is_supported() &&
4086 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004087 return -EINVAL;
4088
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004089 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4090
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004091 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004092 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004093
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004094 in->stream.common.get_sample_rate = in_get_sample_rate;
4095 in->stream.common.set_sample_rate = in_set_sample_rate;
4096 in->stream.common.get_buffer_size = in_get_buffer_size;
4097 in->stream.common.get_channels = in_get_channels;
4098 in->stream.common.get_format = in_get_format;
4099 in->stream.common.set_format = in_set_format;
4100 in->stream.common.standby = in_standby;
4101 in->stream.common.dump = in_dump;
4102 in->stream.common.set_parameters = in_set_parameters;
4103 in->stream.common.get_parameters = in_get_parameters;
4104 in->stream.common.add_audio_effect = in_add_audio_effect;
4105 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4106 in->stream.set_gain = in_set_gain;
4107 in->stream.read = in_read;
4108 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08004109 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004110
4111 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004112 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004113 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004114 in->standby = 1;
4115 in->channel_mask = config->channel_mask;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004116 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004117 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004118
Haynes Mathew George569b7482017-05-08 14:44:27 -07004119 if (is_usb_dev && may_use_hifi_record) {
4120 /* HiFi record selects an appropriate format, channel, rate combo
4121 depending on sink capabilities*/
4122 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
4123 &config->format,
4124 &in->supported_formats[0],
4125 MAX_SUPPORTED_FORMATS,
4126 &config->channel_mask,
4127 &in->supported_channel_masks[0],
4128 MAX_SUPPORTED_CHANNEL_MASKS,
4129 &config->sample_rate,
4130 &in->supported_sample_rates[0],
4131 MAX_SUPPORTED_SAMPLE_RATES);
4132 if (ret != 0) {
4133 ret = -EINVAL;
4134 goto err_open;
4135 }
4136 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07004137 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07004138 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
4139 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
4140 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4141 bool ret_error = false;
4142 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4143 from HAL is 8_24
4144 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4145 8_24 return error indicating supported format is 8_24
4146 *> In case of any other source requesting 24 bit or float return error
4147 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07004148
vivek mehta57ff9b52016-04-28 14:13:08 -07004149 on error flinger will retry with supported format passed
4150 */
4151 if (source != AUDIO_SOURCE_UNPROCESSED) {
4152 config->format = AUDIO_FORMAT_PCM_16_BIT;
4153 ret_error = true;
4154 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
4155 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
4156 ret_error = true;
4157 }
4158
4159 if (ret_error) {
4160 ret = -EINVAL;
4161 goto err_open;
4162 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004163 }
4164
vivek mehta57ff9b52016-04-28 14:13:08 -07004165 in->format = config->format;
4166
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004167 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004168 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
4169 if (config->sample_rate == 0)
4170 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4171 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4172 config->sample_rate != 8000) {
4173 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4174 ret = -EINVAL;
4175 goto err_open;
4176 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004177
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004178 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4179 config->format = AUDIO_FORMAT_PCM_16_BIT;
4180 ret = -EINVAL;
4181 goto err_open;
4182 }
4183
4184 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4185 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07004186 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004187 } else if (is_usb_dev && may_use_hifi_record) {
4188 in->usecase = USECASE_AUDIO_RECORD_HIFI;
4189 in->config = pcm_config_audio_capture;
4190 frame_size = audio_stream_in_frame_size(&in->stream);
4191 buffer_size = get_input_buffer_size(config->sample_rate,
4192 config->format,
4193 channel_count,
4194 false /*is_low_latency*/);
4195 in->config.period_size = buffer_size / frame_size;
4196 in->config.rate = config->sample_rate;
4197 in->af_period_multiplier = 1;
4198 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004199 } else {
4200 in->usecase = USECASE_AUDIO_RECORD;
4201 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08004202 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004203 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07004204#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004205 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07004206#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08004207 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004208 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08004209 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004210 frame_size = audio_stream_in_frame_size(&in->stream);
4211 buffer_size = get_input_buffer_size(config->sample_rate,
4212 config->format,
4213 channel_count,
Haynes Mathew George569b7482017-05-08 14:44:27 -07004214 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004215 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004216 in->config.rate = config->sample_rate;
4217 in->af_period_multiplier = 1;
4218 } else {
4219 // period size is left untouched for rt mode playback
4220 in->config = pcm_config_audio_capture_rt;
4221 in->af_period_multiplier = af_period_multiplier;
4222 }
4223 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
4224 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004225 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08004226 in->usecase = USECASE_AUDIO_RECORD_MMAP;
4227 in->config = pcm_config_mmap_capture;
4228 in->stream.start = in_start;
4229 in->stream.stop = in_stop;
4230 in->stream.create_mmap_buffer = in_create_mmap_buffer;
4231 in->stream.get_mmap_position = in_get_mmap_position;
4232 in->af_period_multiplier = 1;
4233 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
4234 } else {
4235 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004236 frame_size = audio_stream_in_frame_size(&in->stream);
4237 buffer_size = get_input_buffer_size(config->sample_rate,
4238 config->format,
4239 channel_count,
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004240 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004241 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004242 in->config.rate = config->sample_rate;
4243 in->af_period_multiplier = 1;
4244 }
4245 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
4246 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004247 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004248
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004249 in->config.channels = channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004250
Andy Hungd13f0d32017-06-12 13:58:37 -07004251 in->error_log = error_log_create(
4252 ERROR_LOG_ENTRIES,
4253 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
4254
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004255 /* This stream could be for sound trigger lab,
4256 get sound trigger pcm if present */
4257 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004258
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004259 lock_input_stream(in);
4260 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
4261 pthread_mutex_lock(&adev->lock);
4262 in->card_status = adev->card_status;
4263 pthread_mutex_unlock(&adev->lock);
4264 pthread_mutex_unlock(&in->lock);
4265
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004266 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004267 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004268 return 0;
4269
4270err_open:
4271 free(in);
4272 *stream_in = NULL;
4273 return ret;
4274}
4275
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004276static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004277 struct audio_stream_in *stream)
4278{
Andy Hungd13f0d32017-06-12 13:58:37 -07004279 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004280 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004281
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004282 // must deregister from sndmonitor first to prevent races
4283 // between the callback and close_stream
4284 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004285 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07004286
4287 error_log_destroy(in->error_log);
4288 in->error_log = NULL;
4289
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004290 free(stream);
4291
4292 return;
4293}
4294
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004295static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004296{
4297 return 0;
4298}
4299
Andy Hung31aca912014-03-20 17:14:59 -07004300/* verifies input and output devices and their capabilities.
4301 *
4302 * This verification is required when enabling extended bit-depth or
4303 * sampling rates, as not all qcom products support it.
4304 *
4305 * Suitable for calling only on initialization such as adev_open().
4306 * It fills the audio_device use_case_table[] array.
4307 *
4308 * Has a side-effect that it needs to configure audio routing / devices
4309 * in order to power up the devices and read the device parameters.
4310 * It does not acquire any hw device lock. Should restore the devices
4311 * back to "normal state" upon completion.
4312 */
4313static int adev_verify_devices(struct audio_device *adev)
4314{
4315 /* enumeration is a bit difficult because one really wants to pull
4316 * the use_case, device id, etc from the hidden pcm_device_table[].
4317 * In this case there are the following use cases and device ids.
4318 *
4319 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
4320 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004321 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07004322 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
4323 * [USECASE_AUDIO_RECORD] = {0, 0},
4324 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
4325 * [USECASE_VOICE_CALL] = {2, 2},
4326 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004327 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07004328 * USECASE_VOICE_CALL omitted, but possible for either input or output.
4329 */
4330
4331 /* should be the usecases enabled in adev_open_input_stream() */
4332 static const int test_in_usecases[] = {
4333 USECASE_AUDIO_RECORD,
4334 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
4335 };
4336 /* should be the usecases enabled in adev_open_output_stream()*/
4337 static const int test_out_usecases[] = {
4338 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
4339 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
4340 };
4341 static const usecase_type_t usecase_type_by_dir[] = {
4342 PCM_PLAYBACK,
4343 PCM_CAPTURE,
4344 };
4345 static const unsigned flags_by_dir[] = {
4346 PCM_OUT,
4347 PCM_IN,
4348 };
4349
4350 size_t i;
4351 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004352 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07004353 char info[512]; /* for possible debug info */
4354
4355 for (dir = 0; dir < 2; ++dir) {
4356 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
4357 const unsigned flags_dir = flags_by_dir[dir];
4358 const size_t testsize =
4359 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
4360 const int *testcases =
4361 dir ? test_in_usecases : test_out_usecases;
4362 const audio_devices_t audio_device =
4363 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
4364
4365 for (i = 0; i < testsize; ++i) {
4366 const audio_usecase_t audio_usecase = testcases[i];
4367 int device_id;
4368 snd_device_t snd_device;
4369 struct pcm_params **pparams;
4370 struct stream_out out;
4371 struct stream_in in;
4372 struct audio_usecase uc_info;
4373 int retval;
4374
4375 pparams = &adev->use_case_table[audio_usecase];
4376 pcm_params_free(*pparams); /* can accept null input */
4377 *pparams = NULL;
4378
4379 /* find the device ID for the use case (signed, for error) */
4380 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
4381 if (device_id < 0)
4382 continue;
4383
4384 /* prepare structures for device probing */
4385 memset(&uc_info, 0, sizeof(uc_info));
4386 uc_info.id = audio_usecase;
4387 uc_info.type = usecase_type;
4388 if (dir) {
4389 adev->active_input = &in;
4390 memset(&in, 0, sizeof(in));
4391 in.device = audio_device;
4392 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4393 uc_info.stream.in = &in;
4394 } else {
4395 adev->active_input = NULL;
4396 }
4397 memset(&out, 0, sizeof(out));
4398 out.devices = audio_device; /* only field needed in select_devices */
4399 uc_info.stream.out = &out;
4400 uc_info.devices = audio_device;
4401 uc_info.in_snd_device = SND_DEVICE_NONE;
4402 uc_info.out_snd_device = SND_DEVICE_NONE;
4403 list_add_tail(&adev->usecase_list, &uc_info.list);
4404
4405 /* select device - similar to start_(in/out)put_stream() */
4406 retval = select_devices(adev, audio_usecase);
4407 if (retval >= 0) {
4408 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4409#if LOG_NDEBUG == 0
4410 if (*pparams) {
4411 ALOGV("%s: (%s) card %d device %d", __func__,
4412 dir ? "input" : "output", card_id, device_id);
4413 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004414 } else {
4415 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4416 }
4417#endif
4418 }
4419
4420 /* deselect device - similar to stop_(in/out)put_stream() */
4421 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004422 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004423 /* 2. Disable the rx device */
4424 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004425 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004426 list_remove(&uc_info.list);
4427 }
4428 }
4429 adev->active_input = NULL; /* restore adev state */
4430 return 0;
4431}
4432
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004433static int adev_close(hw_device_t *device)
4434{
Andy Hung31aca912014-03-20 17:14:59 -07004435 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004436 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004437
4438 if (!adev)
4439 return 0;
4440
Kevin Rocarda5453442017-05-02 15:09:20 -07004441 audio_extn_snd_mon_unregister_listener(adev);
Kevin Rocard8342c2c2017-04-07 18:50:00 -07004442 audio_extn_snd_mon_deinit();
Kevin Rocarda5453442017-05-02 15:09:20 -07004443
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004444 audio_extn_tfa_98xx_deinit();
4445
vivek mehta1a9b7c02015-06-25 11:49:38 -07004446 pthread_mutex_lock(&adev_init_lock);
4447
4448 if ((--audio_device_ref_count) == 0) {
4449 audio_route_free(adev->audio_route);
4450 free(adev->snd_dev_ref_cnt);
4451 platform_deinit(adev->platform);
4452 audio_extn_extspk_deinit(adev->extspk);
4453 audio_extn_sound_trigger_deinit(adev);
4454 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4455 pcm_params_free(adev->use_case_table[i]);
4456 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004457 if (adev->adm_deinit)
4458 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004459 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004460 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004461
4462 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004463
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004464 return 0;
4465}
4466
Glenn Kasten4f993392014-05-14 07:30:48 -07004467/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4468 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4469 * just that it _might_ work.
4470 */
4471static int period_size_is_plausible_for_low_latency(int period_size)
4472{
4473 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004474 case 48:
4475 case 96:
4476 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004477 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004478 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004479 case 240:
4480 case 320:
4481 case 480:
4482 return 1;
4483 default:
4484 return 0;
4485 }
4486}
4487
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004488static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4489{
4490 int card;
4491 card_status_t status;
4492
4493 if (!parms)
4494 return;
4495
4496 if (parse_snd_card_status(parms, &card, &status) < 0)
4497 return;
4498
4499 pthread_mutex_lock(&adev->lock);
4500 bool valid_cb = (card == adev->snd_card);
4501 if (valid_cb) {
4502 if (adev->card_status != status) {
4503 adev->card_status = status;
4504 platform_snd_card_update(adev->platform, status);
4505 }
4506 }
4507 pthread_mutex_unlock(&adev->lock);
4508 return;
4509}
4510
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004511static int adev_open(const hw_module_t *module, const char *name,
4512 hw_device_t **device)
4513{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004514 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004515
Eric Laurent2bafff12016-03-17 12:17:23 -07004516 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004517 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004518 pthread_mutex_lock(&adev_init_lock);
4519 if (audio_device_ref_count != 0) {
4520 *device = &adev->device.common;
4521 audio_device_ref_count++;
4522 ALOGV("%s: returning existing instance of adev", __func__);
4523 ALOGV("%s: exit", __func__);
4524 pthread_mutex_unlock(&adev_init_lock);
4525 return 0;
4526 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004527 adev = calloc(1, sizeof(struct audio_device));
4528
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004529 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4530
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004531 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4532 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4533 adev->device.common.module = (struct hw_module_t *)module;
4534 adev->device.common.close = adev_close;
4535
4536 adev->device.init_check = adev_init_check;
4537 adev->device.set_voice_volume = adev_set_voice_volume;
4538 adev->device.set_master_volume = adev_set_master_volume;
4539 adev->device.get_master_volume = adev_get_master_volume;
4540 adev->device.set_master_mute = adev_set_master_mute;
4541 adev->device.get_master_mute = adev_get_master_mute;
4542 adev->device.set_mode = adev_set_mode;
4543 adev->device.set_mic_mute = adev_set_mic_mute;
4544 adev->device.get_mic_mute = adev_get_mic_mute;
4545 adev->device.set_parameters = adev_set_parameters;
4546 adev->device.get_parameters = adev_get_parameters;
4547 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4548 adev->device.open_output_stream = adev_open_output_stream;
4549 adev->device.close_output_stream = adev_close_output_stream;
4550 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004551
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004552 adev->device.close_input_stream = adev_close_input_stream;
4553 adev->device.dump = adev_dump;
4554
4555 /* Set the default route before the PCM stream is opened */
4556 pthread_mutex_lock(&adev->lock);
4557 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004558 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004559 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004560 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004561 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004562 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004563 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004564 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004565 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004566 pthread_mutex_unlock(&adev->lock);
4567
4568 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004569 adev->platform = platform_init(adev);
4570 if (!adev->platform) {
4571 free(adev->snd_dev_ref_cnt);
4572 free(adev);
4573 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4574 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004575 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004576 return -EINVAL;
4577 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05004578 adev->extspk = audio_extn_extspk_init(adev);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004579 audio_extn_sound_trigger_init(adev);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004580
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004581 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4582 if (adev->visualizer_lib == NULL) {
4583 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4584 } else {
4585 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4586 adev->visualizer_start_output =
4587 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4588 "visualizer_hal_start_output");
4589 adev->visualizer_stop_output =
4590 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4591 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07004592 }
4593
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004594 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4595 if (adev->offload_effects_lib == NULL) {
4596 ALOGW("%s: DLOPEN failed for %s", __func__,
4597 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4598 } else {
4599 ALOGV("%s: DLOPEN successful for %s", __func__,
4600 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4601 adev->offload_effects_start_output =
4602 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4603 "offload_effects_bundle_hal_start_output");
4604 adev->offload_effects_stop_output =
4605 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4606 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07004607 }
4608
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004609 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4610 if (adev->adm_lib == NULL) {
4611 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4612 } else {
4613 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4614 adev->adm_init = (adm_init_t)
4615 dlsym(adev->adm_lib, "adm_init");
4616 adev->adm_deinit = (adm_deinit_t)
4617 dlsym(adev->adm_lib, "adm_deinit");
4618 adev->adm_register_input_stream = (adm_register_input_stream_t)
4619 dlsym(adev->adm_lib, "adm_register_input_stream");
4620 adev->adm_register_output_stream = (adm_register_output_stream_t)
4621 dlsym(adev->adm_lib, "adm_register_output_stream");
4622 adev->adm_deregister_stream = (adm_deregister_stream_t)
4623 dlsym(adev->adm_lib, "adm_deregister_stream");
4624 adev->adm_request_focus = (adm_request_focus_t)
4625 dlsym(adev->adm_lib, "adm_request_focus");
4626 adev->adm_abandon_focus = (adm_abandon_focus_t)
4627 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08004628 adev->adm_set_config = (adm_set_config_t)
4629 dlsym(adev->adm_lib, "adm_set_config");
4630 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4631 dlsym(adev->adm_lib, "adm_request_focus_v2");
4632 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4633 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4634 adev->adm_on_routing_change = (adm_on_routing_change_t)
4635 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004636 }
4637
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004638 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004639 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004640
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004641 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004642
Andy Hung31aca912014-03-20 17:14:59 -07004643 if (k_enable_extended_precision)
4644 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004645
Glenn Kasten4f993392014-05-14 07:30:48 -07004646 char value[PROPERTY_VALUE_MAX];
4647 int trial;
4648 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4649 trial = atoi(value);
4650 if (period_size_is_plausible_for_low_latency(trial)) {
4651 pcm_config_low_latency.period_size = trial;
4652 pcm_config_low_latency.start_threshold = trial / 4;
4653 pcm_config_low_latency.avail_min = trial / 4;
4654 configured_low_latency_capture_period_size = trial;
4655 }
4656 }
4657 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4658 trial = atoi(value);
4659 if (period_size_is_plausible_for_low_latency(trial)) {
4660 configured_low_latency_capture_period_size = trial;
4661 }
4662 }
4663
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004664 // commented as full set of app type cfg is sent from platform
4665 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004666 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004667
4668 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4669 af_period_multiplier = atoi(value);
4670 if (af_period_multiplier < 0) {
4671 af_period_multiplier = 2;
4672 } else if (af_period_multiplier > 4) {
4673 af_period_multiplier = 4;
4674 }
4675 ALOGV("new period_multiplier = %d", af_period_multiplier);
4676 }
4677
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004678 audio_extn_tfa_98xx_init(adev);
4679
vivek mehta1a9b7c02015-06-25 11:49:38 -07004680 pthread_mutex_unlock(&adev_init_lock);
4681
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004682 if (adev->adm_init)
4683 adev->adm_data = adev->adm_init();
4684
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004685 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004686 audio_extn_snd_mon_init();
4687 pthread_mutex_lock(&adev->lock);
4688 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
4689 adev->card_status = CARD_STATUS_ONLINE;
4690 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004691
Eric Laurent2bafff12016-03-17 12:17:23 -07004692 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004693 return 0;
4694}
4695
4696static struct hw_module_methods_t hal_module_methods = {
4697 .open = adev_open,
4698};
4699
4700struct audio_module HAL_MODULE_INFO_SYM = {
4701 .common = {
4702 .tag = HARDWARE_MODULE_TAG,
4703 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4704 .hal_api_version = HARDWARE_HAL_API_VERSION,
4705 .id = AUDIO_HARDWARE_MODULE_ID,
4706 .name = "QCOM Audio HAL",
4707 .author = "Code Aurora Forum",
4708 .methods = &hal_module_methods,
4709 },
4710};