blob: 44a0216ddaaa53caa75413747c8d8beef6a0e731 [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
vivek mehtaa68fea62017-06-08 19:04:02 -070070#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070071
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070072#define PROXY_OPEN_RETRY_COUNT 100
73#define PROXY_OPEN_WAIT_TIME 20
74
vivek mehtadae44712015-07-27 14:13:18 -070075#define MIN_CHANNEL_COUNT 1
76#define DEFAULT_CHANNEL_COUNT 2
77
Jean-Michel Trivic0750692015-10-12 12:12:32 -070078#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
79#define MAX_CHANNEL_COUNT 1
80#else
vivek mehtadae44712015-07-27 14:13:18 -070081#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
82#define XSTR(x) STR(x)
83#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070084#endif
vivek mehtadae44712015-07-27 14:13:18 -070085
Haynes Mathew George03c40102016-01-29 17:57:48 -080086#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
87
Glenn Kasten4f993392014-05-14 07:30:48 -070088static unsigned int configured_low_latency_capture_period_size =
89 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
90
Eric Laurent0e46adf2016-12-16 12:49:24 -080091
92#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Phil Burkbc991042017-02-24 08:06:44 -080093#define MMAP_PERIOD_COUNT_MIN 32
94#define MMAP_PERIOD_COUNT_MAX 512
95#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
Eric Laurent0e46adf2016-12-16 12:49:24 -080096
97
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
vivek mehtaa68fea62017-06-08 19:04:02 -0700208struct pcm_config pcm_config_voip = {
209 .channels = 1,
210 .period_count = 2,
211 .format = PCM_FORMAT_S16_LE,
212 .stop_threshold = INT_MAX,
213 .avail_min = 0,
214};
215
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700216#define AFE_PROXY_CHANNEL_COUNT 2
217#define AFE_PROXY_SAMPLING_RATE 48000
218
219#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
220#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
221
222struct pcm_config pcm_config_afe_proxy_playback = {
223 .channels = AFE_PROXY_CHANNEL_COUNT,
224 .rate = AFE_PROXY_SAMPLING_RATE,
225 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
226 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
227 .format = PCM_FORMAT_S16_LE,
228 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
229 .stop_threshold = INT_MAX,
230 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
231};
232
233#define AFE_PROXY_RECORD_PERIOD_SIZE 768
234#define AFE_PROXY_RECORD_PERIOD_COUNT 4
235
236struct pcm_config pcm_config_afe_proxy_record = {
237 .channels = AFE_PROXY_CHANNEL_COUNT,
238 .rate = AFE_PROXY_SAMPLING_RATE,
239 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
240 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
241 .format = PCM_FORMAT_S16_LE,
242 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
243 .stop_threshold = INT_MAX,
244 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
245};
246
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700247const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700248 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
249 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800250 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700251 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700252 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700253 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800254 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700255
Eric Laurentb23d5282013-05-14 15:27:20 -0700256 [USECASE_AUDIO_RECORD] = "audio-record",
257 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800258 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George569b7482017-05-08 14:44:27 -0700259 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700260
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800261 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
262 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700263
Eric Laurentb23d5282013-05-14 15:27:20 -0700264 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700265 [USECASE_VOICE2_CALL] = "voice2-call",
266 [USECASE_VOLTE_CALL] = "volte-call",
267 [USECASE_QCHAT_CALL] = "qchat-call",
268 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800269 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
270 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700271
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700272 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
273 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
274
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700275 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
276 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
vivek mehta781065c2017-04-04 12:55:01 -0700277
278 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
279 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
280 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
281
vivek mehtaa68fea62017-06-08 19:04:02 -0700282 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
283 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Eric Laurentb23d5282013-05-14 15:27:20 -0700284};
285
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800286
287#define STRING_TO_ENUM(string) { #string, string }
288
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800289struct string_to_enum {
290 const char *name;
291 uint32_t value;
292};
293
Haynes Mathew George569b7482017-05-08 14:44:27 -0700294static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800295 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
296 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
297 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George569b7482017-05-08 14:44:27 -0700298 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
299 //TBD - string values for channel_in > 2?
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800300};
301
Haynes Mathew George5191a852013-09-11 14:19:36 -0700302static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700303static struct audio_device *adev = NULL;
Andy Hung9e737de2017-05-22 10:51:22 -0700304static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700305static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700306//cache last MBDRC cal step level
307static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700308
Andy Hung9e737de2017-05-22 10:51:22 -0700309// TODO: Consider moving this to a pthread_once() if we have more
310// static initialization required.
311static bool is_userdebug_or_eng_build() {
312 char value[PROPERTY_VALUE_MAX];
313 (void)property_get("ro.build.type", value, "unknown"); // ignore actual length
314 return strcmp(value, "userdebug") == 0 || strcmp(value, "eng") == 0;
315}
316
Haynes Mathew George03c40102016-01-29 17:57:48 -0800317static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
318 int flags __unused)
319{
320 int dir = 0;
321 switch (uc_id) {
322 case USECASE_AUDIO_RECORD_LOW_LATENCY:
323 dir = 1;
324 case USECASE_AUDIO_PLAYBACK_ULL:
325 break;
326 default:
327 return false;
328 }
329
330 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
331 PCM_PLAYBACK : PCM_CAPTURE);
332 if (adev->adm_is_noirq_avail)
333 return adev->adm_is_noirq_avail(adev->adm_data,
334 adev->snd_card, dev_id, dir);
335 return false;
336}
337
338static void register_out_stream(struct stream_out *out)
339{
340 struct audio_device *adev = out->dev;
341 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
342 return;
343
344 if (!adev->adm_register_output_stream)
345 return;
346
347 adev->adm_register_output_stream(adev->adm_data,
348 out->handle,
349 out->flags);
350
351 if (!adev->adm_set_config)
352 return;
353
354 if (out->realtime) {
355 adev->adm_set_config(adev->adm_data,
356 out->handle,
357 out->pcm, &out->config);
358 }
359}
360
361static void register_in_stream(struct stream_in *in)
362{
363 struct audio_device *adev = in->dev;
364 if (!adev->adm_register_input_stream)
365 return;
366
367 adev->adm_register_input_stream(adev->adm_data,
368 in->capture_handle,
369 in->flags);
370
371 if (!adev->adm_set_config)
372 return;
373
374 if (in->realtime) {
375 adev->adm_set_config(adev->adm_data,
376 in->capture_handle,
377 in->pcm,
378 &in->config);
379 }
380}
381
382static void request_out_focus(struct stream_out *out, long ns)
383{
384 struct audio_device *adev = out->dev;
385
Haynes Mathew George03c40102016-01-29 17:57:48 -0800386 if (adev->adm_request_focus_v2) {
387 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
388 } else if (adev->adm_request_focus) {
389 adev->adm_request_focus(adev->adm_data, out->handle);
390 }
391}
392
393static void request_in_focus(struct stream_in *in, long ns)
394{
395 struct audio_device *adev = in->dev;
396
Haynes Mathew George03c40102016-01-29 17:57:48 -0800397 if (adev->adm_request_focus_v2) {
398 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
399 } else if (adev->adm_request_focus) {
400 adev->adm_request_focus(adev->adm_data, in->capture_handle);
401 }
402}
403
404static void release_out_focus(struct stream_out *out, long ns __unused)
405{
406 struct audio_device *adev = out->dev;
407
408 if (adev->adm_abandon_focus)
409 adev->adm_abandon_focus(adev->adm_data, out->handle);
410}
411
412static void release_in_focus(struct stream_in *in, long ns __unused)
413{
414 struct audio_device *adev = in->dev;
415 if (adev->adm_abandon_focus)
416 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
417}
418
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700419static int parse_snd_card_status(struct str_parms * parms, int * card,
420 card_status_t * status)
421{
422 char value[32]={0};
423 char state[32]={0};
424
425 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
426
427 if (ret < 0)
428 return -1;
429
430 // sscanf should be okay as value is of max length 32.
431 // same as sizeof state.
432 if (sscanf(value, "%d,%s", card, state) < 2)
433 return -1;
434
435 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
436 CARD_STATUS_OFFLINE;
437 return 0;
438}
439
vivek mehta1a9b7c02015-06-25 11:49:38 -0700440__attribute__ ((visibility ("default")))
441bool audio_hw_send_gain_dep_calibration(int level) {
442 bool ret_val = false;
443 ALOGV("%s: enter ... ", __func__);
444
445 pthread_mutex_lock(&adev_init_lock);
446
447 if (adev != NULL && adev->platform != NULL) {
448 pthread_mutex_lock(&adev->lock);
449 ret_val = platform_send_gain_dep_cal(adev->platform, level);
450 pthread_mutex_unlock(&adev->lock);
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700451
452 // if cal set fails, cache level info
453 // if cal set succeds, reset known last cal set
454 if (!ret_val)
455 last_known_cal_step = level;
456 else if (last_known_cal_step != -1)
457 last_known_cal_step = -1;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700458 } else {
459 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
460 }
461
462 pthread_mutex_unlock(&adev_init_lock);
463
464 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
465 return ret_val;
466}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700467
vivek mehtaa8d7c922016-05-25 14:40:44 -0700468__attribute__ ((visibility ("default")))
469int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
470 int table_size) {
471 int ret_val = 0;
472 ALOGV("%s: enter ... ", __func__);
473
474 pthread_mutex_lock(&adev_init_lock);
475 if (adev == NULL) {
476 ALOGW("%s: adev is NULL .... ", __func__);
477 goto done;
478 }
479
480 pthread_mutex_lock(&adev->lock);
481 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
482 pthread_mutex_unlock(&adev->lock);
483done:
484 pthread_mutex_unlock(&adev_init_lock);
485 ALOGV("%s: exit ... ", __func__);
486 return ret_val;
487}
488
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700489static bool is_supported_format(audio_format_t format)
490{
Eric Laurent8251ac82014-07-23 11:00:25 -0700491 switch (format) {
492 case AUDIO_FORMAT_MP3:
493 case AUDIO_FORMAT_AAC_LC:
494 case AUDIO_FORMAT_AAC_HE_V1:
495 case AUDIO_FORMAT_AAC_HE_V2:
496 return true;
497 default:
498 break;
499 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700500 return false;
501}
502
Haynes Mathew George03c40102016-01-29 17:57:48 -0800503static inline bool is_mmap_usecase(audio_usecase_t uc_id)
504{
505 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
506 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
507}
508
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700509static int get_snd_codec_id(audio_format_t format)
510{
511 int id = 0;
512
Eric Laurent8251ac82014-07-23 11:00:25 -0700513 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700514 case AUDIO_FORMAT_MP3:
515 id = SND_AUDIOCODEC_MP3;
516 break;
517 case AUDIO_FORMAT_AAC:
518 id = SND_AUDIOCODEC_AAC;
519 break;
520 default:
521 ALOGE("%s: Unsupported audio format", __func__);
522 }
523
524 return id;
525}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800526
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800527static int audio_ssr_status(struct audio_device *adev)
528{
529 int ret = 0;
530 struct mixer_ctl *ctl;
531 const char *mixer_ctl_name = "Audio SSR Status";
532
533 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
534 ret = mixer_ctl_get_value(ctl, 0);
535 ALOGD("%s: value: %d", __func__, ret);
536 return ret;
537}
538
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800539int enable_audio_route(struct audio_device *adev,
540 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800541{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700542 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800543 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800544
545 if (usecase == NULL)
546 return -EINVAL;
547
548 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
549
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800550 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700551 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800552 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700553 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800554
Yamit Mehtae3b99562016-09-16 22:44:00 +0530555 audio_extn_utils_send_app_type_cfg(adev, usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800556 audio_extn_utils_send_audio_calibration(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800557 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500558 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700559 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700560 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800561
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800562 ALOGV("%s: exit", __func__);
563 return 0;
564}
565
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800566int disable_audio_route(struct audio_device *adev,
567 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800568{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700569 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800570 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800571
572 if (usecase == NULL)
573 return -EINVAL;
574
575 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700576 if (usecase->type == PCM_CAPTURE)
577 snd_device = usecase->in_snd_device;
578 else
579 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800580 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500581 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700582 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700583 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800584
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800585 ALOGV("%s: exit", __func__);
586 return 0;
587}
588
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800589int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700590 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800591{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700592 int i, num_devices = 0;
593 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800594 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800595 if (snd_device < SND_DEVICE_MIN ||
596 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800597 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800598 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800599 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700600
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700601 platform_send_audio_calibration(adev->platform, snd_device);
602
vivek mehtade4849c2016-03-03 17:23:38 -0800603 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700604 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700605 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800606 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700607 }
608
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700609 /* due to the possibility of calibration overwrite between listen
610 and audio, notify sound trigger hal before audio calibration is sent */
611 audio_extn_sound_trigger_update_device_status(snd_device,
612 ST_EVENT_SND_DEVICE_BUSY);
613
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700614 if (audio_extn_spkr_prot_is_enabled())
615 audio_extn_spkr_prot_calib_cancel(adev);
616
zhaoyang yin4211fad2015-06-04 21:13:25 +0800617 audio_extn_dsm_feedback_enable(adev, snd_device, true);
618
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700619 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
620 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
621 audio_extn_spkr_prot_is_enabled()) {
622 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800623 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700624 }
625 if (audio_extn_spkr_prot_start_processing(snd_device)) {
626 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800627 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700628 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700629 } else if (platform_can_split_snd_device(snd_device,
630 &num_devices,
631 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700632 for (i = 0; i < num_devices; i++) {
633 enable_snd_device(adev, new_snd_devices[i]);
634 }
vivek mehtab6506412015-08-07 16:55:17 -0700635 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700636 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800637 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
638 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
639 ALOGE(" %s: Invalid sound device returned", __func__);
640 goto on_error;
641 }
Ed Tam70b5c142016-03-21 19:14:29 -0700642
Eric Laurent2e140aa2016-06-30 17:14:46 -0700643 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800644 audio_route_apply_and_update_path(adev->audio_route, device_name);
645 }
646on_success:
647 adev->snd_dev_ref_cnt[snd_device]++;
648 ret_val = 0;
649on_error:
650 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800651}
652
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800653int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700654 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800655{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700656 int i, num_devices = 0;
657 snd_device_t new_snd_devices[2];
658
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800659 if (snd_device < SND_DEVICE_MIN ||
660 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800661 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800662 return -EINVAL;
663 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700664 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
665 ALOGE("%s: device ref cnt is already 0", __func__);
666 return -EINVAL;
667 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800668 audio_extn_tfa_98xx_disable_speaker(snd_device);
669
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700670 adev->snd_dev_ref_cnt[snd_device]--;
671 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800672 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700673 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
674 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
675 audio_extn_spkr_prot_is_enabled()) {
676 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700677 } else if (platform_can_split_snd_device(snd_device,
678 &num_devices,
679 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700680 for (i = 0; i < num_devices; i++) {
681 disable_snd_device(adev, new_snd_devices[i]);
682 }
vivek mehtab6506412015-08-07 16:55:17 -0700683 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700684 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800685 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
686 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
687 ALOGE(" %s: Invalid sound device returned", __func__);
688 return -EINVAL;
689 }
690
Eric Laurent2e140aa2016-06-30 17:14:46 -0700691 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800692 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700693 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700694 audio_extn_sound_trigger_update_device_status(snd_device,
695 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700696 }
vivek mehtab6506412015-08-07 16:55:17 -0700697
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800698 return 0;
699}
700
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700701/*
702 legend:
703 uc - existing usecase
704 new_uc - new usecase
705 d1, d11, d2 - SND_DEVICE enums
706 a1, a2 - corresponding ANDROID device enums
707 B, B1, B2 - backend strings
708
709case 1
710 uc->dev d1 (a1) B1
711 new_uc->dev d1 (a1), d2 (a2) B1, B2
712
713 resolution: disable and enable uc->dev on d1
714
715case 2
716 uc->dev d1 (a1) B1
717 new_uc->dev d11 (a1) B1
718
719 resolution: need to switch uc since d1 and d11 are related
720 (e.g. speaker and voice-speaker)
721 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
722
723case 3
724 uc->dev d1 (a1) B1
725 new_uc->dev d2 (a2) B2
726
727 resolution: no need to switch uc
728
729case 4
730 uc->dev d1 (a1) B
731 new_uc->dev 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. e.g. if offload is on speaker device using
736 QUAD_MI2S backend and a low-latency stream is started on voice-handset
737 using the same backend, offload must also be switched to voice-handset.
738
739case 5
740 uc->dev d1 (a1) B
741 new_uc->dev d1 (a1), d2 (a2) B
742
743 resolution: disable enable uc-dev on d2 since backends match
744 we cannot enable two streams on two different devices if they
745 share the same backend.
746
747case 6
748 uc->dev d1 a1 B1
749 new_uc->dev d2 a1 B2
750
751 resolution: no need to switch
752
753case 7
754
755 uc->dev d1 (a1), d2 (a2) B1, B2
756 new_uc->dev d1 B1
757
758 resolution: no need to switch
759
760*/
761static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
762 struct audio_usecase *new_uc,
763 snd_device_t new_snd_device)
764{
765 audio_devices_t a1 = uc->stream.out->devices;
766 audio_devices_t a2 = new_uc->stream.out->devices;
767
768 snd_device_t d1 = uc->out_snd_device;
769 snd_device_t d2 = new_snd_device;
770
771 // Treat as a special case when a1 and a2 are not disjoint
772 if ((a1 != a2) && (a1 & a2)) {
773 snd_device_t d3[2];
774 int num_devices = 0;
775 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
776 &num_devices,
777 d3);
778 if (ret < 0) {
779 if (ret != -ENOSYS) {
780 ALOGW("%s failed to split snd_device %d",
781 __func__,
782 popcount(a1) > 1 ? d1 : d2);
783 }
784 goto end;
785 }
786
787 // NB: case 7 is hypothetical and isn't a practical usecase yet.
788 // But if it does happen, we need to give priority to d2 if
789 // the combo devices active on the existing usecase share a backend.
790 // This is because we cannot have a usecase active on a combo device
791 // and a new usecase requests one device in this combo pair.
792 if (platform_check_backends_match(d3[0], d3[1])) {
793 return d2; // case 5
794 } else {
795 return d1; // case 1
796 }
797 } else {
798 if (platform_check_backends_match(d1, d2)) {
799 return d2; // case 2, 4
800 } else {
801 return d1; // case 6, 3
802 }
803 }
804
805end:
806 return d2; // return whatever was calculated before.
807}
808
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700809static void check_and_route_playback_usecases(struct audio_device *adev,
810 struct audio_usecase *uc_info,
811 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700812{
813 struct listnode *node;
814 struct audio_usecase *usecase;
815 bool switch_device[AUDIO_USECASE_MAX];
816 int i, num_uc_to_switch = 0;
817
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700818 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
819 uc_info,
820 snd_device);
David Linee3fe402017-03-13 10:00:42 -0700821
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700822 /*
823 * This function is to make sure that all the usecases that are active on
824 * the hardware codec backend are always routed to any one device that is
825 * handled by the hardware codec.
826 * For example, if low-latency and deep-buffer usecases are currently active
827 * on speaker and out_set_parameters(headset) is received on low-latency
828 * output, then we have to make sure deep-buffer is also switched to headset,
829 * because of the limitation that both the devices cannot be enabled
830 * at the same time as they share the same backend.
831 */
832 /* Disable all the usecases on the shared backend other than the
833 specified usecase */
834 for (i = 0; i < AUDIO_USECASE_MAX; i++)
835 switch_device[i] = false;
836
837 list_for_each(node, &adev->usecase_list) {
838 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700839 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
840 continue;
841
842 if (force_routing ||
843 (usecase->out_snd_device != snd_device &&
844 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
845 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700846 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
847 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700848 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700849 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700850 switch_device[usecase->id] = true;
851 num_uc_to_switch++;
852 }
853 }
854
855 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700856 list_for_each(node, &adev->usecase_list) {
857 usecase = node_to_item(node, struct audio_usecase, list);
858 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700859 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900860 }
861 }
862
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700863 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900864 list_for_each(node, &adev->usecase_list) {
865 usecase = node_to_item(node, struct audio_usecase, list);
866 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700867 d_device = derive_playback_snd_device(usecase, uc_info,
868 snd_device);
869 enable_snd_device(adev, d_device);
870 /* Update the out_snd_device before enabling the audio route */
871 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700872 }
873 }
874
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700875 /* Re-route all the usecases on the shared backend other than the
876 specified usecase to new snd devices */
877 list_for_each(node, &adev->usecase_list) {
878 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700879 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700880 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700881 }
882 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700883 }
884}
885
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700886static void check_and_route_capture_usecases(struct audio_device *adev,
887 struct audio_usecase *uc_info,
888 snd_device_t snd_device)
889{
890 struct listnode *node;
891 struct audio_usecase *usecase;
892 bool switch_device[AUDIO_USECASE_MAX];
893 int i, num_uc_to_switch = 0;
894
vivek mehta4ed66e62016-04-15 23:33:34 -0700895 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
896
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700897 /*
898 * This function is to make sure that all the active capture usecases
899 * are always routed to the same input sound device.
900 * For example, if audio-record and voice-call usecases are currently
901 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
902 * is received for voice call then we have to make sure that audio-record
903 * usecase is also switched to earpiece i.e. voice-dmic-ef,
904 * because of the limitation that two devices cannot be enabled
905 * at the same time if they share the same backend.
906 */
907 for (i = 0; i < AUDIO_USECASE_MAX; i++)
908 switch_device[i] = false;
909
910 list_for_each(node, &adev->usecase_list) {
911 usecase = node_to_item(node, struct audio_usecase, list);
912 if (usecase->type != PCM_PLAYBACK &&
913 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700914 usecase->in_snd_device != snd_device &&
915 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700916 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
917 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700918 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700919 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700920 switch_device[usecase->id] = true;
921 num_uc_to_switch++;
922 }
923 }
924
925 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700926 list_for_each(node, &adev->usecase_list) {
927 usecase = node_to_item(node, struct audio_usecase, list);
928 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700929 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700930 }
931 }
932
933 list_for_each(node, &adev->usecase_list) {
934 usecase = node_to_item(node, struct audio_usecase, list);
935 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700936 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700937 }
938 }
939
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700940 /* Re-route all the usecases on the shared backend other than the
941 specified usecase to new snd devices */
942 list_for_each(node, &adev->usecase_list) {
943 usecase = node_to_item(node, struct audio_usecase, list);
944 /* Update the in_snd_device only before enabling the audio route */
945 if (switch_device[usecase->id] ) {
946 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700947 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700948 }
949 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700950 }
951}
952
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800953/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700954static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800955{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700956 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700957 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800958
959 switch (channels) {
960 /*
961 * Do not handle stereo output in Multi-channel cases
962 * Stereo case is handled in normal playback path
963 */
964 case 6:
965 ALOGV("%s: HDMI supports 5.1", __func__);
966 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
967 break;
968 case 8:
969 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
970 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
971 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
972 break;
973 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700974 ALOGE("HDMI does not support multi channel playback");
975 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800976 break;
977 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700978 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800979}
980
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -0700981static ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
982 uint32_t *supported_sample_rates __unused,
983 uint32_t max_rates __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800984{
Haynes Mathew George569b7482017-05-08 14:44:27 -0700985 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
986 supported_sample_rates,
987 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800988#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -0700989 for (ssize_t i=0; i<count; i++) {
990 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
991 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800992 }
993#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -0700994 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800995}
996
Haynes Mathew George569b7482017-05-08 14:44:27 -0700997static int read_usb_sup_channel_masks(bool is_playback,
998 audio_channel_mask_t *supported_channel_masks,
999 uint32_t max_masks __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001000{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001001 int channels = audio_extn_usb_get_max_channels(is_playback);
1002 if (is_playback) {
1003 supported_channel_masks[0] =
1004 channels < 3 ? audio_channel_out_mask_from_count(channels) :
1005 audio_channel_mask_for_index_assignment_from_count(channels);
1006 } else {
1007 supported_channel_masks[0] = audio_channel_in_mask_from_count(channels);
1008 }
1009 ALOGV("%s: %s supported ch %d", __func__,
1010 is_playback ? "P" : "C", channels);
1011 return 1;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001012}
1013
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001014static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001015 audio_format_t *supported_formats,
1016 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001017{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001018 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001019 switch (bitwidth) {
1020 case 24:
1021 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001022 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001023 break;
1024 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001025 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001026 break;
1027 case 16:
1028 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001029 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001030 break;
1031 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001032 ALOGV("%s: %s supported format %d", __func__,
1033 is_playback ? "P" : "C", bitwidth);
1034 return 1;
1035}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001036
Haynes Mathew George569b7482017-05-08 14:44:27 -07001037static int read_usb_sup_params_and_compare(bool is_playback,
1038 audio_format_t *format,
1039 audio_format_t *supported_formats,
1040 uint32_t max_formats,
1041 audio_channel_mask_t *mask,
1042 audio_channel_mask_t *supported_channel_masks,
1043 uint32_t max_masks,
1044 uint32_t *rate,
1045 uint32_t *supported_sample_rates,
1046 uint32_t max_rates) {
1047 int ret = 0;
1048 int num_formats;
1049 int num_masks;
1050 int num_rates;
1051 int i;
1052
1053 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1054 max_formats);
1055 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1056 max_masks);
1057 num_rates = read_usb_sup_sample_rates(is_playback,
1058 supported_sample_rates, max_rates);
1059
1060#define LUT(table, len, what, dflt) \
1061 for (i=0; i<len && (table[i] != what); i++); \
1062 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1063
1064 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1065 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1066 LUT(supported_sample_rates, num_rates, *rate, 0);
1067
1068#undef LUT
1069 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001070}
1071
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001072static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1073{
1074 struct audio_usecase *usecase;
1075 struct listnode *node;
1076
1077 list_for_each(node, &adev->usecase_list) {
1078 usecase = node_to_item(node, struct audio_usecase, list);
1079 if (usecase->type == VOICE_CALL) {
1080 ALOGV("%s: usecase id %d", __func__, usecase->id);
1081 return usecase->id;
1082 }
1083 }
1084 return USECASE_INVALID;
1085}
1086
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001087struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1088 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001089{
1090 struct audio_usecase *usecase;
1091 struct listnode *node;
1092
1093 list_for_each(node, &adev->usecase_list) {
1094 usecase = node_to_item(node, struct audio_usecase, list);
1095 if (usecase->id == uc_id)
1096 return usecase;
1097 }
1098 return NULL;
1099}
1100
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001101int select_devices(struct audio_device *adev,
1102 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001103{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001104 snd_device_t out_snd_device = SND_DEVICE_NONE;
1105 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001106 struct audio_usecase *usecase = NULL;
1107 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001108 struct audio_usecase *hfp_usecase = NULL;
1109 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001110 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001111 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001112
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001113 usecase = get_usecase_from_list(adev, uc_id);
1114 if (usecase == NULL) {
1115 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1116 return -EINVAL;
1117 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001118
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001119 if ((usecase->type == VOICE_CALL) ||
1120 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001121 out_snd_device = platform_get_output_snd_device(adev->platform,
1122 usecase->stream.out->devices);
1123 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001124 usecase->devices = usecase->stream.out->devices;
1125 } else {
1126 /*
1127 * If the voice call is active, use the sound devices of voice call usecase
1128 * so that it would not result any device switch. All the usecases will
1129 * be switched to new device when select_devices() is called for voice call
1130 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001131 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001132 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001133 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001134 vc_usecase = get_usecase_from_list(adev,
1135 get_voice_usecase_id_from_list(adev));
1136 if ((vc_usecase != NULL) &&
1137 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1138 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001139 in_snd_device = vc_usecase->in_snd_device;
1140 out_snd_device = vc_usecase->out_snd_device;
1141 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001142 } else if (audio_extn_hfp_is_active(adev)) {
1143 hfp_ucid = audio_extn_hfp_get_usecase();
1144 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1145 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1146 in_snd_device = hfp_usecase->in_snd_device;
1147 out_snd_device = hfp_usecase->out_snd_device;
1148 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001149 }
1150 if (usecase->type == PCM_PLAYBACK) {
1151 usecase->devices = usecase->stream.out->devices;
1152 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001153 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001154 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001155 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001156 if (usecase->stream.out == adev->primary_output &&
1157 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001158 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1159 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001160 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001161 select_devices(adev, adev->active_input->usecase);
1162 }
1163 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001164 } else if (usecase->type == PCM_CAPTURE) {
1165 usecase->devices = usecase->stream.in->device;
1166 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001167 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001168 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001169 if (adev->active_input &&
1170 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1171 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001172 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001173 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1174 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
1175 } else if (adev->primary_output) {
1176 out_device = adev->primary_output->devices;
1177 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001178 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001179 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001180 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001181 }
1182 }
1183
1184 if (out_snd_device == usecase->out_snd_device &&
1185 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001186 return 0;
1187 }
1188
Eric Laurent2bafff12016-03-17 12:17:23 -07001189 if (out_snd_device != SND_DEVICE_NONE &&
1190 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1191 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1192 __func__,
1193 use_case_table[uc_id],
1194 adev->last_logged_snd_device[uc_id][0],
1195 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1196 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1197 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1198 -1,
1199 out_snd_device,
1200 platform_get_snd_device_name(out_snd_device),
1201 platform_get_snd_device_acdb_id(out_snd_device));
1202 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1203 }
1204 if (in_snd_device != SND_DEVICE_NONE &&
1205 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1206 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1207 __func__,
1208 use_case_table[uc_id],
1209 adev->last_logged_snd_device[uc_id][1],
1210 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1211 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1212 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1213 -1,
1214 in_snd_device,
1215 platform_get_snd_device_name(in_snd_device),
1216 platform_get_snd_device_acdb_id(in_snd_device));
1217 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1218 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001219
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001220 /*
1221 * Limitation: While in call, to do a device switch we need to disable
1222 * and enable both RX and TX devices though one of them is same as current
1223 * device.
1224 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001225 if ((usecase->type == VOICE_CALL) &&
1226 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1227 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001228 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001229 /* Disable sidetone only if voice call already exists */
1230 if (voice_is_call_state_active(adev))
1231 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001232 }
1233
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001234 /* Disable current sound devices */
1235 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001236 disable_audio_route(adev, usecase);
1237 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001238 }
1239
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001240 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001241 disable_audio_route(adev, usecase);
1242 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001243 }
1244
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001245 /* Applicable only on the targets that has external modem.
1246 * New device information should be sent to modem before enabling
1247 * the devices to reduce in-call device switch time.
1248 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001249 if ((usecase->type == VOICE_CALL) &&
1250 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1251 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001252 status = platform_switch_voice_call_enable_device_config(adev->platform,
1253 out_snd_device,
1254 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001255 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001256
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001257 /* Enable new sound devices */
1258 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001259 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1260 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001261 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001262 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001263 }
1264
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001265 if (in_snd_device != SND_DEVICE_NONE) {
1266 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001267 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001268 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001269
Eric Laurentb23d5282013-05-14 15:27:20 -07001270 if (usecase->type == VOICE_CALL)
1271 status = platform_switch_voice_call_device_post(adev->platform,
1272 out_snd_device,
1273 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001274
sangwoo170731f2013-06-08 15:36:36 +09001275 usecase->in_snd_device = in_snd_device;
1276 usecase->out_snd_device = out_snd_device;
1277
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001278 audio_extn_tfa_98xx_set_mode();
1279
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001280 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001281
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001282 /* Applicable only on the targets that has external modem.
1283 * Enable device command should be sent to modem only after
1284 * enabling voice call mixer controls
1285 */
vivek mehta765eb642015-08-07 19:46:06 -07001286 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001287 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1288 out_snd_device,
1289 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001290 /* Enable sidetone only if voice call already exists */
1291 if (voice_is_call_state_active(adev))
1292 voice_set_sidetone(adev, out_snd_device, true);
1293 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001294
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001295 return status;
1296}
1297
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001298static int stop_input_stream(struct stream_in *in)
1299{
1300 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001301 struct audio_usecase *uc_info;
1302 struct audio_device *adev = in->dev;
1303
Eric Laurentc8400632013-02-14 19:04:54 -08001304 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001305
Eric Laurent994a6932013-07-17 11:51:42 -07001306 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001307 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001308 uc_info = get_usecase_from_list(adev, in->usecase);
1309 if (uc_info == NULL) {
1310 ALOGE("%s: Could not find the usecase (%d) in the list",
1311 __func__, in->usecase);
1312 return -EINVAL;
1313 }
1314
vivek mehta781065c2017-04-04 12:55:01 -07001315 /* Close in-call recording streams */
1316 voice_check_and_stop_incall_rec_usecase(adev, in);
1317
Eric Laurent150dbfe2013-02-27 14:31:02 -08001318 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001319 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001320
1321 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001322 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001323
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001324 list_remove(&uc_info->list);
1325 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001326
Eric Laurent994a6932013-07-17 11:51:42 -07001327 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001328 return ret;
1329}
1330
1331int start_input_stream(struct stream_in *in)
1332{
1333 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001334 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001335 struct audio_usecase *uc_info;
1336 struct audio_device *adev = in->dev;
1337
Eric Laurent994a6932013-07-17 11:51:42 -07001338 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001339
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001340 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1341 return -EIO;
1342
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001343 if (in->card_status == CARD_STATUS_OFFLINE ||
1344 adev->card_status == CARD_STATUS_OFFLINE) {
1345 ALOGW("in->card_status or adev->card_status offline, try again");
1346 ret = -EAGAIN;
1347 goto error_config;
1348 }
1349
vivek mehta781065c2017-04-04 12:55:01 -07001350 /* Check if source matches incall recording usecase criteria */
1351 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1352 if (ret)
1353 goto error_config;
1354 else
1355 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1356
Eric Laurentb23d5282013-05-14 15:27:20 -07001357 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001358 if (in->pcm_device_id < 0) {
1359 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1360 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001361 ret = -EINVAL;
1362 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001363 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001364
1365 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001366 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1367 uc_info->id = in->usecase;
1368 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001369 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001370 uc_info->devices = in->device;
1371 uc_info->in_snd_device = SND_DEVICE_NONE;
1372 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001373
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001374 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001375
1376 audio_extn_perf_lock_acquire();
1377
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001378 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001379
Eric Laurent0e46adf2016-12-16 12:49:24 -08001380 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001381 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001382 ALOGE("%s: pcm stream not ready", __func__);
1383 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001384 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001385 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001386 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001387 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1388 goto error_open;
1389 }
1390 } else {
1391 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1392 unsigned int pcm_open_retry_count = 0;
1393
1394 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1395 flags |= PCM_MMAP | PCM_NOIRQ;
1396 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1397 } else if (in->realtime) {
1398 flags |= PCM_MMAP | PCM_NOIRQ;
1399 }
1400
1401 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1402 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1403
1404 while (1) {
1405 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1406 flags, &in->config);
1407 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1408 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1409 if (in->pcm != NULL) {
1410 pcm_close(in->pcm);
1411 in->pcm = NULL;
1412 }
1413 if (pcm_open_retry_count-- == 0) {
1414 ret = -EIO;
1415 goto error_open;
1416 }
1417 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1418 continue;
1419 }
1420 break;
1421 }
1422
1423 ALOGV("%s: pcm_prepare", __func__);
1424 ret = pcm_prepare(in->pcm);
1425 if (ret < 0) {
1426 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001427 pcm_close(in->pcm);
1428 in->pcm = NULL;
1429 goto error_open;
1430 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001431 if (in->realtime) {
1432 ret = pcm_start(in->pcm);
1433 if (ret < 0) {
1434 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1435 pcm_close(in->pcm);
1436 in->pcm = NULL;
1437 goto error_open;
1438 }
1439 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001440 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001441 register_in_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001442 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001443 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001444
Eric Laurent0e46adf2016-12-16 12:49:24 -08001445 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001446
1447error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001448 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001449 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001450
1451error_config:
1452 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001453 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001454 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001455}
1456
Eric Laurenta1478072015-09-21 17:21:52 -07001457void lock_input_stream(struct stream_in *in)
1458{
1459 pthread_mutex_lock(&in->pre_lock);
1460 pthread_mutex_lock(&in->lock);
1461 pthread_mutex_unlock(&in->pre_lock);
1462}
1463
1464void lock_output_stream(struct stream_out *out)
1465{
1466 pthread_mutex_lock(&out->pre_lock);
1467 pthread_mutex_lock(&out->lock);
1468 pthread_mutex_unlock(&out->pre_lock);
1469}
1470
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001471/* must be called with out->lock locked */
1472static int send_offload_cmd_l(struct stream_out* out, int command)
1473{
1474 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1475
1476 ALOGVV("%s %d", __func__, command);
1477
1478 cmd->cmd = command;
1479 list_add_tail(&out->offload_cmd_list, &cmd->node);
1480 pthread_cond_signal(&out->offload_cond);
1481 return 0;
1482}
1483
1484/* must be called iwth out->lock locked */
1485static void stop_compressed_output_l(struct stream_out *out)
1486{
1487 out->offload_state = OFFLOAD_STATE_IDLE;
1488 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001489 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001490 if (out->compr != NULL) {
1491 compress_stop(out->compr);
1492 while (out->offload_thread_blocked) {
1493 pthread_cond_wait(&out->cond, &out->lock);
1494 }
1495 }
1496}
1497
1498static void *offload_thread_loop(void *context)
1499{
1500 struct stream_out *out = (struct stream_out *) context;
1501 struct listnode *item;
1502
1503 out->offload_state = OFFLOAD_STATE_IDLE;
1504 out->playback_started = 0;
1505
1506 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1507 set_sched_policy(0, SP_FOREGROUND);
1508 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1509
1510 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001511 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001512 for (;;) {
1513 struct offload_cmd *cmd = NULL;
1514 stream_callback_event_t event;
1515 bool send_callback = false;
1516
1517 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1518 __func__, list_empty(&out->offload_cmd_list),
1519 out->offload_state);
1520 if (list_empty(&out->offload_cmd_list)) {
1521 ALOGV("%s SLEEPING", __func__);
1522 pthread_cond_wait(&out->offload_cond, &out->lock);
1523 ALOGV("%s RUNNING", __func__);
1524 continue;
1525 }
1526
1527 item = list_head(&out->offload_cmd_list);
1528 cmd = node_to_item(item, struct offload_cmd, node);
1529 list_remove(item);
1530
1531 ALOGVV("%s STATE %d CMD %d out->compr %p",
1532 __func__, out->offload_state, cmd->cmd, out->compr);
1533
1534 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1535 free(cmd);
1536 break;
1537 }
1538
1539 if (out->compr == NULL) {
1540 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001541 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001542 pthread_cond_signal(&out->cond);
1543 continue;
1544 }
1545 out->offload_thread_blocked = true;
1546 pthread_mutex_unlock(&out->lock);
1547 send_callback = false;
1548 switch(cmd->cmd) {
1549 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1550 compress_wait(out->compr, -1);
1551 send_callback = true;
1552 event = STREAM_CBK_EVENT_WRITE_READY;
1553 break;
1554 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001555 compress_next_track(out->compr);
1556 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001557 send_callback = true;
1558 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001559 /* Resend the metadata for next iteration */
1560 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001561 break;
1562 case OFFLOAD_CMD_DRAIN:
1563 compress_drain(out->compr);
1564 send_callback = true;
1565 event = STREAM_CBK_EVENT_DRAIN_READY;
1566 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001567 case OFFLOAD_CMD_ERROR:
1568 send_callback = true;
1569 event = STREAM_CBK_EVENT_ERROR;
1570 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001571 default:
1572 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1573 break;
1574 }
Eric Laurenta1478072015-09-21 17:21:52 -07001575 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001576 out->offload_thread_blocked = false;
1577 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001578 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001579 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001580 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001581 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001582 free(cmd);
1583 }
1584
1585 pthread_cond_signal(&out->cond);
1586 while (!list_empty(&out->offload_cmd_list)) {
1587 item = list_head(&out->offload_cmd_list);
1588 list_remove(item);
1589 free(node_to_item(item, struct offload_cmd, node));
1590 }
1591 pthread_mutex_unlock(&out->lock);
1592
1593 return NULL;
1594}
1595
1596static int create_offload_callback_thread(struct stream_out *out)
1597{
1598 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1599 list_init(&out->offload_cmd_list);
1600 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1601 offload_thread_loop, out);
1602 return 0;
1603}
1604
1605static int destroy_offload_callback_thread(struct stream_out *out)
1606{
Eric Laurenta1478072015-09-21 17:21:52 -07001607 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001608 stop_compressed_output_l(out);
1609 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1610
1611 pthread_mutex_unlock(&out->lock);
1612 pthread_join(out->offload_thread, (void **) NULL);
1613 pthread_cond_destroy(&out->offload_cond);
1614
1615 return 0;
1616}
1617
Eric Laurent07eeafd2013-10-06 12:52:49 -07001618static bool allow_hdmi_channel_config(struct audio_device *adev)
1619{
1620 struct listnode *node;
1621 struct audio_usecase *usecase;
1622 bool ret = true;
1623
1624 list_for_each(node, &adev->usecase_list) {
1625 usecase = node_to_item(node, struct audio_usecase, list);
1626 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1627 /*
1628 * If voice call is already existing, do not proceed further to avoid
1629 * disabling/enabling both RX and TX devices, CSD calls, etc.
1630 * Once the voice call done, the HDMI channels can be configured to
1631 * max channels of remaining use cases.
1632 */
1633 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001634 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001635 __func__);
1636 ret = false;
1637 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001638 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1639 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001640 "no change in HDMI channels", __func__);
1641 ret = false;
1642 break;
1643 }
1644 }
1645 }
1646 return ret;
1647}
1648
1649static int check_and_set_hdmi_channels(struct audio_device *adev,
1650 unsigned int channels)
1651{
1652 struct listnode *node;
1653 struct audio_usecase *usecase;
1654
1655 /* Check if change in HDMI channel config is allowed */
1656 if (!allow_hdmi_channel_config(adev))
1657 return 0;
1658
1659 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001660 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001661 return 0;
1662 }
1663
1664 platform_set_hdmi_channels(adev->platform, channels);
1665 adev->cur_hdmi_channels = channels;
1666
1667 /*
1668 * Deroute all the playback streams routed to HDMI so that
1669 * the back end is deactivated. Note that backend will not
1670 * be deactivated if any one stream is connected to it.
1671 */
1672 list_for_each(node, &adev->usecase_list) {
1673 usecase = node_to_item(node, struct audio_usecase, list);
1674 if (usecase->type == PCM_PLAYBACK &&
1675 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001676 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001677 }
1678 }
1679
1680 /*
1681 * Enable all the streams disabled above. Now the HDMI backend
1682 * will be activated with new channel configuration
1683 */
1684 list_for_each(node, &adev->usecase_list) {
1685 usecase = node_to_item(node, struct audio_usecase, list);
1686 if (usecase->type == PCM_PLAYBACK &&
1687 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001688 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001689 }
1690 }
1691
1692 return 0;
1693}
1694
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001695static int stop_output_stream(struct stream_out *out)
1696{
1697 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001698 struct audio_usecase *uc_info;
1699 struct audio_device *adev = out->dev;
1700
Eric Laurent994a6932013-07-17 11:51:42 -07001701 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001702 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001703 uc_info = get_usecase_from_list(adev, out->usecase);
1704 if (uc_info == NULL) {
1705 ALOGE("%s: Could not find the usecase (%d) in the list",
1706 __func__, out->usecase);
1707 return -EINVAL;
1708 }
1709
Haynes Mathew George41f86652014-06-17 14:22:15 -07001710 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1711 if (adev->visualizer_stop_output != NULL)
1712 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1713 if (adev->offload_effects_stop_output != NULL)
1714 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1715 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001716
Eric Laurent150dbfe2013-02-27 14:31:02 -08001717 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001718 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001719
1720 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001721 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001722
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001723 list_remove(&uc_info->list);
1724 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001725
Eric Laurent0499d4f2014-08-25 22:39:29 -05001726 audio_extn_extspk_update(adev->extspk);
1727
Eric Laurent07eeafd2013-10-06 12:52:49 -07001728 /* Must be called after removing the usecase from list */
1729 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1730 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1731
Eric Laurent994a6932013-07-17 11:51:42 -07001732 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001733 return ret;
1734}
1735
1736int start_output_stream(struct stream_out *out)
1737{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001738 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001739 struct audio_usecase *uc_info;
1740 struct audio_device *adev = out->dev;
1741
Eric Laurent994a6932013-07-17 11:51:42 -07001742 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001743 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001744
1745 if (out->card_status == CARD_STATUS_OFFLINE ||
1746 adev->card_status == CARD_STATUS_OFFLINE) {
1747 ALOGW("out->card_status or adev->card_status offline, try again");
1748 ret = -EAGAIN;
1749 goto error_config;
1750 }
1751
Eric Laurentb23d5282013-05-14 15:27:20 -07001752 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001753 if (out->pcm_device_id < 0) {
1754 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1755 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001756 ret = -EINVAL;
1757 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001758 }
1759
1760 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1761 uc_info->id = out->usecase;
1762 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001763 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001764 uc_info->devices = out->devices;
1765 uc_info->in_snd_device = SND_DEVICE_NONE;
1766 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001767
Eric Laurent07eeafd2013-10-06 12:52:49 -07001768 /* This must be called before adding this usecase to the list */
1769 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1770 check_and_set_hdmi_channels(adev, out->config.channels);
1771
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001772 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001773
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001774 audio_extn_perf_lock_acquire();
1775
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001776 select_devices(adev, out->usecase);
1777
Eric Laurent0499d4f2014-08-25 22:39:29 -05001778 audio_extn_extspk_update(adev->extspk);
1779
Andy Hung31aca912014-03-20 17:14:59 -07001780 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001781 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001782 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1783 out->pcm = NULL;
1784 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1785 COMPRESS_IN, &out->compr_config);
1786 if (out->compr && !is_compress_ready(out->compr)) {
1787 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1788 compress_close(out->compr);
1789 out->compr = NULL;
1790 ret = -EIO;
1791 goto error_open;
1792 }
1793 if (out->offload_callback)
1794 compress_nonblock(out->compr, out->non_blocking);
1795
1796 if (adev->visualizer_start_output != NULL)
1797 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1798 if (adev->offload_effects_start_output != NULL)
1799 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
1800 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001801 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001802 ALOGE("%s: pcm stream not ready", __func__);
1803 goto error_open;
1804 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001805 ret = pcm_start(out->pcm);
1806 if (ret < 0) {
1807 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1808 goto error_open;
1809 }
1810 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07001811 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001812 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001813
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001814 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1815 flags |= PCM_MMAP | PCM_NOIRQ;
1816 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001817 } else if (out->realtime) {
1818 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07001819 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001820
1821 while (1) {
1822 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1823 flags, &out->config);
1824 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1825 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1826 if (out->pcm != NULL) {
1827 pcm_close(out->pcm);
1828 out->pcm = NULL;
1829 }
1830 if (pcm_open_retry_count-- == 0) {
1831 ret = -EIO;
1832 goto error_open;
1833 }
1834 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1835 continue;
1836 }
1837 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001838 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001839 ALOGV("%s: pcm_prepare", __func__);
1840 if (pcm_is_ready(out->pcm)) {
1841 ret = pcm_prepare(out->pcm);
1842 if (ret < 0) {
1843 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1844 pcm_close(out->pcm);
1845 out->pcm = NULL;
1846 goto error_open;
1847 }
1848 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001849 if (out->realtime) {
1850 ret = pcm_start(out->pcm);
1851 if (ret < 0) {
1852 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1853 pcm_close(out->pcm);
1854 out->pcm = NULL;
1855 goto error_open;
1856 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001857 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001858 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001859 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001860 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001861 audio_extn_tfa_98xx_enable_speaker();
1862
Eric Laurent994a6932013-07-17 11:51:42 -07001863 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001864 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001865error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001866 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001867 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001868error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001869 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001870}
1871
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001872static int check_input_parameters(uint32_t sample_rate,
1873 audio_format_t format,
1874 int channel_count)
1875{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001876 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
1877 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
1878 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED)) {
vivek mehtadae44712015-07-27 14:13:18 -07001879 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1880 return -EINVAL;
1881 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001882
vivek mehtadae44712015-07-27 14:13:18 -07001883 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > MAX_CHANNEL_COUNT)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001884 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
vivek mehtadae44712015-07-27 14:13:18 -07001885 channel_count, MIN_CHANNEL_COUNT, MAX_CHANNEL_COUNT);
1886 return -EINVAL;
1887 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001888
1889 switch (sample_rate) {
1890 case 8000:
1891 case 11025:
1892 case 12000:
1893 case 16000:
1894 case 22050:
1895 case 24000:
1896 case 32000:
1897 case 44100:
1898 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001899 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001900 break;
1901 default:
vivek mehtadae44712015-07-27 14:13:18 -07001902 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001903 return -EINVAL;
1904 }
1905
1906 return 0;
1907}
1908
vivek mehtaa68fea62017-06-08 19:04:02 -07001909static size_t get_stream_buffer_size(size_t duration_ms,
1910 uint32_t sample_rate,
1911 audio_format_t format,
1912 int channel_count,
1913 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001914{
1915 size_t size = 0;
1916
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001917 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1918 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001919
vivek mehtaa68fea62017-06-08 19:04:02 -07001920 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001921 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001922 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07001923
1924 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001925
Glenn Kasten4f993392014-05-14 07:30:48 -07001926 /* make sure the size is multiple of 32 bytes
1927 * At 48 kHz mono 16-bit PCM:
1928 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1929 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1930 */
1931 size += 0x1f;
1932 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001933
1934 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001935}
1936
1937static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1938{
1939 struct stream_out *out = (struct stream_out *)stream;
1940
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001941 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001942}
1943
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001944static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001945{
1946 return -ENOSYS;
1947}
1948
1949static size_t out_get_buffer_size(const struct audio_stream *stream)
1950{
1951 struct stream_out *out = (struct stream_out *)stream;
1952
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001953 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1954 return out->compr_config.fragment_size;
1955 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001956 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07001957 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001958}
1959
1960static uint32_t out_get_channels(const struct audio_stream *stream)
1961{
1962 struct stream_out *out = (struct stream_out *)stream;
1963
1964 return out->channel_mask;
1965}
1966
1967static audio_format_t out_get_format(const struct audio_stream *stream)
1968{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001969 struct stream_out *out = (struct stream_out *)stream;
1970
1971 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001972}
1973
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001974static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001975{
1976 return -ENOSYS;
1977}
1978
1979static int out_standby(struct audio_stream *stream)
1980{
1981 struct stream_out *out = (struct stream_out *)stream;
1982 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08001983 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001984
Eric Laurent994a6932013-07-17 11:51:42 -07001985 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001986 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001987
Eric Laurenta1478072015-09-21 17:21:52 -07001988 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001989 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001990 if (adev->adm_deregister_stream)
1991 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001992 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001993 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001994 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1995 if (out->pcm) {
1996 pcm_close(out->pcm);
1997 out->pcm = NULL;
1998 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001999 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002000 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002001 out->playback_started = false;
2002 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002003 } else {
2004 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002005 out->gapless_mdata.encoder_delay = 0;
2006 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002007 if (out->compr != NULL) {
2008 compress_close(out->compr);
2009 out->compr = NULL;
2010 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002011 }
Phil Burkbc991042017-02-24 08:06:44 -08002012 if (do_stop) {
2013 stop_output_stream(out);
2014 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002015 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002016 }
2017 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002018 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002019 return 0;
2020}
2021
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002022static int out_on_error(struct audio_stream *stream)
2023{
2024 struct stream_out *out = (struct stream_out *)stream;
2025 struct audio_device *adev = out->dev;
2026 bool do_standby = false;
2027
2028 lock_output_stream(out);
2029 if (!out->standby) {
2030 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2031 stop_compressed_output_l(out);
2032 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2033 } else
2034 do_standby = true;
2035 }
2036 pthread_mutex_unlock(&out->lock);
2037
2038 if (do_standby)
2039 return out_standby(&out->stream.common);
2040
2041 return 0;
2042}
2043
Andy Hung7401c7c2016-09-21 12:41:21 -07002044static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002045{
Andy Hung7401c7c2016-09-21 12:41:21 -07002046 struct stream_out *out = (struct stream_out *)stream;
2047
2048 // We try to get the lock for consistency,
2049 // but it isn't necessary for these variables.
2050 // If we're not in standby, we may be blocked on a write.
2051 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2052 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2053 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2054
2055 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002056 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002057 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002058
2059 // dump error info
2060 (void)error_log_dump(
2061 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hungfc044e12017-03-20 09:24:22 -07002062 // dump power info (out->power_log may be null)
Andy Hung62c9b882017-03-22 16:43:42 -07002063 (void)power_log_dump(
2064 out->power_log, fd, " " /* prefix */, POWER_LOG_LINES, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002065 return 0;
2066}
2067
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002068static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2069{
2070 int ret = 0;
2071 char value[32];
2072 struct compr_gapless_mdata tmp_mdata;
2073
2074 if (!out || !parms) {
2075 return -EINVAL;
2076 }
2077
2078 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2079 if (ret >= 0) {
2080 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2081 } else {
2082 return -EINVAL;
2083 }
2084
2085 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2086 if (ret >= 0) {
2087 tmp_mdata.encoder_padding = atoi(value);
2088 } else {
2089 return -EINVAL;
2090 }
2091
2092 out->gapless_mdata = tmp_mdata;
2093 out->send_new_metadata = 1;
2094 ALOGV("%s new encoder delay %u and padding %u", __func__,
2095 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2096
2097 return 0;
2098}
2099
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002100static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2101{
2102 return out == adev->primary_output || out == adev->voice_tx_output;
2103}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002104
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002105static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2106{
2107 struct stream_out *out = (struct stream_out *)stream;
2108 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002109 struct audio_usecase *usecase;
2110 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002111 struct str_parms *parms;
2112 char value[32];
2113 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002114 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002115 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002116
Eric Laurent2e140aa2016-06-30 17:14:46 -07002117 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002118 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002119 parms = str_parms_create_str(kvpairs);
2120 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2121 if (ret >= 0) {
2122 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07002123 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002124 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002125
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002126 /*
2127 * When HDMI cable is unplugged the music playback is paused and
2128 * the policy manager sends routing=0. But the audioflinger
2129 * continues to write data until standby time (3sec).
2130 * As the HDMI core is turned off, the write gets blocked.
2131 * Avoid this by routing audio to speaker until standby.
2132 */
2133 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2134 val == AUDIO_DEVICE_NONE) {
2135 val = AUDIO_DEVICE_OUT_SPEAKER;
2136 }
2137
2138 /*
2139 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002140 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002141 * the select_devices(). But how do we undo this?
2142 *
2143 * For example, music playback is active on headset (deep-buffer usecase)
2144 * and if we go to ringtones and select a ringtone, low-latency usecase
2145 * will be started on headset+speaker. As we can't enable headset+speaker
2146 * and headset devices at the same time, select_devices() switches the music
2147 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2148 * So when the ringtone playback is completed, how do we undo the same?
2149 *
2150 * We are relying on the out_set_parameters() call on deep-buffer output,
2151 * once the ringtone playback is ended.
2152 * NOTE: We should not check if the current devices are same as new devices.
2153 * Because select_devices() must be called to switch back the music
2154 * playback to headset.
2155 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002156 audio_devices_t new_dev = val;
2157 if (new_dev != AUDIO_DEVICE_NONE) {
2158 bool same_dev = out->devices == new_dev;
2159 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002160
Eric Laurenta7657192014-10-09 21:09:33 -07002161 if (output_drives_call(adev, out)) {
2162 if (!voice_is_in_call(adev)) {
2163 if (adev->mode == AUDIO_MODE_IN_CALL) {
2164 adev->current_call_output = out;
2165 ret = voice_start_call(adev);
2166 }
2167 } else {
2168 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002169 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002170 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002171 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002172
2173 if (!out->standby) {
2174 if (!same_dev) {
2175 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002176 // inform adm before actual routing to prevent glitches.
2177 if (adev->adm_on_routing_change) {
2178 adev->adm_on_routing_change(adev->adm_data,
2179 out->handle);
2180 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002181 }
2182 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002183 audio_extn_tfa_98xx_update();
vivek mehta0d3637a2016-07-24 09:32:02 -07002184 }
2185
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002186 }
2187
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002188 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002189 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002190
2191 /*handles device and call state changes*/
2192 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002193 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002194
2195 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2196 parse_compress_metadata(out, parms);
2197 }
2198
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002199 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002200 ALOGV("%s: exit: code(%d)", __func__, status);
2201 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002202}
2203
Haynes Mathew George569b7482017-05-08 14:44:27 -07002204static bool stream_get_parameter_channels(struct str_parms *query,
2205 struct str_parms *reply,
2206 audio_channel_mask_t *supported_channel_masks) {
2207 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002208 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002209 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002210 size_t i, j;
2211
2212 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2213 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002214 value[0] = '\0';
2215 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002216 while (supported_channel_masks[i] != 0) {
2217 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2218 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002219 if (!first) {
2220 strcat(value, "|");
2221 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002222 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002223 first = false;
2224 break;
2225 }
2226 }
2227 i++;
2228 }
2229 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002230 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002231 return ret >= 0;
2232}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002233
Haynes Mathew George569b7482017-05-08 14:44:27 -07002234static bool stream_get_parameter_formats(struct str_parms *query,
2235 struct str_parms *reply,
2236 audio_format_t *supported_formats) {
2237 int ret = -1;
2238 char value[256];
2239 int i;
2240
2241 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2242 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002243 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002244 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002245 case AUDIO_FORMAT_PCM_16_BIT:
2246 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2247 break;
2248 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2249 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2250 break;
2251 case AUDIO_FORMAT_PCM_32_BIT:
2252 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2253 break;
2254 default:
2255 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002256 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002257 break;
2258 }
2259 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002260 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002261 return ret >= 0;
2262}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002263
Haynes Mathew George569b7482017-05-08 14:44:27 -07002264static bool stream_get_parameter_rates(struct str_parms *query,
2265 struct str_parms *reply,
2266 uint32_t *supported_sample_rates) {
2267
2268 int i;
2269 char value[256];
2270 int ret = -1;
2271 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2272 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002273 value[0] = '\0';
2274 i=0;
2275 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002276 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002277 int avail = sizeof(value) - cursor;
2278 ret = snprintf(value + cursor, avail, "%s%d",
2279 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002280 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002281 if (ret < 0 || ret >= avail) {
2282 // if cursor is at the last element of the array
2283 // overwrite with \0 is duplicate work as
2284 // snprintf already put a \0 in place.
2285 // else
2286 // we had space to write the '|' at value[cursor]
2287 // (which will be overwritten) or no space to fill
2288 // the first element (=> cursor == 0)
2289 value[cursor] = '\0';
2290 break;
2291 }
2292 cursor += ret;
2293 ++i;
2294 }
2295 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2296 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002297 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002298 return ret >= 0;
2299}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002300
Haynes Mathew George569b7482017-05-08 14:44:27 -07002301static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2302{
2303 struct stream_out *out = (struct stream_out *)stream;
2304 struct str_parms *query = str_parms_create_str(keys);
2305 char *str;
2306 struct str_parms *reply = str_parms_create();
2307 bool replied = false;
2308 ALOGV("%s: enter: keys - %s", __func__, keys);
2309
2310 replied |= stream_get_parameter_channels(query, reply,
2311 &out->supported_channel_masks[0]);
2312 replied |= stream_get_parameter_formats(query, reply,
2313 &out->supported_formats[0]);
2314 replied |= stream_get_parameter_rates(query, reply,
2315 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002316 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002317 str = str_parms_to_str(reply);
2318 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002319 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002320 }
2321 str_parms_destroy(query);
2322 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002323 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002324 return str;
2325}
2326
2327static uint32_t out_get_latency(const struct audio_stream_out *stream)
2328{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002329 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002330 struct stream_out *out = (struct stream_out *)stream;
2331
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002332 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2333 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002334 else if ((out->realtime) ||
2335 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002336 // since the buffer won't be filled up faster than realtime,
2337 // return a smaller number
2338 period_ms = (out->af_period_multiplier * out->config.period_size *
2339 1000) / (out->config.rate);
2340 hw_delay = platform_render_latency(out->usecase)/1000;
2341 return period_ms + hw_delay;
2342 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002343
2344 return (out->config.period_count * out->config.period_size * 1000) /
2345 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002346}
2347
2348static int out_set_volume(struct audio_stream_out *stream, float left,
2349 float right)
2350{
Eric Laurenta9024de2013-04-04 09:19:12 -07002351 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002352 int volume[2];
2353
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002354 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002355 /* only take left channel into account: the API is for stereo anyway */
2356 out->muted = (left == 0.0f);
2357 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002358 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2359 const char *mixer_ctl_name = "Compress Playback Volume";
2360 struct audio_device *adev = out->dev;
2361 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002362 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2363 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002364 /* try with the control based on device id */
2365 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2366 PCM_PLAYBACK);
2367 char ctl_name[128] = {0};
2368 snprintf(ctl_name, sizeof(ctl_name),
2369 "Compress Playback %d Volume", pcm_device_id);
2370 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2371 if (!ctl) {
2372 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2373 return -EINVAL;
2374 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002375 }
2376 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2377 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2378 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2379 return 0;
vivek mehtaa68fea62017-06-08 19:04:02 -07002380 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
2381 int gain_cfg[4];
2382 const char *mixer_ctl_name = "App Type Gain";
2383 struct audio_device *adev = out->dev;
2384 struct mixer_ctl *ctl;
2385 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2386 if (!ctl) {
2387 ALOGE("%s: Could not get volume ctl mixer %s", __func__,
2388 mixer_ctl_name);
2389 return -EINVAL;
2390 }
2391 gain_cfg[0] = 0;
2392 gain_cfg[1] = out->app_type_cfg.app_type;
2393 gain_cfg[2] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2394 gain_cfg[3] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2395 mixer_ctl_set_array(ctl, gain_cfg, sizeof(gain_cfg)/sizeof(gain_cfg[0]));
2396 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002397 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002398
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002399 return -ENOSYS;
2400}
2401
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002402// note: this call is safe only if the stream_cb is
2403// removed first in close_output_stream (as is done now).
2404static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2405{
2406 if (!stream || !parms)
2407 return;
2408
2409 struct stream_out *out = (struct stream_out *)stream;
2410 struct audio_device *adev = out->dev;
2411
2412 card_status_t status;
2413 int card;
2414 if (parse_snd_card_status(parms, &card, &status) < 0)
2415 return;
2416
2417 pthread_mutex_lock(&adev->lock);
2418 bool valid_cb = (card == adev->snd_card);
2419 pthread_mutex_unlock(&adev->lock);
2420
2421 if (!valid_cb)
2422 return;
2423
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002424 lock_output_stream(out);
2425 if (out->card_status != status)
2426 out->card_status = status;
2427 pthread_mutex_unlock(&out->lock);
2428
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002429 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2430 use_case_table[out->usecase],
2431 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2432
2433 if (status == CARD_STATUS_OFFLINE)
2434 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002435
2436 return;
2437}
2438
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002439#ifdef NO_AUDIO_OUT
2440static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002441 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002442{
2443 struct stream_out *out = (struct stream_out *)stream;
2444
2445 /* No Output device supported other than BT for playback.
2446 * Sleep for the amount of buffer duration
2447 */
Eric Laurenta1478072015-09-21 17:21:52 -07002448 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002449 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2450 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002451 out_get_sample_rate(&out->stream.common));
2452 pthread_mutex_unlock(&out->lock);
2453 return bytes;
2454}
2455#endif
2456
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002457static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2458 size_t bytes)
2459{
2460 struct stream_out *out = (struct stream_out *)stream;
2461 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002462 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002463 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002464
Eric Laurenta1478072015-09-21 17:21:52 -07002465 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002466 // this is always nonzero
2467 const int frame_size = audio_stream_out_frame_size(stream);
2468
Eric Laurent0e46adf2016-12-16 12:49:24 -08002469 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2470 error_code = ERROR_CODE_WRITE;
2471 goto exit;
2472 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002473 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002474 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002475 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002476 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002477 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002478 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002479 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002480 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002481 goto exit;
2482 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002483
2484 if (last_known_cal_step != -1) {
2485 ALOGD("%s: retry previous failed cal level set", __func__);
2486 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2487 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002488 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002489
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002490 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002491 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002492 if (out->send_new_metadata) {
2493 ALOGVV("send new gapless metadata");
2494 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2495 out->send_new_metadata = 0;
2496 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002497 unsigned int avail;
2498 struct timespec tstamp;
2499 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2500 /* Do not limit write size if the available frames count is unknown */
2501 if (ret != 0) {
2502 avail = bytes;
2503 }
2504 if (avail == 0) {
2505 ret = 0;
2506 } else {
2507 if (avail > bytes) {
2508 avail = bytes;
2509 }
2510 ret = compress_write(out->compr, buffer, avail);
2511 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2512 __func__, avail, ret);
2513 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002514
Eric Laurent6e895242013-09-05 16:10:57 -07002515 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002516 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2517 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002518 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002519 compress_start(out->compr);
2520 out->playback_started = 1;
2521 out->offload_state = OFFLOAD_STATE_PLAYING;
2522 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002523 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002524 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002525 } else {
2526 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002527 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002528 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002529 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002530 return ret;
2531 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002532 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002533 if (out->pcm) {
2534 if (out->muted)
2535 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002536
Eric Laurent0e46adf2016-12-16 12:49:24 -08002537 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002538
Haynes Mathew George03c40102016-01-29 17:57:48 -08002539 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2540 out->config.rate;
2541 request_out_focus(out, ns);
2542
2543 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2544 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002545 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002546 else
2547 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002548
Haynes Mathew George03c40102016-01-29 17:57:48 -08002549 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002550 } else {
2551 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002552 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002553 }
2554
2555exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002556 // For PCM we always consume the buffer and return #bytes regardless of ret.
2557 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2558 out->written += bytes / (out->config.channels * sizeof(short));
2559 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002560 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07002561
2562 // only get time if needed for logging, as it is a system call on 32 bit devices.
2563 // TODO: Consider always enabling for 64 bit vDSO using compile time check on __LP64__.
2564 const int64_t now_ns = out->power_log != 0 || (ret != 0 && out->error_log != 0)
2565 ? audio_utils_get_real_time_ns() : 0;
Andy Hungfc044e12017-03-20 09:24:22 -07002566
Andy Hung7401c7c2016-09-21 12:41:21 -07002567 if (ret != 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002568 error_log_log(out->error_log, error_code, now_ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002569 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2570 ALOGE_IF(out->pcm != NULL,
2571 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hungfc044e12017-03-20 09:24:22 -07002572 sleeptime_us = bytes * 1000000LL / frame_size /
Andy Hung7401c7c2016-09-21 12:41:21 -07002573 out_get_sample_rate(&out->stream.common);
2574 // usleep not guaranteed for values over 1 second but we don't limit here.
2575 }
2576 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002577
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002578 pthread_mutex_unlock(&out->lock);
2579
2580 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002581 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002582 if (sleeptime_us != 0)
2583 usleep(sleeptime_us);
Andy Hungfc044e12017-03-20 09:24:22 -07002584 } else {
2585 // only log if the data is properly written (out->power_log may be null)
2586 power_log_log(out->power_log, buffer, bytes / frame_size, now_ns);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002587 }
2588 return bytes;
2589}
2590
2591static int out_get_render_position(const struct audio_stream_out *stream,
2592 uint32_t *dsp_frames)
2593{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002594 struct stream_out *out = (struct stream_out *)stream;
2595 *dsp_frames = 0;
2596 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002597 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002598 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002599 unsigned long frames = 0;
2600 // TODO: check return value
2601 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2602 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002603 ALOGVV("%s rendered frames %d sample_rate %d",
2604 __func__, *dsp_frames, out->sample_rate);
2605 }
2606 pthread_mutex_unlock(&out->lock);
2607 return 0;
2608 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002609 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002610}
2611
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002612static int out_add_audio_effect(const struct audio_stream *stream __unused,
2613 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002614{
2615 return 0;
2616}
2617
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002618static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2619 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002620{
2621 return 0;
2622}
2623
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002624static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2625 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002626{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002627 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002628}
2629
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002630static int out_get_presentation_position(const struct audio_stream_out *stream,
2631 uint64_t *frames, struct timespec *timestamp)
2632{
2633 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002634 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07002635 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002636
Eric Laurenta1478072015-09-21 17:21:52 -07002637 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002638
Eric Laurent949a0892013-09-20 09:20:13 -07002639 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2640 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002641 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002642 compress_get_tstamp(out->compr, &dsp_frames,
2643 &out->sample_rate);
2644 ALOGVV("%s rendered frames %ld sample_rate %d",
2645 __func__, dsp_frames, out->sample_rate);
2646 *frames = dsp_frames;
2647 ret = 0;
2648 /* this is the best we can do */
2649 clock_gettime(CLOCK_MONOTONIC, timestamp);
2650 }
2651 } else {
2652 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002653 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002654 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2655 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002656 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002657 // This adjustment accounts for buffering after app processor.
2658 // It is based on estimated DSP latency per use case, rather than exact.
2659 signed_frames -=
2660 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2661
Eric Laurent949a0892013-09-20 09:20:13 -07002662 // It would be unusual for this value to be negative, but check just in case ...
2663 if (signed_frames >= 0) {
2664 *frames = signed_frames;
2665 ret = 0;
2666 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002667 }
2668 }
2669 }
2670
2671 pthread_mutex_unlock(&out->lock);
2672
2673 return ret;
2674}
2675
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002676static int out_set_callback(struct audio_stream_out *stream,
2677 stream_callback_t callback, void *cookie)
2678{
2679 struct stream_out *out = (struct stream_out *)stream;
2680
2681 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002682 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002683 out->offload_callback = callback;
2684 out->offload_cookie = cookie;
2685 pthread_mutex_unlock(&out->lock);
2686 return 0;
2687}
2688
2689static int out_pause(struct audio_stream_out* stream)
2690{
2691 struct stream_out *out = (struct stream_out *)stream;
2692 int status = -ENOSYS;
2693 ALOGV("%s", __func__);
2694 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002695 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002696 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2697 status = compress_pause(out->compr);
2698 out->offload_state = OFFLOAD_STATE_PAUSED;
2699 }
2700 pthread_mutex_unlock(&out->lock);
2701 }
2702 return status;
2703}
2704
2705static int out_resume(struct audio_stream_out* stream)
2706{
2707 struct stream_out *out = (struct stream_out *)stream;
2708 int status = -ENOSYS;
2709 ALOGV("%s", __func__);
2710 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2711 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002712 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002713 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2714 status = compress_resume(out->compr);
2715 out->offload_state = OFFLOAD_STATE_PLAYING;
2716 }
2717 pthread_mutex_unlock(&out->lock);
2718 }
2719 return status;
2720}
2721
2722static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2723{
2724 struct stream_out *out = (struct stream_out *)stream;
2725 int status = -ENOSYS;
2726 ALOGV("%s", __func__);
2727 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002728 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002729 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2730 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2731 else
2732 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2733 pthread_mutex_unlock(&out->lock);
2734 }
2735 return status;
2736}
2737
2738static int out_flush(struct audio_stream_out* stream)
2739{
2740 struct stream_out *out = (struct stream_out *)stream;
2741 ALOGV("%s", __func__);
2742 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002743 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002744 stop_compressed_output_l(out);
2745 pthread_mutex_unlock(&out->lock);
2746 return 0;
2747 }
2748 return -ENOSYS;
2749}
2750
Eric Laurent0e46adf2016-12-16 12:49:24 -08002751static int out_stop(const struct audio_stream_out* stream)
2752{
2753 struct stream_out *out = (struct stream_out *)stream;
2754 struct audio_device *adev = out->dev;
2755 int ret = -ENOSYS;
2756
2757 ALOGV("%s", __func__);
2758 pthread_mutex_lock(&adev->lock);
2759 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2760 out->playback_started && out->pcm != NULL) {
2761 pcm_stop(out->pcm);
2762 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08002763 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002764 }
2765 pthread_mutex_unlock(&adev->lock);
2766 return ret;
2767}
2768
2769static int out_start(const struct audio_stream_out* stream)
2770{
2771 struct stream_out *out = (struct stream_out *)stream;
2772 struct audio_device *adev = out->dev;
2773 int ret = -ENOSYS;
2774
2775 ALOGV("%s", __func__);
2776 pthread_mutex_lock(&adev->lock);
2777 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2778 !out->playback_started && out->pcm != NULL) {
2779 ret = start_output_stream(out);
2780 if (ret == 0) {
2781 out->playback_started = true;
2782 }
2783 }
2784 pthread_mutex_unlock(&adev->lock);
2785 return ret;
2786}
2787
Phil Burkbc991042017-02-24 08:06:44 -08002788/*
2789 * Modify config->period_count based on min_size_frames
2790 */
2791static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
2792{
2793 int periodCountRequested = (min_size_frames + config->period_size - 1)
2794 / config->period_size;
2795 int periodCount = MMAP_PERIOD_COUNT_MIN;
2796
2797 ALOGV("%s original config.period_size = %d config.period_count = %d",
2798 __func__, config->period_size, config->period_count);
2799
2800 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
2801 periodCount *= 2;
2802 }
2803 config->period_count = periodCount;
2804
2805 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
2806}
2807
Eric Laurent0e46adf2016-12-16 12:49:24 -08002808static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2809 int32_t min_size_frames,
2810 struct audio_mmap_buffer_info *info)
2811{
2812 struct stream_out *out = (struct stream_out *)stream;
2813 struct audio_device *adev = out->dev;
2814 int ret = 0;
2815 unsigned int offset1;
2816 unsigned int frames1;
2817 const char *step = "";
2818
2819 ALOGV("%s", __func__);
2820 pthread_mutex_lock(&adev->lock);
2821
2822 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002823 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002824 ret = -EINVAL;
2825 goto exit;
2826 }
2827 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08002828 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002829 ret = -ENOSYS;
2830 goto exit;
2831 }
2832 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
2833 if (out->pcm_device_id < 0) {
2834 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2835 __func__, out->pcm_device_id, out->usecase);
2836 ret = -EINVAL;
2837 goto exit;
2838 }
Phil Burkbc991042017-02-24 08:06:44 -08002839
2840 adjust_mmap_period_count(&out->config, min_size_frames);
2841
Eric Laurent0e46adf2016-12-16 12:49:24 -08002842 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2843 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
2844 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2845 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
2846 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2847 step = "open";
2848 ret = -ENODEV;
2849 goto exit;
2850 }
2851 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
2852 if (ret < 0) {
2853 step = "begin";
2854 goto exit;
2855 }
2856 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
2857 info->burst_size_frames = out->config.period_size;
2858 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
2859
2860 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
2861 info->buffer_size_frames));
2862
2863 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
2864 if (ret < 0) {
2865 step = "commit";
2866 goto exit;
2867 }
Phil Burkbc991042017-02-24 08:06:44 -08002868
2869 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002870 ret = 0;
2871
2872 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
2873 __func__, info->shared_memory_address, info->buffer_size_frames);
2874
2875exit:
2876 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002877 if (out->pcm == NULL) {
2878 ALOGE("%s: %s - %d", __func__, step, ret);
2879 } else {
2880 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08002881 pcm_close(out->pcm);
2882 out->pcm = NULL;
2883 }
2884 }
2885 pthread_mutex_unlock(&adev->lock);
2886 return ret;
2887}
2888
2889static int out_get_mmap_position(const struct audio_stream_out *stream,
2890 struct audio_mmap_position *position)
2891{
2892 struct stream_out *out = (struct stream_out *)stream;
2893 ALOGVV("%s", __func__);
2894 if (position == NULL) {
2895 return -EINVAL;
2896 }
2897 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
2898 return -ENOSYS;
2899 }
2900 if (out->pcm == NULL) {
2901 return -ENOSYS;
2902 }
2903
2904 struct timespec ts = { 0, 0 };
2905 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
2906 if (ret < 0) {
2907 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2908 return ret;
2909 }
Andy Hungfc044e12017-03-20 09:24:22 -07002910 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002911 return 0;
2912}
2913
2914
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002915/** audio_stream_in implementation **/
2916static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2917{
2918 struct stream_in *in = (struct stream_in *)stream;
2919
2920 return in->config.rate;
2921}
2922
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002923static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002924{
2925 return -ENOSYS;
2926}
2927
2928static size_t in_get_buffer_size(const struct audio_stream *stream)
2929{
2930 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002931 return in->config.period_size * in->af_period_multiplier *
2932 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002933}
2934
2935static uint32_t in_get_channels(const struct audio_stream *stream)
2936{
2937 struct stream_in *in = (struct stream_in *)stream;
2938
2939 return in->channel_mask;
2940}
2941
vivek mehta4ed66e62016-04-15 23:33:34 -07002942static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002943{
vivek mehta4ed66e62016-04-15 23:33:34 -07002944 struct stream_in *in = (struct stream_in *)stream;
2945 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002946}
2947
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002948static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002949{
2950 return -ENOSYS;
2951}
2952
2953static int in_standby(struct audio_stream *stream)
2954{
2955 struct stream_in *in = (struct stream_in *)stream;
2956 struct audio_device *adev = in->dev;
2957 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08002958 bool do_stop = true;
2959
Eric Laurent994a6932013-07-17 11:51:42 -07002960 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002961
2962 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002963
2964 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08002965 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002966 audio_extn_sound_trigger_stop_lab(in);
2967 in->standby = true;
2968 }
2969
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002970 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002971 if (adev->adm_deregister_stream)
2972 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2973
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002974 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002975 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002976 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002977 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002978 in->capture_started = false;
2979 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002980 if (in->pcm) {
2981 pcm_close(in->pcm);
2982 in->pcm = NULL;
2983 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002984 adev->enable_voicerx = false;
2985 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08002986 if (do_stop) {
2987 status = stop_input_stream(in);
2988 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002989 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002990 }
2991 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002992 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002993 return status;
2994}
2995
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002996static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002997{
2998 return 0;
2999}
3000
3001static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3002{
3003 struct stream_in *in = (struct stream_in *)stream;
3004 struct audio_device *adev = in->dev;
3005 struct str_parms *parms;
3006 char *str;
3007 char value[32];
3008 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003009 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003010
Eric Laurent994a6932013-07-17 11:51:42 -07003011 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003012 parms = str_parms_create_str(kvpairs);
3013
3014 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3015
Eric Laurenta1478072015-09-21 17:21:52 -07003016 lock_input_stream(in);
3017
Eric Laurent150dbfe2013-02-27 14:31:02 -08003018 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003019 if (ret >= 0) {
3020 val = atoi(value);
3021 /* no audio source uses val == 0 */
3022 if ((in->source != val) && (val != 0)) {
3023 in->source = val;
3024 }
3025 }
3026
3027 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003028
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003029 if (ret >= 0) {
3030 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003031 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003032 in->device = val;
3033 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08003034 if (!in->standby) {
3035 ALOGV("update input routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003036 // inform adm before actual routing to prevent glitches.
3037 if (adev->adm_on_routing_change) {
3038 adev->adm_on_routing_change(adev->adm_data,
3039 in->capture_handle);
3040 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003041 select_devices(adev, in->usecase);
3042 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003043 }
3044 }
3045
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003046 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003047 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003048
3049 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003050 ALOGV("%s: exit: status(%d)", __func__, status);
3051 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003052}
3053
Haynes Mathew George569b7482017-05-08 14:44:27 -07003054static char* in_get_parameters(const struct audio_stream *stream,
3055 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003056{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003057 struct stream_in *in = (struct stream_in *)stream;
3058 struct str_parms *query = str_parms_create_str(keys);
3059 char *str;
3060 struct str_parms *reply = str_parms_create();
3061 bool replied = false;
3062
3063 ALOGV("%s: enter: keys - %s", __func__, keys);
3064 replied |= stream_get_parameter_channels(query, reply,
3065 &in->supported_channel_masks[0]);
3066 replied |= stream_get_parameter_formats(query, reply,
3067 &in->supported_formats[0]);
3068 replied |= stream_get_parameter_rates(query, reply,
3069 &in->supported_sample_rates[0]);
3070 if (replied) {
3071 str = str_parms_to_str(reply);
3072 } else {
3073 str = strdup(keys);
3074 }
3075 str_parms_destroy(query);
3076 str_parms_destroy(reply);
3077 ALOGV("%s: exit: returns - %s", __func__, str);
3078 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003079}
3080
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003081static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003082{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003083 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003084}
3085
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003086static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3087{
3088 if (!stream || !parms)
3089 return;
3090
3091 struct stream_in *in = (struct stream_in *)stream;
3092 struct audio_device *adev = in->dev;
3093
3094 card_status_t status;
3095 int card;
3096 if (parse_snd_card_status(parms, &card, &status) < 0)
3097 return;
3098
3099 pthread_mutex_lock(&adev->lock);
3100 bool valid_cb = (card == adev->snd_card);
3101 pthread_mutex_unlock(&adev->lock);
3102
3103 if (!valid_cb)
3104 return;
3105
3106 lock_input_stream(in);
3107 if (in->card_status != status)
3108 in->card_status = status;
3109 pthread_mutex_unlock(&in->lock);
3110
3111 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3112 use_case_table[in->usecase],
3113 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3114
3115 // a better solution would be to report error back to AF and let
3116 // it put the stream to standby
3117 if (status == CARD_STATUS_OFFLINE)
3118 in_standby(&in->stream.common);
3119
3120 return;
3121}
3122
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003123static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3124 size_t bytes)
3125{
3126 struct stream_in *in = (struct stream_in *)stream;
3127 struct audio_device *adev = in->dev;
3128 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003129 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003130
Eric Laurenta1478072015-09-21 17:21:52 -07003131 lock_input_stream(in);
3132
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003133 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003134 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003135 /* Read from sound trigger HAL */
3136 audio_extn_sound_trigger_read(in, buffer, bytes);
3137 pthread_mutex_unlock(&in->lock);
3138 return bytes;
3139 }
3140
Eric Laurent0e46adf2016-12-16 12:49:24 -08003141 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3142 ret = -ENOSYS;
3143 goto exit;
3144 }
3145
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003146 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003147 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003148 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003149 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003150 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003151 goto exit;
3152 }
3153 in->standby = 0;
3154 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003155
Haynes Mathew George03c40102016-01-29 17:57:48 -08003156 //what's the duration requested by the client?
3157 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3158 in->config.rate;
3159 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003160
Haynes Mathew George03c40102016-01-29 17:57:48 -08003161 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003162 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003163 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003164 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003165 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003166 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003167 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003168 if (ret < 0) {
3169 ALOGE("Failed to read w/err %s", strerror(errno));
3170 ret = -errno;
3171 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003172 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3173 if (bytes % 4 == 0) {
3174 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3175 int_buf_stream = buffer;
3176 for (size_t itt=0; itt < bytes/4 ; itt++) {
3177 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003178 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003179 } else {
3180 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3181 ret = -EINVAL;
3182 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003183 }
3184 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003185 }
3186
Haynes Mathew George03c40102016-01-29 17:57:48 -08003187 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003188
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003189 /*
3190 * Instead of writing zeroes here, we could trust the hardware
3191 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003192 * 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 -08003193 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003194 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003195 memset(buffer, 0, bytes);
3196
3197exit:
3198 pthread_mutex_unlock(&in->lock);
3199
3200 if (ret != 0) {
3201 in_standby(&in->stream.common);
3202 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Eric Laurentfdf296a2014-07-03 16:41:51 -07003203 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003204 in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003205 memset(buffer, 0, bytes); // clear return data
3206 }
3207 if (bytes > 0) {
Andy Hung6ebe5962016-01-15 17:46:57 -08003208 in->frames_read += bytes / audio_stream_in_frame_size(stream);
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;
vivek mehtaa68fea62017-06-08 19:04:02 -07003602 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3603 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT |
3604 AUDIO_OUTPUT_FLAG_VOIP_RX))) {
3605 uint32_t buffer_size, frame_size;
3606 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
3607 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
3608 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
3609 out->config = pcm_config_voip;
3610 out->config.format = pcm_format_from_audio_format(config->format);
3611 out->config.rate = config->sample_rate;
3612 out->config.channels =
3613 audio_channel_count_from_out_mask(config->channel_mask);
3614 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
3615 config->sample_rate,
3616 config->format,
3617 out->config.channels,
3618 false /*is_low_latency*/);
3619 frame_size = audio_bytes_per_sample(config->format) * out->config.channels;
3620 out->config.period_size = buffer_size / frame_size;
3621 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
3622 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003623 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003624 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3625 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3626 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003627 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
3628 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3629 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003630 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3631 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003632 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003633 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003634 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3635 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3636 out->config = pcm_config_mmap_playback;
3637 out->stream.start = out_start;
3638 out->stream.stop = out_stop;
3639 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3640 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003641 } else {
3642 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3643 out->config = pcm_config_low_latency;
3644 }
3645 if (config->format != audio_format_from_pcm_format(out->config.format)) {
3646 if (k_enable_extended_precision
3647 && pcm_params_format_test(adev->use_case_table[out->usecase],
3648 pcm_format_from_audio_format(config->format))) {
3649 out->config.format = pcm_format_from_audio_format(config->format);
3650 /* out->format already set to config->format */
3651 } else {
3652 /* deny the externally proposed config format
3653 * and use the one specified in audio_hw layer configuration.
3654 * Note: out->format is returned by out->stream.common.get_format()
3655 * and is used to set config->format in the code several lines below.
3656 */
3657 out->format = audio_format_from_pcm_format(out->config.format);
3658 }
3659 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003660 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003661 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003662
3663 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
3664 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
3665 (config->channel_mask != 0 && config->channel_mask != out->channel_mask)) {
3666 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
3667 __func__, config->sample_rate, config->format, config->channel_mask);
3668 config->sample_rate = out->sample_rate;
3669 config->format = out->format;
3670 config->channel_mask = out->channel_mask;
3671 ret = -EINVAL;
3672 goto error_open;
3673 }
3674
Andy Hung6fcba9c2014-03-18 11:53:32 -07003675 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3676 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003677
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003678 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003679 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003680 adev->primary_output = out;
3681 else {
3682 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003683 ret = -EEXIST;
3684 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003685 }
3686 }
3687
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003688 /* Check if this usecase is already existing */
3689 pthread_mutex_lock(&adev->lock);
3690 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3691 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003692 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003693 ret = -EEXIST;
3694 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003695 }
3696 pthread_mutex_unlock(&adev->lock);
3697
3698 out->stream.common.get_sample_rate = out_get_sample_rate;
3699 out->stream.common.set_sample_rate = out_set_sample_rate;
3700 out->stream.common.get_buffer_size = out_get_buffer_size;
3701 out->stream.common.get_channels = out_get_channels;
3702 out->stream.common.get_format = out_get_format;
3703 out->stream.common.set_format = out_set_format;
3704 out->stream.common.standby = out_standby;
3705 out->stream.common.dump = out_dump;
3706 out->stream.common.set_parameters = out_set_parameters;
3707 out->stream.common.get_parameters = out_get_parameters;
3708 out->stream.common.add_audio_effect = out_add_audio_effect;
3709 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3710 out->stream.get_latency = out_get_latency;
3711 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003712#ifdef NO_AUDIO_OUT
3713 out->stream.write = out_write_for_no_output;
3714#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003715 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003716#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003717 out->stream.get_render_position = out_get_render_position;
3718 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003719 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003720
Eric Laurent0e46adf2016-12-16 12:49:24 -08003721 if (out->realtime)
3722 out->af_period_multiplier = af_period_multiplier;
3723 else
3724 out->af_period_multiplier = 1;
3725
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003726 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003727 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003728 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003729
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003730 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003731 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003732 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3733
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003734 config->format = out->stream.common.get_format(&out->stream.common);
3735 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3736 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3737
Andy Hunga452b0a2017-03-15 14:51:15 -07003738 out->error_log = error_log_create(
3739 ERROR_LOG_ENTRIES,
3740 1000000000 /* aggregate consecutive identical errors within one second in ns */);
3741
Andy Hungfc044e12017-03-20 09:24:22 -07003742 // power_log may be null if the format is not supported
Andy Hung9e737de2017-05-22 10:51:22 -07003743 // or not a userdebug or eng build.
Andy Hung02caae52017-06-06 12:33:33 -07003744 if (false /* is_userdebug_or_eng_build() */) {
Andy Hung9e737de2017-05-22 10:51:22 -07003745 const size_t POWER_LOG_FRAMES_PER_ENTRY =
3746 (long long)config->sample_rate * POWER_LOG_SAMPLING_INTERVAL_MS / 1000;
3747
3748 out->power_log = power_log_create(
3749 config->sample_rate,
3750 audio_channel_count_from_out_mask(config->channel_mask),
3751 config->format,
3752 POWER_LOG_ENTRIES,
3753 POWER_LOG_FRAMES_PER_ENTRY);
3754 }
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003755
3756 /*
3757 By locking output stream before registering, we allow the callback
3758 to update stream's state only after stream's initial state is set to
3759 adev state.
3760 */
3761 lock_output_stream(out);
3762 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3763 pthread_mutex_lock(&adev->lock);
3764 out->card_status = adev->card_status;
3765 pthread_mutex_unlock(&adev->lock);
3766 pthread_mutex_unlock(&out->lock);
3767
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003768 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003769
Eric Laurent994a6932013-07-17 11:51:42 -07003770 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003771 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003772
3773error_open:
3774 free(out);
3775 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003776 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003777 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003778}
3779
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003780static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003781 struct audio_stream_out *stream)
3782{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003783 struct stream_out *out = (struct stream_out *)stream;
3784 struct audio_device *adev = out->dev;
3785
Eric Laurent994a6932013-07-17 11:51:42 -07003786 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003787
3788 // must deregister from sndmonitor first to prevent races
3789 // between the callback and close_stream
3790 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003791 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003792 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3793 destroy_offload_callback_thread(out);
3794
3795 if (out->compr_config.codec != NULL)
3796 free(out->compr_config.codec);
3797 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003798
3799 if (adev->voice_tx_output == out)
3800 adev->voice_tx_output = NULL;
3801
Andy Hungfc044e12017-03-20 09:24:22 -07003802 power_log_destroy(out->power_log);
3803 out->power_log = NULL;
3804
Andy Hunga452b0a2017-03-15 14:51:15 -07003805 error_log_destroy(out->error_log);
3806 out->error_log = NULL;
3807
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003808 pthread_cond_destroy(&out->cond);
3809 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003810 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003811 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003812}
3813
3814static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3815{
3816 struct audio_device *adev = (struct audio_device *)dev;
3817 struct str_parms *parms;
3818 char *str;
3819 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003820 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003821 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003822 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003823
Joe Onorato188b6222016-03-01 11:02:27 -08003824 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003825
3826 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003827
3828 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003829 status = voice_set_parameters(adev, parms);
3830 if (status != 0) {
3831 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003832 }
3833
3834 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3835 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003836 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003837 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3838 adev->bluetooth_nrec = true;
3839 else
3840 adev->bluetooth_nrec = false;
3841 }
3842
3843 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3844 if (ret >= 0) {
3845 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3846 adev->screen_off = false;
3847 else
3848 adev->screen_off = true;
3849 }
3850
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003851 ret = str_parms_get_int(parms, "rotation", &val);
3852 if (ret >= 0) {
3853 bool reverse_speakers = false;
3854 switch(val) {
3855 // FIXME: note that the code below assumes that the speakers are in the correct placement
3856 // relative to the user when the device is rotated 90deg from its default rotation. This
3857 // assumption is device-specific, not platform-specific like this code.
3858 case 270:
3859 reverse_speakers = true;
3860 break;
3861 case 0:
3862 case 90:
3863 case 180:
3864 break;
3865 default:
3866 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003867 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003868 }
Eric Laurent03f09432014-03-25 18:09:11 -07003869 if (status == 0) {
Ravi Kumar Alamanda1f60cf82015-04-23 19:45:17 -07003870 platform_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003871 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003872 }
3873
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003874 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3875 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003876 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003877 }
3878
David Linee3fe402017-03-13 10:00:42 -07003879 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3880 if (ret >= 0) {
3881 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
3882 if (device == AUDIO_DEVICE_OUT_USB_DEVICE) {
3883 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3884 if (ret >= 0) {
3885 const int card = atoi(value);
3886 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, card);
3887 }
3888 } else if (device == AUDIO_DEVICE_IN_USB_DEVICE) {
3889 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3890 if (ret >= 0) {
3891 const int card = atoi(value);
3892 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, card);
3893 }
3894 }
3895 }
3896
3897 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3898 if (ret >= 0) {
3899 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
3900 if (device == AUDIO_DEVICE_OUT_USB_DEVICE) {
3901 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3902 if (ret >= 0) {
3903 const int card = atoi(value);
3904
3905 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, card);
3906 }
3907 } else if (device == AUDIO_DEVICE_IN_USB_DEVICE) {
3908 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3909 if (ret >= 0) {
3910 const int card = atoi(value);
3911 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, card);
3912 }
3913 }
3914 }
3915
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08003916 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003917done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003918 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003919 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07003920 ALOGV("%s: exit with code(%d)", __func__, status);
3921 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003922}
3923
3924static char* adev_get_parameters(const struct audio_hw_device *dev,
3925 const char *keys)
3926{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003927 struct audio_device *adev = (struct audio_device *)dev;
3928 struct str_parms *reply = str_parms_create();
3929 struct str_parms *query = str_parms_create_str(keys);
3930 char *str;
3931
3932 pthread_mutex_lock(&adev->lock);
3933
3934 voice_get_parameters(adev, query, reply);
3935 str = str_parms_to_str(reply);
3936 str_parms_destroy(query);
3937 str_parms_destroy(reply);
3938
3939 pthread_mutex_unlock(&adev->lock);
3940 ALOGV("%s: exit: returns - %s", __func__, str);
3941 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003942}
3943
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003944static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003945{
3946 return 0;
3947}
3948
Haynes Mathew George5191a852013-09-11 14:19:36 -07003949static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3950{
3951 int ret;
3952 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003953
Eric Laurent4cc4ce12014-09-10 13:21:01 -05003954 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
3955
Haynes Mathew George5191a852013-09-11 14:19:36 -07003956 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003957 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003958 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003959
Haynes Mathew George5191a852013-09-11 14:19:36 -07003960 return ret;
3961}
3962
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003963static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003964{
3965 return -ENOSYS;
3966}
3967
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003968static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3969 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003970{
3971 return -ENOSYS;
3972}
3973
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003974static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003975{
3976 return -ENOSYS;
3977}
3978
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003979static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003980{
3981 return -ENOSYS;
3982}
3983
3984static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3985{
3986 struct audio_device *adev = (struct audio_device *)dev;
3987
3988 pthread_mutex_lock(&adev->lock);
3989 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07003990 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003991 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07003992 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3993 voice_is_in_call(adev)) {
3994 voice_stop_call(adev);
3995 adev->current_call_output = NULL;
3996 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003997 }
3998 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003999
4000 audio_extn_extspk_set_mode(adev->extspk, mode);
4001
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004002 return 0;
4003}
4004
4005static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4006{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004007 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004008 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004009
Eric Laurent2bafff12016-03-17 12:17:23 -07004010 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004011 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004012 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4013 ret = audio_extn_hfp_set_mic_mute(adev, state);
4014 } else {
4015 ret = voice_set_mic_mute(adev, state);
4016 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004017 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004018 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004019
4020 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004021}
4022
4023static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4024{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004025 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004026 return 0;
4027}
4028
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004029static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004030 const struct audio_config *config)
4031{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004032 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004033
vivek mehtaa68fea62017-06-08 19:04:02 -07004034 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4035 config->sample_rate, config->format,
4036 channel_count,
4037 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004038}
4039
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004040static bool adev_input_allow_hifi_record(struct audio_device *adev,
4041 audio_devices_t devices,
4042 audio_input_flags_t flags,
4043 audio_source_t source) {
4044 const bool allowed = true;
4045
4046 if (!audio_is_usb_in_device(devices))
4047 return !allowed;
4048
4049 switch (flags) {
4050 case AUDIO_INPUT_FLAG_NONE:
4051 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4052 break;
4053 default:
4054 return !allowed;
4055 }
4056
4057 switch (source) {
4058 case AUDIO_SOURCE_DEFAULT:
4059 case AUDIO_SOURCE_MIC:
4060 case AUDIO_SOURCE_UNPROCESSED:
4061 break;
4062 default:
4063 return !allowed;
4064 }
4065
4066 switch (adev->mode) {
4067 case 0:
4068 break;
4069 default:
4070 return !allowed;
4071 }
4072
4073 return allowed;
4074}
4075
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004076static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004077 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004078 audio_devices_t devices,
4079 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004080 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004081 audio_input_flags_t flags,
4082 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004083 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004084{
4085 struct audio_device *adev = (struct audio_device *)dev;
4086 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004087 int ret = 0, buffer_size, frame_size;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004088 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004089 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004090 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004091 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4092 devices,
4093 flags,
4094 source);
4095 ALOGE("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004096 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004097
4098 if (config->sample_rate == 0)
4099 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4100 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4101 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4102 if (config->format == AUDIO_FORMAT_DEFAULT)
4103 config->format = AUDIO_FORMAT_PCM_16_BIT;
4104
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004105 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
4106 return -EINVAL;
4107
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004108 if (audio_extn_tfa_98xx_is_supported() &&
4109 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004110 return -EINVAL;
4111
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004112 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4113
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004114 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004115 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004116
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004117 in->stream.common.get_sample_rate = in_get_sample_rate;
4118 in->stream.common.set_sample_rate = in_set_sample_rate;
4119 in->stream.common.get_buffer_size = in_get_buffer_size;
4120 in->stream.common.get_channels = in_get_channels;
4121 in->stream.common.get_format = in_get_format;
4122 in->stream.common.set_format = in_set_format;
4123 in->stream.common.standby = in_standby;
4124 in->stream.common.dump = in_dump;
4125 in->stream.common.set_parameters = in_set_parameters;
4126 in->stream.common.get_parameters = in_get_parameters;
4127 in->stream.common.add_audio_effect = in_add_audio_effect;
4128 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4129 in->stream.set_gain = in_set_gain;
4130 in->stream.read = in_read;
4131 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08004132 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004133
4134 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004135 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004136 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004137 in->standby = 1;
4138 in->channel_mask = config->channel_mask;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004139 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004140 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004141
Haynes Mathew George569b7482017-05-08 14:44:27 -07004142 if (is_usb_dev && may_use_hifi_record) {
4143 /* HiFi record selects an appropriate format, channel, rate combo
4144 depending on sink capabilities*/
4145 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
4146 &config->format,
4147 &in->supported_formats[0],
4148 MAX_SUPPORTED_FORMATS,
4149 &config->channel_mask,
4150 &in->supported_channel_masks[0],
4151 MAX_SUPPORTED_CHANNEL_MASKS,
4152 &config->sample_rate,
4153 &in->supported_sample_rates[0],
4154 MAX_SUPPORTED_SAMPLE_RATES);
4155 if (ret != 0) {
4156 ret = -EINVAL;
4157 goto err_open;
4158 }
4159 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07004160 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07004161 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
4162 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
4163 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4164 bool ret_error = false;
4165 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4166 from HAL is 8_24
4167 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4168 8_24 return error indicating supported format is 8_24
4169 *> In case of any other source requesting 24 bit or float return error
4170 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07004171
vivek mehta57ff9b52016-04-28 14:13:08 -07004172 on error flinger will retry with supported format passed
4173 */
4174 if (source != AUDIO_SOURCE_UNPROCESSED) {
4175 config->format = AUDIO_FORMAT_PCM_16_BIT;
4176 ret_error = true;
4177 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
4178 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
4179 ret_error = true;
4180 }
4181
4182 if (ret_error) {
4183 ret = -EINVAL;
4184 goto err_open;
4185 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004186 }
4187
vivek mehta57ff9b52016-04-28 14:13:08 -07004188 in->format = config->format;
4189
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004190 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004191 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
4192 if (config->sample_rate == 0)
4193 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4194 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4195 config->sample_rate != 8000) {
4196 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4197 ret = -EINVAL;
4198 goto err_open;
4199 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004200
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004201 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4202 config->format = AUDIO_FORMAT_PCM_16_BIT;
4203 ret = -EINVAL;
4204 goto err_open;
4205 }
4206
4207 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4208 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07004209 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004210 } else if (is_usb_dev && may_use_hifi_record) {
4211 in->usecase = USECASE_AUDIO_RECORD_HIFI;
4212 in->config = pcm_config_audio_capture;
4213 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004214 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4215 config->sample_rate,
4216 config->format,
4217 channel_count,
4218 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004219 in->config.period_size = buffer_size / frame_size;
4220 in->config.rate = config->sample_rate;
4221 in->af_period_multiplier = 1;
4222 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004223 } else {
4224 in->usecase = USECASE_AUDIO_RECORD;
4225 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08004226 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004227 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07004228#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004229 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07004230#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08004231 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004232 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08004233 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004234 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004235 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4236 config->sample_rate,
4237 config->format,
4238 channel_count,
4239 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004240 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004241 in->config.rate = config->sample_rate;
4242 in->af_period_multiplier = 1;
4243 } else {
4244 // period size is left untouched for rt mode playback
4245 in->config = pcm_config_audio_capture_rt;
4246 in->af_period_multiplier = af_period_multiplier;
4247 }
4248 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
4249 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004250 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08004251 in->usecase = USECASE_AUDIO_RECORD_MMAP;
4252 in->config = pcm_config_mmap_capture;
4253 in->stream.start = in_start;
4254 in->stream.stop = in_stop;
4255 in->stream.create_mmap_buffer = in_create_mmap_buffer;
4256 in->stream.get_mmap_position = in_get_mmap_position;
4257 in->af_period_multiplier = 1;
4258 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07004259 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
4260 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION &&
4261 (config->sample_rate == 8000 ||
4262 config->sample_rate == 16000 ||
4263 config->sample_rate == 32000 ||
4264 config->sample_rate == 48000) &&
4265 channel_count == 1) {
4266 in->usecase = USECASE_AUDIO_RECORD_VOIP;
4267 in->config = pcm_config_audio_capture;
4268 frame_size = audio_stream_in_frame_size(&in->stream);
4269 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
4270 config->sample_rate,
4271 config->format,
4272 channel_count, false /*is_low_latency*/);
4273 in->config.period_size = buffer_size / frame_size;
4274 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
4275 in->config.rate = config->sample_rate;
4276 in->af_period_multiplier = 1;
4277 in->flags |= AUDIO_INPUT_FLAG_VOIP_TX;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004278 } else {
4279 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004280 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004281 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4282 config->sample_rate,
4283 config->format,
4284 channel_count,
4285 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004286 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004287 in->config.rate = config->sample_rate;
4288 in->af_period_multiplier = 1;
4289 }
4290 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
4291 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004292 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004293
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004294 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07004295 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004296
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004297 /* This stream could be for sound trigger lab,
4298 get sound trigger pcm if present */
4299 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004300
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004301 lock_input_stream(in);
4302 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
4303 pthread_mutex_lock(&adev->lock);
4304 in->card_status = adev->card_status;
4305 pthread_mutex_unlock(&adev->lock);
4306 pthread_mutex_unlock(&in->lock);
4307
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004308 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004309 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004310 return 0;
4311
4312err_open:
4313 free(in);
4314 *stream_in = NULL;
4315 return ret;
4316}
4317
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004318static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004319 struct audio_stream_in *stream)
4320{
Eric Laurent994a6932013-07-17 11:51:42 -07004321 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004322
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004323 // must deregister from sndmonitor first to prevent races
4324 // between the callback and close_stream
4325 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004326 in_standby(&stream->common);
4327 free(stream);
4328
4329 return;
4330}
4331
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004332static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004333{
4334 return 0;
4335}
4336
Andy Hung31aca912014-03-20 17:14:59 -07004337/* verifies input and output devices and their capabilities.
4338 *
4339 * This verification is required when enabling extended bit-depth or
4340 * sampling rates, as not all qcom products support it.
4341 *
4342 * Suitable for calling only on initialization such as adev_open().
4343 * It fills the audio_device use_case_table[] array.
4344 *
4345 * Has a side-effect that it needs to configure audio routing / devices
4346 * in order to power up the devices and read the device parameters.
4347 * It does not acquire any hw device lock. Should restore the devices
4348 * back to "normal state" upon completion.
4349 */
4350static int adev_verify_devices(struct audio_device *adev)
4351{
4352 /* enumeration is a bit difficult because one really wants to pull
4353 * the use_case, device id, etc from the hidden pcm_device_table[].
4354 * In this case there are the following use cases and device ids.
4355 *
4356 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
4357 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004358 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07004359 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
4360 * [USECASE_AUDIO_RECORD] = {0, 0},
4361 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
4362 * [USECASE_VOICE_CALL] = {2, 2},
4363 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004364 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07004365 * USECASE_VOICE_CALL omitted, but possible for either input or output.
4366 */
4367
4368 /* should be the usecases enabled in adev_open_input_stream() */
4369 static const int test_in_usecases[] = {
4370 USECASE_AUDIO_RECORD,
4371 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
4372 };
4373 /* should be the usecases enabled in adev_open_output_stream()*/
4374 static const int test_out_usecases[] = {
4375 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
4376 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
4377 };
4378 static const usecase_type_t usecase_type_by_dir[] = {
4379 PCM_PLAYBACK,
4380 PCM_CAPTURE,
4381 };
4382 static const unsigned flags_by_dir[] = {
4383 PCM_OUT,
4384 PCM_IN,
4385 };
4386
4387 size_t i;
4388 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004389 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07004390 char info[512]; /* for possible debug info */
4391
4392 for (dir = 0; dir < 2; ++dir) {
4393 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
4394 const unsigned flags_dir = flags_by_dir[dir];
4395 const size_t testsize =
4396 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
4397 const int *testcases =
4398 dir ? test_in_usecases : test_out_usecases;
4399 const audio_devices_t audio_device =
4400 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
4401
4402 for (i = 0; i < testsize; ++i) {
4403 const audio_usecase_t audio_usecase = testcases[i];
4404 int device_id;
4405 snd_device_t snd_device;
4406 struct pcm_params **pparams;
4407 struct stream_out out;
4408 struct stream_in in;
4409 struct audio_usecase uc_info;
4410 int retval;
4411
4412 pparams = &adev->use_case_table[audio_usecase];
4413 pcm_params_free(*pparams); /* can accept null input */
4414 *pparams = NULL;
4415
4416 /* find the device ID for the use case (signed, for error) */
4417 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
4418 if (device_id < 0)
4419 continue;
4420
4421 /* prepare structures for device probing */
4422 memset(&uc_info, 0, sizeof(uc_info));
4423 uc_info.id = audio_usecase;
4424 uc_info.type = usecase_type;
4425 if (dir) {
4426 adev->active_input = &in;
4427 memset(&in, 0, sizeof(in));
4428 in.device = audio_device;
4429 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4430 uc_info.stream.in = &in;
4431 } else {
4432 adev->active_input = NULL;
4433 }
4434 memset(&out, 0, sizeof(out));
4435 out.devices = audio_device; /* only field needed in select_devices */
4436 uc_info.stream.out = &out;
4437 uc_info.devices = audio_device;
4438 uc_info.in_snd_device = SND_DEVICE_NONE;
4439 uc_info.out_snd_device = SND_DEVICE_NONE;
4440 list_add_tail(&adev->usecase_list, &uc_info.list);
4441
4442 /* select device - similar to start_(in/out)put_stream() */
4443 retval = select_devices(adev, audio_usecase);
4444 if (retval >= 0) {
4445 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4446#if LOG_NDEBUG == 0
4447 if (*pparams) {
4448 ALOGV("%s: (%s) card %d device %d", __func__,
4449 dir ? "input" : "output", card_id, device_id);
4450 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004451 } else {
4452 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4453 }
4454#endif
4455 }
4456
4457 /* deselect device - similar to stop_(in/out)put_stream() */
4458 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004459 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004460 /* 2. Disable the rx device */
4461 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004462 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004463 list_remove(&uc_info.list);
4464 }
4465 }
4466 adev->active_input = NULL; /* restore adev state */
4467 return 0;
4468}
4469
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004470static int adev_close(hw_device_t *device)
4471{
Andy Hung31aca912014-03-20 17:14:59 -07004472 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004473 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004474
4475 if (!adev)
4476 return 0;
4477
Kevin Rocarda5453442017-05-02 15:09:20 -07004478 audio_extn_snd_mon_unregister_listener(adev);
Kevin Rocard8342c2c2017-04-07 18:50:00 -07004479 audio_extn_snd_mon_deinit();
Kevin Rocarda5453442017-05-02 15:09:20 -07004480
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004481 audio_extn_tfa_98xx_deinit();
4482
vivek mehta1a9b7c02015-06-25 11:49:38 -07004483 pthread_mutex_lock(&adev_init_lock);
4484
4485 if ((--audio_device_ref_count) == 0) {
4486 audio_route_free(adev->audio_route);
4487 free(adev->snd_dev_ref_cnt);
4488 platform_deinit(adev->platform);
4489 audio_extn_extspk_deinit(adev->extspk);
4490 audio_extn_sound_trigger_deinit(adev);
4491 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4492 pcm_params_free(adev->use_case_table[i]);
4493 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004494 if (adev->adm_deinit)
4495 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004496 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004497 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004498
4499 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004500
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004501 return 0;
4502}
4503
Glenn Kasten4f993392014-05-14 07:30:48 -07004504/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4505 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4506 * just that it _might_ work.
4507 */
4508static int period_size_is_plausible_for_low_latency(int period_size)
4509{
4510 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004511 case 48:
4512 case 96:
4513 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004514 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004515 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004516 case 240:
4517 case 320:
4518 case 480:
4519 return 1;
4520 default:
4521 return 0;
4522 }
4523}
4524
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004525static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4526{
4527 int card;
4528 card_status_t status;
4529
4530 if (!parms)
4531 return;
4532
4533 if (parse_snd_card_status(parms, &card, &status) < 0)
4534 return;
4535
4536 pthread_mutex_lock(&adev->lock);
4537 bool valid_cb = (card == adev->snd_card);
4538 if (valid_cb) {
4539 if (adev->card_status != status) {
4540 adev->card_status = status;
4541 platform_snd_card_update(adev->platform, status);
4542 }
4543 }
4544 pthread_mutex_unlock(&adev->lock);
4545 return;
4546}
4547
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004548static int adev_open(const hw_module_t *module, const char *name,
4549 hw_device_t **device)
4550{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004551 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004552
Eric Laurent2bafff12016-03-17 12:17:23 -07004553 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004554 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004555 pthread_mutex_lock(&adev_init_lock);
4556 if (audio_device_ref_count != 0) {
4557 *device = &adev->device.common;
4558 audio_device_ref_count++;
4559 ALOGV("%s: returning existing instance of adev", __func__);
4560 ALOGV("%s: exit", __func__);
4561 pthread_mutex_unlock(&adev_init_lock);
4562 return 0;
4563 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004564 adev = calloc(1, sizeof(struct audio_device));
4565
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004566 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4567
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004568 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4569 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4570 adev->device.common.module = (struct hw_module_t *)module;
4571 adev->device.common.close = adev_close;
4572
4573 adev->device.init_check = adev_init_check;
4574 adev->device.set_voice_volume = adev_set_voice_volume;
4575 adev->device.set_master_volume = adev_set_master_volume;
4576 adev->device.get_master_volume = adev_get_master_volume;
4577 adev->device.set_master_mute = adev_set_master_mute;
4578 adev->device.get_master_mute = adev_get_master_mute;
4579 adev->device.set_mode = adev_set_mode;
4580 adev->device.set_mic_mute = adev_set_mic_mute;
4581 adev->device.get_mic_mute = adev_get_mic_mute;
4582 adev->device.set_parameters = adev_set_parameters;
4583 adev->device.get_parameters = adev_get_parameters;
4584 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4585 adev->device.open_output_stream = adev_open_output_stream;
4586 adev->device.close_output_stream = adev_close_output_stream;
4587 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004588
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004589 adev->device.close_input_stream = adev_close_input_stream;
4590 adev->device.dump = adev_dump;
4591
4592 /* Set the default route before the PCM stream is opened */
4593 pthread_mutex_lock(&adev->lock);
4594 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004595 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004596 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004597 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004598 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004599 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004600 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004601 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004602 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004603 pthread_mutex_unlock(&adev->lock);
4604
4605 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004606 adev->platform = platform_init(adev);
4607 if (!adev->platform) {
4608 free(adev->snd_dev_ref_cnt);
4609 free(adev);
4610 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4611 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004612 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004613 return -EINVAL;
4614 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05004615 adev->extspk = audio_extn_extspk_init(adev);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004616 audio_extn_sound_trigger_init(adev);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004617
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004618 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4619 if (adev->visualizer_lib == NULL) {
4620 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4621 } else {
4622 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4623 adev->visualizer_start_output =
4624 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4625 "visualizer_hal_start_output");
4626 adev->visualizer_stop_output =
4627 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4628 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07004629 }
4630
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004631 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4632 if (adev->offload_effects_lib == NULL) {
4633 ALOGW("%s: DLOPEN failed for %s", __func__,
4634 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4635 } else {
4636 ALOGV("%s: DLOPEN successful for %s", __func__,
4637 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4638 adev->offload_effects_start_output =
4639 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4640 "offload_effects_bundle_hal_start_output");
4641 adev->offload_effects_stop_output =
4642 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4643 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07004644 }
4645
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004646 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4647 if (adev->adm_lib == NULL) {
4648 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4649 } else {
4650 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4651 adev->adm_init = (adm_init_t)
4652 dlsym(adev->adm_lib, "adm_init");
4653 adev->adm_deinit = (adm_deinit_t)
4654 dlsym(adev->adm_lib, "adm_deinit");
4655 adev->adm_register_input_stream = (adm_register_input_stream_t)
4656 dlsym(adev->adm_lib, "adm_register_input_stream");
4657 adev->adm_register_output_stream = (adm_register_output_stream_t)
4658 dlsym(adev->adm_lib, "adm_register_output_stream");
4659 adev->adm_deregister_stream = (adm_deregister_stream_t)
4660 dlsym(adev->adm_lib, "adm_deregister_stream");
4661 adev->adm_request_focus = (adm_request_focus_t)
4662 dlsym(adev->adm_lib, "adm_request_focus");
4663 adev->adm_abandon_focus = (adm_abandon_focus_t)
4664 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08004665 adev->adm_set_config = (adm_set_config_t)
4666 dlsym(adev->adm_lib, "adm_set_config");
4667 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4668 dlsym(adev->adm_lib, "adm_request_focus_v2");
4669 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4670 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4671 adev->adm_on_routing_change = (adm_on_routing_change_t)
4672 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004673 }
4674
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004675 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004676 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004677
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004678 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004679
Andy Hung31aca912014-03-20 17:14:59 -07004680 if (k_enable_extended_precision)
4681 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004682
Glenn Kasten4f993392014-05-14 07:30:48 -07004683 char value[PROPERTY_VALUE_MAX];
4684 int trial;
4685 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4686 trial = atoi(value);
4687 if (period_size_is_plausible_for_low_latency(trial)) {
4688 pcm_config_low_latency.period_size = trial;
4689 pcm_config_low_latency.start_threshold = trial / 4;
4690 pcm_config_low_latency.avail_min = trial / 4;
4691 configured_low_latency_capture_period_size = trial;
4692 }
4693 }
4694 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4695 trial = atoi(value);
4696 if (period_size_is_plausible_for_low_latency(trial)) {
4697 configured_low_latency_capture_period_size = trial;
4698 }
4699 }
4700
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004701 // commented as full set of app type cfg is sent from platform
4702 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004703 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004704
4705 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4706 af_period_multiplier = atoi(value);
4707 if (af_period_multiplier < 0) {
4708 af_period_multiplier = 2;
4709 } else if (af_period_multiplier > 4) {
4710 af_period_multiplier = 4;
4711 }
4712 ALOGV("new period_multiplier = %d", af_period_multiplier);
4713 }
4714
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004715 audio_extn_tfa_98xx_init(adev);
4716
vivek mehta1a9b7c02015-06-25 11:49:38 -07004717 pthread_mutex_unlock(&adev_init_lock);
4718
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004719 if (adev->adm_init)
4720 adev->adm_data = adev->adm_init();
4721
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004722 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004723 audio_extn_snd_mon_init();
4724 pthread_mutex_lock(&adev->lock);
4725 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
4726 adev->card_status = CARD_STATUS_ONLINE;
4727 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004728
Eric Laurent2bafff12016-03-17 12:17:23 -07004729 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004730 return 0;
4731}
4732
4733static struct hw_module_methods_t hal_module_methods = {
4734 .open = adev_open,
4735};
4736
4737struct audio_module HAL_MODULE_INFO_SYM = {
4738 .common = {
4739 .tag = HARDWARE_MODULE_TAG,
4740 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4741 .hal_api_version = HARDWARE_HAL_API_VERSION,
4742 .id = AUDIO_HARDWARE_MODULE_ID,
4743 .name = "QCOM Audio HAL",
4744 .author = "Code Aurora Forum",
4745 .methods = &hal_module_methods,
4746 },
4747};