blob: 7d9a366126bcc4add8be3b93b16c8040bdfc17d2 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
vivek mehtaa51fd402016-02-04 19:49:33 -08002 * Copyright (C) 2013-2016 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "audio_hw_primary"
Haynes Mathew George03c40102016-01-29 17:57:48 -080018#define ATRACE_TAG ATRACE_TAG_AUDIO
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080019/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070020/*#define VERY_VERY_VERBOSE_LOGGING*/
21#ifdef VERY_VERY_VERBOSE_LOGGING
22#define ALOGVV ALOGV
23#else
24#define ALOGVV(a...) do { } while(0)
25#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080026
27#include <errno.h>
28#include <pthread.h>
29#include <stdint.h>
30#include <sys/time.h>
31#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080032#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070033#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070034#include <sys/resource.h>
35#include <sys/prctl.h>
Kevin Rocardb5c28192017-05-02 15:30:20 -070036#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080037
38#include <cutils/log.h>
Haynes Mathew George03c40102016-01-29 17:57:48 -080039#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040#include <cutils/str_parms.h>
41#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070042#include <cutils/atomic.h>
43#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080044
Eric Laurentb23d5282013-05-14 15:27:20 -070045#include <hardware/audio_effect.h>
Andy Hung31aca912014-03-20 17:14:59 -070046#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070047#include <system/thread_defs.h>
Phil Burkbc991042017-02-24 08:06:44 -080048#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070049#include <audio_effects/effect_aec.h>
50#include <audio_effects/effect_ns.h>
Andy Hungfc044e12017-03-20 09:24:22 -070051#include <audio_utils/clock.h>
52#include <audio_utils/power.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include "audio_hw.h"
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -080054#include "audio_extn.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070055#include "platform_api.h"
56#include <platform.h>
Vineeta Srivastava4b89e372014-06-19 14:21:42 -070057#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080058
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070059#include "sound/compress_params.h"
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -080060#include "audio_extn/tfa_98xx.h"
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070061
Eric Laurent397db572016-05-11 11:31:47 -070062/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
63 * COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
Marco Nelissen32093f52015-04-08 15:14:02 -070064#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070065// 2 buffers causes problems with high bitrate files
66#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070067/* ToDo: Check and update a proper value in msec */
68#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
69#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
70
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070071#define PROXY_OPEN_RETRY_COUNT 100
72#define PROXY_OPEN_WAIT_TIME 20
73
vivek mehtadae44712015-07-27 14:13:18 -070074#define MIN_CHANNEL_COUNT 1
75#define DEFAULT_CHANNEL_COUNT 2
76
Jean-Michel Trivic0750692015-10-12 12:12:32 -070077#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
78#define MAX_CHANNEL_COUNT 1
79#else
vivek mehtadae44712015-07-27 14:13:18 -070080#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
81#define XSTR(x) STR(x)
82#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070083#endif
vivek mehtadae44712015-07-27 14:13:18 -070084
Haynes Mathew George03c40102016-01-29 17:57:48 -080085#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
86
Glenn Kasten4f993392014-05-14 07:30:48 -070087static unsigned int configured_low_latency_capture_period_size =
88 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
89
Eric Laurent0e46adf2016-12-16 12:49:24 -080090
91#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Phil Burkbc991042017-02-24 08:06:44 -080092#define MMAP_PERIOD_COUNT_MIN 32
93#define MMAP_PERIOD_COUNT_MAX 512
94#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
Eric Laurent0e46adf2016-12-16 12:49:24 -080095
96
Andy Hung31aca912014-03-20 17:14:59 -070097/* This constant enables extended precision handling.
98 * TODO The flag is off until more testing is done.
99 */
100static const bool k_enable_extended_precision = false;
101
Eric Laurentb23d5282013-05-14 15:27:20 -0700102struct pcm_config pcm_config_deep_buffer = {
vivek mehtadae44712015-07-27 14:13:18 -0700103 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700104 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
105 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
106 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
107 .format = PCM_FORMAT_S16_LE,
108 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
109 .stop_threshold = INT_MAX,
110 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
111};
112
113struct pcm_config pcm_config_low_latency = {
vivek mehtadae44712015-07-27 14:13:18 -0700114 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700115 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
116 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
117 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
118 .format = PCM_FORMAT_S16_LE,
119 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
120 .stop_threshold = INT_MAX,
121 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
122};
123
Haynes Mathew George03c40102016-01-29 17:57:48 -0800124static int af_period_multiplier = 4;
125struct pcm_config pcm_config_rt = {
126 .channels = DEFAULT_CHANNEL_COUNT,
127 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
128 .period_size = ULL_PERIOD_SIZE, //1 ms
129 .period_count = 512, //=> buffer size is 512ms
130 .format = PCM_FORMAT_S16_LE,
131 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
132 .stop_threshold = INT_MAX,
133 .silence_threshold = 0,
134 .silence_size = 0,
135 .avail_min = ULL_PERIOD_SIZE, //1 ms
136};
137
Eric Laurentb23d5282013-05-14 15:27:20 -0700138struct pcm_config pcm_config_hdmi_multi = {
139 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
140 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
141 .period_size = HDMI_MULTI_PERIOD_SIZE,
142 .period_count = HDMI_MULTI_PERIOD_COUNT,
143 .format = PCM_FORMAT_S16_LE,
144 .start_threshold = 0,
145 .stop_threshold = INT_MAX,
146 .avail_min = 0,
147};
148
Eric Laurent0e46adf2016-12-16 12:49:24 -0800149struct pcm_config pcm_config_mmap_playback = {
150 .channels = DEFAULT_CHANNEL_COUNT,
151 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
152 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800153 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800154 .format = PCM_FORMAT_S16_LE,
155 .start_threshold = MMAP_PERIOD_SIZE*8,
156 .stop_threshold = INT32_MAX,
157 .silence_threshold = 0,
158 .silence_size = 0,
159 .avail_min = MMAP_PERIOD_SIZE, //1 ms
160};
161
Eric Laurentb23d5282013-05-14 15:27:20 -0700162struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700163 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700164 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
165 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700166 .stop_threshold = INT_MAX,
167 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700168};
169
Haynes Mathew George03c40102016-01-29 17:57:48 -0800170struct pcm_config pcm_config_audio_capture_rt = {
171 .channels = DEFAULT_CHANNEL_COUNT,
172 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
173 .period_size = ULL_PERIOD_SIZE,
174 .period_count = 512,
175 .format = PCM_FORMAT_S16_LE,
176 .start_threshold = 0,
177 .stop_threshold = INT_MAX,
178 .silence_threshold = 0,
179 .silence_size = 0,
180 .avail_min = ULL_PERIOD_SIZE, //1 ms
181};
182
Eric Laurent0e46adf2016-12-16 12:49:24 -0800183struct pcm_config pcm_config_mmap_capture = {
184 .channels = DEFAULT_CHANNEL_COUNT,
185 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
186 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800187 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800188 .format = PCM_FORMAT_S16_LE,
189 .start_threshold = 0,
190 .stop_threshold = INT_MAX,
191 .silence_threshold = 0,
192 .silence_size = 0,
193 .avail_min = MMAP_PERIOD_SIZE, //1 ms
194};
195
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700196#define AFE_PROXY_CHANNEL_COUNT 2
197#define AFE_PROXY_SAMPLING_RATE 48000
198
199#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
200#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
201
202struct pcm_config pcm_config_afe_proxy_playback = {
203 .channels = AFE_PROXY_CHANNEL_COUNT,
204 .rate = AFE_PROXY_SAMPLING_RATE,
205 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
206 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
207 .format = PCM_FORMAT_S16_LE,
208 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
209 .stop_threshold = INT_MAX,
210 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
211};
212
213#define AFE_PROXY_RECORD_PERIOD_SIZE 768
214#define AFE_PROXY_RECORD_PERIOD_COUNT 4
215
216struct pcm_config pcm_config_afe_proxy_record = {
217 .channels = AFE_PROXY_CHANNEL_COUNT,
218 .rate = AFE_PROXY_SAMPLING_RATE,
219 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
220 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
221 .format = PCM_FORMAT_S16_LE,
222 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
223 .stop_threshold = INT_MAX,
224 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
225};
226
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700227const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700228 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
229 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
230 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700231 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700232 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700233 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800234 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700235
Eric Laurentb23d5282013-05-14 15:27:20 -0700236 [USECASE_AUDIO_RECORD] = "audio-record",
237 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800238 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700239
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800240 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
241 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700242
Eric Laurentb23d5282013-05-14 15:27:20 -0700243 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700244 [USECASE_VOICE2_CALL] = "voice2-call",
245 [USECASE_VOLTE_CALL] = "volte-call",
246 [USECASE_QCHAT_CALL] = "qchat-call",
247 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800248 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
249 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700250
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700251 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
252 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
253
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700254 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
255 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700256};
257
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800258
259#define STRING_TO_ENUM(string) { #string, string }
260
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800261struct string_to_enum {
262 const char *name;
263 uint32_t value;
264};
265
266static const struct string_to_enum out_channels_name_to_enum_table[] = {
267 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
268 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
269 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
270};
271
Haynes Mathew George5191a852013-09-11 14:19:36 -0700272static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700273static struct audio_device *adev = NULL;
274static pthread_mutex_t adev_init_lock;
275static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700276//cache last MBDRC cal step level
277static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700278
Haynes Mathew George03c40102016-01-29 17:57:48 -0800279static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
280 int flags __unused)
281{
282 int dir = 0;
283 switch (uc_id) {
284 case USECASE_AUDIO_RECORD_LOW_LATENCY:
285 dir = 1;
286 case USECASE_AUDIO_PLAYBACK_ULL:
287 break;
288 default:
289 return false;
290 }
291
292 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
293 PCM_PLAYBACK : PCM_CAPTURE);
294 if (adev->adm_is_noirq_avail)
295 return adev->adm_is_noirq_avail(adev->adm_data,
296 adev->snd_card, dev_id, dir);
297 return false;
298}
299
300static void register_out_stream(struct stream_out *out)
301{
302 struct audio_device *adev = out->dev;
303 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
304 return;
305
306 if (!adev->adm_register_output_stream)
307 return;
308
309 adev->adm_register_output_stream(adev->adm_data,
310 out->handle,
311 out->flags);
312
313 if (!adev->adm_set_config)
314 return;
315
316 if (out->realtime) {
317 adev->adm_set_config(adev->adm_data,
318 out->handle,
319 out->pcm, &out->config);
320 }
321}
322
323static void register_in_stream(struct stream_in *in)
324{
325 struct audio_device *adev = in->dev;
326 if (!adev->adm_register_input_stream)
327 return;
328
329 adev->adm_register_input_stream(adev->adm_data,
330 in->capture_handle,
331 in->flags);
332
333 if (!adev->adm_set_config)
334 return;
335
336 if (in->realtime) {
337 adev->adm_set_config(adev->adm_data,
338 in->capture_handle,
339 in->pcm,
340 &in->config);
341 }
342}
343
344static void request_out_focus(struct stream_out *out, long ns)
345{
346 struct audio_device *adev = out->dev;
347
348 if (out->routing_change) {
349 out->routing_change = false;
350 if (adev->adm_on_routing_change)
351 adev->adm_on_routing_change(adev->adm_data, out->handle);
352 }
353
354 if (adev->adm_request_focus_v2) {
355 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
356 } else if (adev->adm_request_focus) {
357 adev->adm_request_focus(adev->adm_data, out->handle);
358 }
359}
360
361static void request_in_focus(struct stream_in *in, long ns)
362{
363 struct audio_device *adev = in->dev;
364
365 if (in->routing_change) {
366 in->routing_change = false;
367 if (adev->adm_on_routing_change)
368 adev->adm_on_routing_change(adev->adm_data, in->capture_handle);
369 }
370
371 if (adev->adm_request_focus_v2) {
372 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
373 } else if (adev->adm_request_focus) {
374 adev->adm_request_focus(adev->adm_data, in->capture_handle);
375 }
376}
377
378static void release_out_focus(struct stream_out *out, long ns __unused)
379{
380 struct audio_device *adev = out->dev;
381
382 if (adev->adm_abandon_focus)
383 adev->adm_abandon_focus(adev->adm_data, out->handle);
384}
385
386static void release_in_focus(struct stream_in *in, long ns __unused)
387{
388 struct audio_device *adev = in->dev;
389 if (adev->adm_abandon_focus)
390 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
391}
392
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700393static int parse_snd_card_status(struct str_parms * parms, int * card,
394 card_status_t * status)
395{
396 char value[32]={0};
397 char state[32]={0};
398
399 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
400
401 if (ret < 0)
402 return -1;
403
404 // sscanf should be okay as value is of max length 32.
405 // same as sizeof state.
406 if (sscanf(value, "%d,%s", card, state) < 2)
407 return -1;
408
409 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
410 CARD_STATUS_OFFLINE;
411 return 0;
412}
413
vivek mehta1a9b7c02015-06-25 11:49:38 -0700414__attribute__ ((visibility ("default")))
415bool audio_hw_send_gain_dep_calibration(int level) {
416 bool ret_val = false;
417 ALOGV("%s: enter ... ", __func__);
418
419 pthread_mutex_lock(&adev_init_lock);
420
421 if (adev != NULL && adev->platform != NULL) {
422 pthread_mutex_lock(&adev->lock);
423 ret_val = platform_send_gain_dep_cal(adev->platform, level);
424 pthread_mutex_unlock(&adev->lock);
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700425
426 // if cal set fails, cache level info
427 // if cal set succeds, reset known last cal set
428 if (!ret_val)
429 last_known_cal_step = level;
430 else if (last_known_cal_step != -1)
431 last_known_cal_step = -1;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700432 } else {
433 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
434 }
435
436 pthread_mutex_unlock(&adev_init_lock);
437
438 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
439 return ret_val;
440}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700441
vivek mehtaa8d7c922016-05-25 14:40:44 -0700442__attribute__ ((visibility ("default")))
443int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
444 int table_size) {
445 int ret_val = 0;
446 ALOGV("%s: enter ... ", __func__);
447
448 pthread_mutex_lock(&adev_init_lock);
449 if (adev == NULL) {
450 ALOGW("%s: adev is NULL .... ", __func__);
451 goto done;
452 }
453
454 pthread_mutex_lock(&adev->lock);
455 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
456 pthread_mutex_unlock(&adev->lock);
457done:
458 pthread_mutex_unlock(&adev_init_lock);
459 ALOGV("%s: exit ... ", __func__);
460 return ret_val;
461}
462
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700463static bool is_supported_format(audio_format_t format)
464{
Eric Laurent8251ac82014-07-23 11:00:25 -0700465 switch (format) {
466 case AUDIO_FORMAT_MP3:
467 case AUDIO_FORMAT_AAC_LC:
468 case AUDIO_FORMAT_AAC_HE_V1:
469 case AUDIO_FORMAT_AAC_HE_V2:
470 return true;
471 default:
472 break;
473 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700474 return false;
475}
476
Haynes Mathew George03c40102016-01-29 17:57:48 -0800477static inline bool is_mmap_usecase(audio_usecase_t uc_id)
478{
479 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
480 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
481}
482
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700483static int get_snd_codec_id(audio_format_t format)
484{
485 int id = 0;
486
Eric Laurent8251ac82014-07-23 11:00:25 -0700487 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700488 case AUDIO_FORMAT_MP3:
489 id = SND_AUDIOCODEC_MP3;
490 break;
491 case AUDIO_FORMAT_AAC:
492 id = SND_AUDIOCODEC_AAC;
493 break;
494 default:
495 ALOGE("%s: Unsupported audio format", __func__);
496 }
497
498 return id;
499}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800500
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800501static int audio_ssr_status(struct audio_device *adev)
502{
503 int ret = 0;
504 struct mixer_ctl *ctl;
505 const char *mixer_ctl_name = "Audio SSR Status";
506
507 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
508 ret = mixer_ctl_get_value(ctl, 0);
509 ALOGD("%s: value: %d", __func__, ret);
510 return ret;
511}
512
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800513int enable_audio_route(struct audio_device *adev,
514 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800515{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700516 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800517 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800518
519 if (usecase == NULL)
520 return -EINVAL;
521
522 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
523
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800524 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700525 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800526 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700527 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800528
Yamit Mehtae3b99562016-09-16 22:44:00 +0530529 audio_extn_utils_send_app_type_cfg(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800530 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500531 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700532 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700533 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800534
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800535 ALOGV("%s: exit", __func__);
536 return 0;
537}
538
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800539int disable_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);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700549 if (usecase->type == PCM_CAPTURE)
550 snd_device = usecase->in_snd_device;
551 else
552 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800553 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500554 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700555 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700556 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800557
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800558 ALOGV("%s: exit", __func__);
559 return 0;
560}
561
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800562int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700563 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800564{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700565 int i, num_devices = 0;
566 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800567 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800568 if (snd_device < SND_DEVICE_MIN ||
569 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800570 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800571 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800572 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700573
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700574 platform_send_audio_calibration(adev->platform, snd_device);
575
vivek mehtade4849c2016-03-03 17:23:38 -0800576 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700577 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700578 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800579 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700580 }
581
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700582 /* due to the possibility of calibration overwrite between listen
583 and audio, notify sound trigger hal before audio calibration is sent */
584 audio_extn_sound_trigger_update_device_status(snd_device,
585 ST_EVENT_SND_DEVICE_BUSY);
586
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700587 if (audio_extn_spkr_prot_is_enabled())
588 audio_extn_spkr_prot_calib_cancel(adev);
589
zhaoyang yin4211fad2015-06-04 21:13:25 +0800590 audio_extn_dsm_feedback_enable(adev, snd_device, true);
591
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700592 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
593 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
594 audio_extn_spkr_prot_is_enabled()) {
595 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800596 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700597 }
598 if (audio_extn_spkr_prot_start_processing(snd_device)) {
599 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800600 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700601 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700602 } else if (platform_can_split_snd_device(snd_device,
603 &num_devices,
604 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700605 for (i = 0; i < num_devices; i++) {
606 enable_snd_device(adev, new_snd_devices[i]);
607 }
vivek mehtab6506412015-08-07 16:55:17 -0700608 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700609 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800610 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
611 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
612 ALOGE(" %s: Invalid sound device returned", __func__);
613 goto on_error;
614 }
Ed Tam70b5c142016-03-21 19:14:29 -0700615
Eric Laurent2e140aa2016-06-30 17:14:46 -0700616 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800617 audio_route_apply_and_update_path(adev->audio_route, device_name);
618 }
619on_success:
620 adev->snd_dev_ref_cnt[snd_device]++;
621 ret_val = 0;
622on_error:
623 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800624}
625
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800626int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700627 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800628{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700629 int i, num_devices = 0;
630 snd_device_t new_snd_devices[2];
631
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800632 if (snd_device < SND_DEVICE_MIN ||
633 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800634 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800635 return -EINVAL;
636 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700637 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
638 ALOGE("%s: device ref cnt is already 0", __func__);
639 return -EINVAL;
640 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800641 audio_extn_tfa_98xx_disable_speaker(snd_device);
642
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700643 adev->snd_dev_ref_cnt[snd_device]--;
644 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800645 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700646 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
647 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
648 audio_extn_spkr_prot_is_enabled()) {
649 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700650 } else if (platform_can_split_snd_device(snd_device,
651 &num_devices,
652 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700653 for (i = 0; i < num_devices; i++) {
654 disable_snd_device(adev, new_snd_devices[i]);
655 }
vivek mehtab6506412015-08-07 16:55:17 -0700656 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700657 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800658 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
659 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
660 ALOGE(" %s: Invalid sound device returned", __func__);
661 return -EINVAL;
662 }
663
Eric Laurent2e140aa2016-06-30 17:14:46 -0700664 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800665 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700666 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700667 audio_extn_sound_trigger_update_device_status(snd_device,
668 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700669 }
vivek mehtab6506412015-08-07 16:55:17 -0700670
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800671 return 0;
672}
673
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700674/*
675 legend:
676 uc - existing usecase
677 new_uc - new usecase
678 d1, d11, d2 - SND_DEVICE enums
679 a1, a2 - corresponding ANDROID device enums
680 B, B1, B2 - backend strings
681
682case 1
683 uc->dev d1 (a1) B1
684 new_uc->dev d1 (a1), d2 (a2) B1, B2
685
686 resolution: disable and enable uc->dev on d1
687
688case 2
689 uc->dev d1 (a1) B1
690 new_uc->dev d11 (a1) B1
691
692 resolution: need to switch uc since d1 and d11 are related
693 (e.g. speaker and voice-speaker)
694 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
695
696case 3
697 uc->dev d1 (a1) B1
698 new_uc->dev d2 (a2) B2
699
700 resolution: no need to switch uc
701
702case 4
703 uc->dev d1 (a1) B
704 new_uc->dev d2 (a2) B
705
706 resolution: disable enable uc-dev on d2 since backends match
707 we cannot enable two streams on two different devices if they
708 share the same backend. e.g. if offload is on speaker device using
709 QUAD_MI2S backend and a low-latency stream is started on voice-handset
710 using the same backend, offload must also be switched to voice-handset.
711
712case 5
713 uc->dev d1 (a1) B
714 new_uc->dev d1 (a1), d2 (a2) B
715
716 resolution: disable enable uc-dev on d2 since backends match
717 we cannot enable two streams on two different devices if they
718 share the same backend.
719
720case 6
721 uc->dev d1 a1 B1
722 new_uc->dev d2 a1 B2
723
724 resolution: no need to switch
725
726case 7
727
728 uc->dev d1 (a1), d2 (a2) B1, B2
729 new_uc->dev d1 B1
730
731 resolution: no need to switch
732
733*/
734static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
735 struct audio_usecase *new_uc,
736 snd_device_t new_snd_device)
737{
738 audio_devices_t a1 = uc->stream.out->devices;
739 audio_devices_t a2 = new_uc->stream.out->devices;
740
741 snd_device_t d1 = uc->out_snd_device;
742 snd_device_t d2 = new_snd_device;
743
744 // Treat as a special case when a1 and a2 are not disjoint
745 if ((a1 != a2) && (a1 & a2)) {
746 snd_device_t d3[2];
747 int num_devices = 0;
748 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
749 &num_devices,
750 d3);
751 if (ret < 0) {
752 if (ret != -ENOSYS) {
753 ALOGW("%s failed to split snd_device %d",
754 __func__,
755 popcount(a1) > 1 ? d1 : d2);
756 }
757 goto end;
758 }
759
760 // NB: case 7 is hypothetical and isn't a practical usecase yet.
761 // But if it does happen, we need to give priority to d2 if
762 // the combo devices active on the existing usecase share a backend.
763 // This is because we cannot have a usecase active on a combo device
764 // and a new usecase requests one device in this combo pair.
765 if (platform_check_backends_match(d3[0], d3[1])) {
766 return d2; // case 5
767 } else {
768 return d1; // case 1
769 }
770 } else {
771 if (platform_check_backends_match(d1, d2)) {
772 return d2; // case 2, 4
773 } else {
774 return d1; // case 6, 3
775 }
776 }
777
778end:
779 return d2; // return whatever was calculated before.
780}
781
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700782static void check_and_route_playback_usecases(struct audio_device *adev,
783 struct audio_usecase *uc_info,
784 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700785{
786 struct listnode *node;
787 struct audio_usecase *usecase;
788 bool switch_device[AUDIO_USECASE_MAX];
789 int i, num_uc_to_switch = 0;
790
David Linee3fe402017-03-13 10:00:42 -0700791 platform_check_and_set_playback_backend_cfg(adev, uc_info, snd_device);
792
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700793 /*
794 * This function is to make sure that all the usecases that are active on
795 * the hardware codec backend are always routed to any one device that is
796 * handled by the hardware codec.
797 * For example, if low-latency and deep-buffer usecases are currently active
798 * on speaker and out_set_parameters(headset) is received on low-latency
799 * output, then we have to make sure deep-buffer is also switched to headset,
800 * because of the limitation that both the devices cannot be enabled
801 * at the same time as they share the same backend.
802 */
803 /* Disable all the usecases on the shared backend other than the
804 specified usecase */
805 for (i = 0; i < AUDIO_USECASE_MAX; i++)
806 switch_device[i] = false;
807
808 list_for_each(node, &adev->usecase_list) {
809 usecase = node_to_item(node, struct audio_usecase, list);
810 if (usecase->type != PCM_CAPTURE &&
811 usecase != uc_info &&
812 usecase->out_snd_device != snd_device &&
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700813 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
814 platform_check_backends_match(snd_device, usecase->out_snd_device)) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700815 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
816 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700817 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700818 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700819 switch_device[usecase->id] = true;
820 num_uc_to_switch++;
821 }
822 }
823
824 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700825 list_for_each(node, &adev->usecase_list) {
826 usecase = node_to_item(node, struct audio_usecase, list);
827 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700828 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900829 }
830 }
831
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700832 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900833 list_for_each(node, &adev->usecase_list) {
834 usecase = node_to_item(node, struct audio_usecase, list);
835 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700836 d_device = derive_playback_snd_device(usecase, uc_info,
837 snd_device);
838 enable_snd_device(adev, d_device);
839 /* Update the out_snd_device before enabling the audio route */
840 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700841 }
842 }
843
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700844 /* Re-route all the usecases on the shared backend other than the
845 specified usecase to new snd devices */
846 list_for_each(node, &adev->usecase_list) {
847 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700848 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700849 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700850 }
851 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700852 }
853}
854
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700855static void check_and_route_capture_usecases(struct audio_device *adev,
856 struct audio_usecase *uc_info,
857 snd_device_t snd_device)
858{
859 struct listnode *node;
860 struct audio_usecase *usecase;
861 bool switch_device[AUDIO_USECASE_MAX];
862 int i, num_uc_to_switch = 0;
863
vivek mehta4ed66e62016-04-15 23:33:34 -0700864 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
865
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700866 /*
867 * This function is to make sure that all the active capture usecases
868 * are always routed to the same input sound device.
869 * For example, if audio-record and voice-call usecases are currently
870 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
871 * is received for voice call then we have to make sure that audio-record
872 * usecase is also switched to earpiece i.e. voice-dmic-ef,
873 * because of the limitation that two devices cannot be enabled
874 * at the same time if they share the same backend.
875 */
876 for (i = 0; i < AUDIO_USECASE_MAX; i++)
877 switch_device[i] = false;
878
879 list_for_each(node, &adev->usecase_list) {
880 usecase = node_to_item(node, struct audio_usecase, list);
881 if (usecase->type != PCM_PLAYBACK &&
882 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700883 usecase->in_snd_device != snd_device &&
884 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700885 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
886 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700887 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700888 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700889 switch_device[usecase->id] = true;
890 num_uc_to_switch++;
891 }
892 }
893
894 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700895 list_for_each(node, &adev->usecase_list) {
896 usecase = node_to_item(node, struct audio_usecase, list);
897 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700898 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700899 }
900 }
901
902 list_for_each(node, &adev->usecase_list) {
903 usecase = node_to_item(node, struct audio_usecase, list);
904 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700905 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700906 }
907 }
908
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700909 /* Re-route all the usecases on the shared backend other than the
910 specified usecase to new snd devices */
911 list_for_each(node, &adev->usecase_list) {
912 usecase = node_to_item(node, struct audio_usecase, list);
913 /* Update the in_snd_device only before enabling the audio route */
914 if (switch_device[usecase->id] ) {
915 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700916 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700917 }
918 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700919 }
920}
921
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800922/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700923static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800924{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700925 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700926 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800927
928 switch (channels) {
929 /*
930 * Do not handle stereo output in Multi-channel cases
931 * Stereo case is handled in normal playback path
932 */
933 case 6:
934 ALOGV("%s: HDMI supports 5.1", __func__);
935 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
936 break;
937 case 8:
938 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
939 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
940 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
941 break;
942 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700943 ALOGE("HDMI does not support multi channel playback");
944 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800945 break;
946 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700947 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800948}
949
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -0700950static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
951{
952 struct audio_usecase *usecase;
953 struct listnode *node;
954
955 list_for_each(node, &adev->usecase_list) {
956 usecase = node_to_item(node, struct audio_usecase, list);
957 if (usecase->type == VOICE_CALL) {
958 ALOGV("%s: usecase id %d", __func__, usecase->id);
959 return usecase->id;
960 }
961 }
962 return USECASE_INVALID;
963}
964
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800965struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
966 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700967{
968 struct audio_usecase *usecase;
969 struct listnode *node;
970
971 list_for_each(node, &adev->usecase_list) {
972 usecase = node_to_item(node, struct audio_usecase, list);
973 if (usecase->id == uc_id)
974 return usecase;
975 }
976 return NULL;
977}
978
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800979int select_devices(struct audio_device *adev,
980 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800981{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800982 snd_device_t out_snd_device = SND_DEVICE_NONE;
983 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700984 struct audio_usecase *usecase = NULL;
985 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800986 struct audio_usecase *hfp_usecase = NULL;
987 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800988 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700989 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800990
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700991 usecase = get_usecase_from_list(adev, uc_id);
992 if (usecase == NULL) {
993 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
994 return -EINVAL;
995 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800996
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800997 if ((usecase->type == VOICE_CALL) ||
998 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700999 out_snd_device = platform_get_output_snd_device(adev->platform,
1000 usecase->stream.out->devices);
1001 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001002 usecase->devices = usecase->stream.out->devices;
1003 } else {
1004 /*
1005 * If the voice call is active, use the sound devices of voice call usecase
1006 * so that it would not result any device switch. All the usecases will
1007 * be switched to new device when select_devices() is called for voice call
1008 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001009 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001010 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001011 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001012 vc_usecase = get_usecase_from_list(adev,
1013 get_voice_usecase_id_from_list(adev));
1014 if ((vc_usecase != NULL) &&
1015 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1016 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001017 in_snd_device = vc_usecase->in_snd_device;
1018 out_snd_device = vc_usecase->out_snd_device;
1019 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001020 } else if (audio_extn_hfp_is_active(adev)) {
1021 hfp_ucid = audio_extn_hfp_get_usecase();
1022 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1023 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1024 in_snd_device = hfp_usecase->in_snd_device;
1025 out_snd_device = hfp_usecase->out_snd_device;
1026 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001027 }
1028 if (usecase->type == PCM_PLAYBACK) {
1029 usecase->devices = usecase->stream.out->devices;
1030 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001031 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001032 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001033 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001034 if (usecase->stream.out == adev->primary_output &&
1035 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001036 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1037 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001038 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001039 select_devices(adev, adev->active_input->usecase);
1040 }
1041 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001042 } else if (usecase->type == PCM_CAPTURE) {
1043 usecase->devices = usecase->stream.in->device;
1044 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001045 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001046 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001047 if (adev->active_input &&
1048 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1049 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001050 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001051 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1052 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
1053 } else if (adev->primary_output) {
1054 out_device = adev->primary_output->devices;
1055 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001056 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001057 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001058 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001059 }
1060 }
1061
1062 if (out_snd_device == usecase->out_snd_device &&
1063 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001064 return 0;
1065 }
1066
Eric Laurent2bafff12016-03-17 12:17:23 -07001067 if (out_snd_device != SND_DEVICE_NONE &&
1068 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1069 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1070 __func__,
1071 use_case_table[uc_id],
1072 adev->last_logged_snd_device[uc_id][0],
1073 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1074 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1075 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1076 -1,
1077 out_snd_device,
1078 platform_get_snd_device_name(out_snd_device),
1079 platform_get_snd_device_acdb_id(out_snd_device));
1080 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1081 }
1082 if (in_snd_device != SND_DEVICE_NONE &&
1083 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1084 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1085 __func__,
1086 use_case_table[uc_id],
1087 adev->last_logged_snd_device[uc_id][1],
1088 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1089 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1090 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1091 -1,
1092 in_snd_device,
1093 platform_get_snd_device_name(in_snd_device),
1094 platform_get_snd_device_acdb_id(in_snd_device));
1095 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1096 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001097
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001098 /*
1099 * Limitation: While in call, to do a device switch we need to disable
1100 * and enable both RX and TX devices though one of them is same as current
1101 * device.
1102 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001103 if ((usecase->type == VOICE_CALL) &&
1104 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1105 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001106 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001107 /* Disable sidetone only if voice call already exists */
1108 if (voice_is_call_state_active(adev))
1109 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001110 }
1111
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001112 /* Disable current sound devices */
1113 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001114 disable_audio_route(adev, usecase);
1115 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001116 }
1117
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001118 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001119 disable_audio_route(adev, usecase);
1120 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001121 }
1122
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001123 /* Applicable only on the targets that has external modem.
1124 * New device information should be sent to modem before enabling
1125 * the devices to reduce in-call device switch time.
1126 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001127 if ((usecase->type == VOICE_CALL) &&
1128 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1129 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001130 status = platform_switch_voice_call_enable_device_config(adev->platform,
1131 out_snd_device,
1132 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001133 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001134
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001135 /* Enable new sound devices */
1136 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001137 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1138 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001139 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001140 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001141 }
1142
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001143 if (in_snd_device != SND_DEVICE_NONE) {
1144 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001145 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001146 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001147
Eric Laurentb23d5282013-05-14 15:27:20 -07001148 if (usecase->type == VOICE_CALL)
1149 status = platform_switch_voice_call_device_post(adev->platform,
1150 out_snd_device,
1151 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001152
sangwoo170731f2013-06-08 15:36:36 +09001153 usecase->in_snd_device = in_snd_device;
1154 usecase->out_snd_device = out_snd_device;
1155
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001156 audio_extn_tfa_98xx_set_mode();
1157
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001158 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001159
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001160 /* Applicable only on the targets that has external modem.
1161 * Enable device command should be sent to modem only after
1162 * enabling voice call mixer controls
1163 */
vivek mehta765eb642015-08-07 19:46:06 -07001164 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001165 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1166 out_snd_device,
1167 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001168 /* Enable sidetone only if voice call already exists */
1169 if (voice_is_call_state_active(adev))
1170 voice_set_sidetone(adev, out_snd_device, true);
1171 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001172
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001173 return status;
1174}
1175
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001176static int stop_input_stream(struct stream_in *in)
1177{
1178 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001179 struct audio_usecase *uc_info;
1180 struct audio_device *adev = in->dev;
1181
Eric Laurentc8400632013-02-14 19:04:54 -08001182 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001183
Eric Laurent994a6932013-07-17 11:51:42 -07001184 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001185 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001186 uc_info = get_usecase_from_list(adev, in->usecase);
1187 if (uc_info == NULL) {
1188 ALOGE("%s: Could not find the usecase (%d) in the list",
1189 __func__, in->usecase);
1190 return -EINVAL;
1191 }
1192
Eric Laurent150dbfe2013-02-27 14:31:02 -08001193 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001194 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001195
1196 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001197 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001198
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001199 list_remove(&uc_info->list);
1200 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001201
Eric Laurent994a6932013-07-17 11:51:42 -07001202 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001203 return ret;
1204}
1205
1206int start_input_stream(struct stream_in *in)
1207{
1208 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001209 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001210 struct audio_usecase *uc_info;
1211 struct audio_device *adev = in->dev;
1212
Eric Laurent994a6932013-07-17 11:51:42 -07001213 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001214
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001215 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1216 return -EIO;
1217
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001218 if (in->card_status == CARD_STATUS_OFFLINE ||
1219 adev->card_status == CARD_STATUS_OFFLINE) {
1220 ALOGW("in->card_status or adev->card_status offline, try again");
1221 ret = -EAGAIN;
1222 goto error_config;
1223 }
1224
Eric Laurentb23d5282013-05-14 15:27:20 -07001225 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001226 if (in->pcm_device_id < 0) {
1227 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1228 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001229 ret = -EINVAL;
1230 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001231 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001232
1233 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001234 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1235 uc_info->id = in->usecase;
1236 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001237 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001238 uc_info->devices = in->device;
1239 uc_info->in_snd_device = SND_DEVICE_NONE;
1240 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001241
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001242 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001243
1244 audio_extn_perf_lock_acquire();
1245
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001246 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001247
Eric Laurent0e46adf2016-12-16 12:49:24 -08001248 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001249 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001250 ALOGE("%s: pcm stream not ready", __func__);
1251 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001252 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001253 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001254 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001255 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1256 goto error_open;
1257 }
1258 } else {
1259 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1260 unsigned int pcm_open_retry_count = 0;
1261
1262 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1263 flags |= PCM_MMAP | PCM_NOIRQ;
1264 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1265 } else if (in->realtime) {
1266 flags |= PCM_MMAP | PCM_NOIRQ;
1267 }
1268
1269 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1270 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1271
1272 while (1) {
1273 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1274 flags, &in->config);
1275 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1276 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1277 if (in->pcm != NULL) {
1278 pcm_close(in->pcm);
1279 in->pcm = NULL;
1280 }
1281 if (pcm_open_retry_count-- == 0) {
1282 ret = -EIO;
1283 goto error_open;
1284 }
1285 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1286 continue;
1287 }
1288 break;
1289 }
1290
1291 ALOGV("%s: pcm_prepare", __func__);
1292 ret = pcm_prepare(in->pcm);
1293 if (ret < 0) {
1294 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001295 pcm_close(in->pcm);
1296 in->pcm = NULL;
1297 goto error_open;
1298 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001299 if (in->realtime) {
1300 ret = pcm_start(in->pcm);
1301 if (ret < 0) {
1302 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1303 pcm_close(in->pcm);
1304 in->pcm = NULL;
1305 goto error_open;
1306 }
1307 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001308 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001309 register_in_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001310 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001311 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001312
Eric Laurent0e46adf2016-12-16 12:49:24 -08001313 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001314
1315error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001316 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001317 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001318
1319error_config:
1320 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001321 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001322
1323 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001324}
1325
Eric Laurenta1478072015-09-21 17:21:52 -07001326void lock_input_stream(struct stream_in *in)
1327{
1328 pthread_mutex_lock(&in->pre_lock);
1329 pthread_mutex_lock(&in->lock);
1330 pthread_mutex_unlock(&in->pre_lock);
1331}
1332
1333void lock_output_stream(struct stream_out *out)
1334{
1335 pthread_mutex_lock(&out->pre_lock);
1336 pthread_mutex_lock(&out->lock);
1337 pthread_mutex_unlock(&out->pre_lock);
1338}
1339
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001340/* must be called with out->lock locked */
1341static int send_offload_cmd_l(struct stream_out* out, int command)
1342{
1343 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1344
1345 ALOGVV("%s %d", __func__, command);
1346
1347 cmd->cmd = command;
1348 list_add_tail(&out->offload_cmd_list, &cmd->node);
1349 pthread_cond_signal(&out->offload_cond);
1350 return 0;
1351}
1352
1353/* must be called iwth out->lock locked */
1354static void stop_compressed_output_l(struct stream_out *out)
1355{
1356 out->offload_state = OFFLOAD_STATE_IDLE;
1357 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001358 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001359 if (out->compr != NULL) {
1360 compress_stop(out->compr);
1361 while (out->offload_thread_blocked) {
1362 pthread_cond_wait(&out->cond, &out->lock);
1363 }
1364 }
1365}
1366
1367static void *offload_thread_loop(void *context)
1368{
1369 struct stream_out *out = (struct stream_out *) context;
1370 struct listnode *item;
1371
1372 out->offload_state = OFFLOAD_STATE_IDLE;
1373 out->playback_started = 0;
1374
1375 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1376 set_sched_policy(0, SP_FOREGROUND);
1377 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1378
1379 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001380 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001381 for (;;) {
1382 struct offload_cmd *cmd = NULL;
1383 stream_callback_event_t event;
1384 bool send_callback = false;
1385
1386 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1387 __func__, list_empty(&out->offload_cmd_list),
1388 out->offload_state);
1389 if (list_empty(&out->offload_cmd_list)) {
1390 ALOGV("%s SLEEPING", __func__);
1391 pthread_cond_wait(&out->offload_cond, &out->lock);
1392 ALOGV("%s RUNNING", __func__);
1393 continue;
1394 }
1395
1396 item = list_head(&out->offload_cmd_list);
1397 cmd = node_to_item(item, struct offload_cmd, node);
1398 list_remove(item);
1399
1400 ALOGVV("%s STATE %d CMD %d out->compr %p",
1401 __func__, out->offload_state, cmd->cmd, out->compr);
1402
1403 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1404 free(cmd);
1405 break;
1406 }
1407
1408 if (out->compr == NULL) {
1409 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001410 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001411 pthread_cond_signal(&out->cond);
1412 continue;
1413 }
1414 out->offload_thread_blocked = true;
1415 pthread_mutex_unlock(&out->lock);
1416 send_callback = false;
1417 switch(cmd->cmd) {
1418 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1419 compress_wait(out->compr, -1);
1420 send_callback = true;
1421 event = STREAM_CBK_EVENT_WRITE_READY;
1422 break;
1423 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001424 compress_next_track(out->compr);
1425 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001426 send_callback = true;
1427 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001428 /* Resend the metadata for next iteration */
1429 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001430 break;
1431 case OFFLOAD_CMD_DRAIN:
1432 compress_drain(out->compr);
1433 send_callback = true;
1434 event = STREAM_CBK_EVENT_DRAIN_READY;
1435 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001436 case OFFLOAD_CMD_ERROR:
1437 send_callback = true;
1438 event = STREAM_CBK_EVENT_ERROR;
1439 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001440 default:
1441 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1442 break;
1443 }
Eric Laurenta1478072015-09-21 17:21:52 -07001444 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001445 out->offload_thread_blocked = false;
1446 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001447 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001448 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001449 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001450 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001451 free(cmd);
1452 }
1453
1454 pthread_cond_signal(&out->cond);
1455 while (!list_empty(&out->offload_cmd_list)) {
1456 item = list_head(&out->offload_cmd_list);
1457 list_remove(item);
1458 free(node_to_item(item, struct offload_cmd, node));
1459 }
1460 pthread_mutex_unlock(&out->lock);
1461
1462 return NULL;
1463}
1464
1465static int create_offload_callback_thread(struct stream_out *out)
1466{
1467 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1468 list_init(&out->offload_cmd_list);
1469 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1470 offload_thread_loop, out);
1471 return 0;
1472}
1473
1474static int destroy_offload_callback_thread(struct stream_out *out)
1475{
Eric Laurenta1478072015-09-21 17:21:52 -07001476 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001477 stop_compressed_output_l(out);
1478 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1479
1480 pthread_mutex_unlock(&out->lock);
1481 pthread_join(out->offload_thread, (void **) NULL);
1482 pthread_cond_destroy(&out->offload_cond);
1483
1484 return 0;
1485}
1486
Eric Laurent07eeafd2013-10-06 12:52:49 -07001487static bool allow_hdmi_channel_config(struct audio_device *adev)
1488{
1489 struct listnode *node;
1490 struct audio_usecase *usecase;
1491 bool ret = true;
1492
1493 list_for_each(node, &adev->usecase_list) {
1494 usecase = node_to_item(node, struct audio_usecase, list);
1495 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1496 /*
1497 * If voice call is already existing, do not proceed further to avoid
1498 * disabling/enabling both RX and TX devices, CSD calls, etc.
1499 * Once the voice call done, the HDMI channels can be configured to
1500 * max channels of remaining use cases.
1501 */
1502 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001503 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001504 __func__);
1505 ret = false;
1506 break;
1507 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
Joe Onorato188b6222016-03-01 11:02:27 -08001508 ALOGV("%s: multi channel playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001509 "no change in HDMI channels", __func__);
1510 ret = false;
1511 break;
1512 }
1513 }
1514 }
1515 return ret;
1516}
1517
1518static int check_and_set_hdmi_channels(struct audio_device *adev,
1519 unsigned int channels)
1520{
1521 struct listnode *node;
1522 struct audio_usecase *usecase;
1523
1524 /* Check if change in HDMI channel config is allowed */
1525 if (!allow_hdmi_channel_config(adev))
1526 return 0;
1527
1528 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001529 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001530 return 0;
1531 }
1532
1533 platform_set_hdmi_channels(adev->platform, channels);
1534 adev->cur_hdmi_channels = channels;
1535
1536 /*
1537 * Deroute all the playback streams routed to HDMI so that
1538 * the back end is deactivated. Note that backend will not
1539 * be deactivated if any one stream is connected to it.
1540 */
1541 list_for_each(node, &adev->usecase_list) {
1542 usecase = node_to_item(node, struct audio_usecase, list);
1543 if (usecase->type == PCM_PLAYBACK &&
1544 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001545 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001546 }
1547 }
1548
1549 /*
1550 * Enable all the streams disabled above. Now the HDMI backend
1551 * will be activated with new channel configuration
1552 */
1553 list_for_each(node, &adev->usecase_list) {
1554 usecase = node_to_item(node, struct audio_usecase, list);
1555 if (usecase->type == PCM_PLAYBACK &&
1556 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001557 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001558 }
1559 }
1560
1561 return 0;
1562}
1563
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001564static int stop_output_stream(struct stream_out *out)
1565{
1566 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001567 struct audio_usecase *uc_info;
1568 struct audio_device *adev = out->dev;
1569
Eric Laurent994a6932013-07-17 11:51:42 -07001570 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001571 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001572 uc_info = get_usecase_from_list(adev, out->usecase);
1573 if (uc_info == NULL) {
1574 ALOGE("%s: Could not find the usecase (%d) in the list",
1575 __func__, out->usecase);
1576 return -EINVAL;
1577 }
1578
Haynes Mathew George41f86652014-06-17 14:22:15 -07001579 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1580 if (adev->visualizer_stop_output != NULL)
1581 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1582 if (adev->offload_effects_stop_output != NULL)
1583 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1584 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001585
Eric Laurent150dbfe2013-02-27 14:31:02 -08001586 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001587 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001588
1589 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001590 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001591
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001592 list_remove(&uc_info->list);
1593 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001594
Eric Laurent0499d4f2014-08-25 22:39:29 -05001595 audio_extn_extspk_update(adev->extspk);
1596
Eric Laurent07eeafd2013-10-06 12:52:49 -07001597 /* Must be called after removing the usecase from list */
1598 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1599 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1600
Eric Laurent994a6932013-07-17 11:51:42 -07001601 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001602 return ret;
1603}
1604
1605int start_output_stream(struct stream_out *out)
1606{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001607 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001608 struct audio_usecase *uc_info;
1609 struct audio_device *adev = out->dev;
1610
Eric Laurent994a6932013-07-17 11:51:42 -07001611 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001612 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001613
1614 if (out->card_status == CARD_STATUS_OFFLINE ||
1615 adev->card_status == CARD_STATUS_OFFLINE) {
1616 ALOGW("out->card_status or adev->card_status offline, try again");
1617 ret = -EAGAIN;
1618 goto error_config;
1619 }
1620
Eric Laurentb23d5282013-05-14 15:27:20 -07001621 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001622 if (out->pcm_device_id < 0) {
1623 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1624 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001625 ret = -EINVAL;
1626 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001627 }
1628
1629 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1630 uc_info->id = out->usecase;
1631 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001632 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001633 uc_info->devices = out->devices;
1634 uc_info->in_snd_device = SND_DEVICE_NONE;
1635 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001636
Eric Laurent07eeafd2013-10-06 12:52:49 -07001637 /* This must be called before adding this usecase to the list */
1638 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1639 check_and_set_hdmi_channels(adev, out->config.channels);
1640
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001641 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001642
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001643 audio_extn_perf_lock_acquire();
1644
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001645 select_devices(adev, out->usecase);
1646
Eric Laurent0499d4f2014-08-25 22:39:29 -05001647 audio_extn_extspk_update(adev->extspk);
1648
Andy Hung31aca912014-03-20 17:14:59 -07001649 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001650 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001651 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1652 out->pcm = NULL;
1653 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1654 COMPRESS_IN, &out->compr_config);
1655 if (out->compr && !is_compress_ready(out->compr)) {
1656 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1657 compress_close(out->compr);
1658 out->compr = NULL;
1659 ret = -EIO;
1660 goto error_open;
1661 }
1662 if (out->offload_callback)
1663 compress_nonblock(out->compr, out->non_blocking);
1664
1665 if (adev->visualizer_start_output != NULL)
1666 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1667 if (adev->offload_effects_start_output != NULL)
1668 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
1669 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001670 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001671 ALOGE("%s: pcm stream not ready", __func__);
1672 goto error_open;
1673 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001674 ret = pcm_start(out->pcm);
1675 if (ret < 0) {
1676 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1677 goto error_open;
1678 }
1679 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001680 unsigned int flags = PCM_OUT;
1681 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001682
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001683 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1684 flags |= PCM_MMAP | PCM_NOIRQ;
1685 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001686 } else if (out->realtime) {
1687 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001688 } else
1689 flags |= PCM_MONOTONIC;
1690
1691 while (1) {
1692 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1693 flags, &out->config);
1694 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1695 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1696 if (out->pcm != NULL) {
1697 pcm_close(out->pcm);
1698 out->pcm = NULL;
1699 }
1700 if (pcm_open_retry_count-- == 0) {
1701 ret = -EIO;
1702 goto error_open;
1703 }
1704 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1705 continue;
1706 }
1707 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001708 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001709 ALOGV("%s: pcm_prepare", __func__);
1710 if (pcm_is_ready(out->pcm)) {
1711 ret = pcm_prepare(out->pcm);
1712 if (ret < 0) {
1713 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1714 pcm_close(out->pcm);
1715 out->pcm = NULL;
1716 goto error_open;
1717 }
1718 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001719 if (out->realtime) {
1720 ret = pcm_start(out->pcm);
1721 if (ret < 0) {
1722 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1723 pcm_close(out->pcm);
1724 out->pcm = NULL;
1725 goto error_open;
1726 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001727 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001728 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001729 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001730 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001731 audio_extn_tfa_98xx_enable_speaker();
1732
Eric Laurent994a6932013-07-17 11:51:42 -07001733 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001734 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001735error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001736 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001737 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001738error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001739 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001740}
1741
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001742static int check_input_parameters(uint32_t sample_rate,
1743 audio_format_t format,
1744 int channel_count)
1745{
vivek mehta4ed66e62016-04-15 23:33:34 -07001746 if ((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT)) {
vivek mehtadae44712015-07-27 14:13:18 -07001747 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1748 return -EINVAL;
1749 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001750
vivek mehtadae44712015-07-27 14:13:18 -07001751 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > MAX_CHANNEL_COUNT)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001752 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
vivek mehtadae44712015-07-27 14:13:18 -07001753 channel_count, MIN_CHANNEL_COUNT, MAX_CHANNEL_COUNT);
1754 return -EINVAL;
1755 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001756
1757 switch (sample_rate) {
1758 case 8000:
1759 case 11025:
1760 case 12000:
1761 case 16000:
1762 case 22050:
1763 case 24000:
1764 case 32000:
1765 case 44100:
1766 case 48000:
1767 break;
1768 default:
vivek mehtadae44712015-07-27 14:13:18 -07001769 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001770 return -EINVAL;
1771 }
1772
1773 return 0;
1774}
1775
1776static size_t get_input_buffer_size(uint32_t sample_rate,
1777 audio_format_t format,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001778 int channel_count,
1779 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001780{
1781 size_t size = 0;
1782
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001783 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1784 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001785
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001786 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001787 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001788 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07001789
1790 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001791
Glenn Kasten4f993392014-05-14 07:30:48 -07001792 /* make sure the size is multiple of 32 bytes
1793 * At 48 kHz mono 16-bit PCM:
1794 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1795 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1796 */
1797 size += 0x1f;
1798 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001799
1800 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001801}
1802
1803static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1804{
1805 struct stream_out *out = (struct stream_out *)stream;
1806
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001807 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001808}
1809
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001810static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001811{
1812 return -ENOSYS;
1813}
1814
1815static size_t out_get_buffer_size(const struct audio_stream *stream)
1816{
1817 struct stream_out *out = (struct stream_out *)stream;
1818
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001819 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1820 return out->compr_config.fragment_size;
1821 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001822 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07001823 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001824}
1825
1826static uint32_t out_get_channels(const struct audio_stream *stream)
1827{
1828 struct stream_out *out = (struct stream_out *)stream;
1829
1830 return out->channel_mask;
1831}
1832
1833static audio_format_t out_get_format(const struct audio_stream *stream)
1834{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001835 struct stream_out *out = (struct stream_out *)stream;
1836
1837 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001838}
1839
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001840static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001841{
1842 return -ENOSYS;
1843}
1844
1845static int out_standby(struct audio_stream *stream)
1846{
1847 struct stream_out *out = (struct stream_out *)stream;
1848 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08001849 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001850
Eric Laurent994a6932013-07-17 11:51:42 -07001851 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001852 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001853
Eric Laurenta1478072015-09-21 17:21:52 -07001854 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001855 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001856 if (adev->adm_deregister_stream)
1857 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001858 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001859 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001860 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1861 if (out->pcm) {
1862 pcm_close(out->pcm);
1863 out->pcm = NULL;
1864 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001865 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001866 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08001867 out->playback_started = false;
1868 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001869 } else {
1870 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001871 out->gapless_mdata.encoder_delay = 0;
1872 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001873 if (out->compr != NULL) {
1874 compress_close(out->compr);
1875 out->compr = NULL;
1876 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001877 }
Phil Burkbc991042017-02-24 08:06:44 -08001878 if (do_stop) {
1879 stop_output_stream(out);
1880 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001881 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001882 }
1883 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001884 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001885 return 0;
1886}
1887
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001888static int out_on_error(struct audio_stream *stream)
1889{
1890 struct stream_out *out = (struct stream_out *)stream;
1891 struct audio_device *adev = out->dev;
1892 bool do_standby = false;
1893
1894 lock_output_stream(out);
1895 if (!out->standby) {
1896 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1897 stop_compressed_output_l(out);
1898 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
1899 } else
1900 do_standby = true;
1901 }
1902 pthread_mutex_unlock(&out->lock);
1903
1904 if (do_standby)
1905 return out_standby(&out->stream.common);
1906
1907 return 0;
1908}
1909
Andy Hung7401c7c2016-09-21 12:41:21 -07001910static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001911{
Andy Hung7401c7c2016-09-21 12:41:21 -07001912 struct stream_out *out = (struct stream_out *)stream;
1913
1914 // We try to get the lock for consistency,
1915 // but it isn't necessary for these variables.
1916 // If we're not in standby, we may be blocked on a write.
1917 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
1918 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
1919 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
1920
1921 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07001922 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07001923 }
Andy Hunga452b0a2017-03-15 14:51:15 -07001924
1925 // dump error info
1926 (void)error_log_dump(
1927 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hungfc044e12017-03-20 09:24:22 -07001928 // dump power info (out->power_log may be null)
Andy Hung62c9b882017-03-22 16:43:42 -07001929 (void)power_log_dump(
1930 out->power_log, fd, " " /* prefix */, POWER_LOG_LINES, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001931 return 0;
1932}
1933
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001934static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1935{
1936 int ret = 0;
1937 char value[32];
1938 struct compr_gapless_mdata tmp_mdata;
1939
1940 if (!out || !parms) {
1941 return -EINVAL;
1942 }
1943
1944 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1945 if (ret >= 0) {
1946 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
1947 } else {
1948 return -EINVAL;
1949 }
1950
1951 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1952 if (ret >= 0) {
1953 tmp_mdata.encoder_padding = atoi(value);
1954 } else {
1955 return -EINVAL;
1956 }
1957
1958 out->gapless_mdata = tmp_mdata;
1959 out->send_new_metadata = 1;
1960 ALOGV("%s new encoder delay %u and padding %u", __func__,
1961 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1962
1963 return 0;
1964}
1965
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001966static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1967{
1968 return out == adev->primary_output || out == adev->voice_tx_output;
1969}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001970
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001971static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1972{
1973 struct stream_out *out = (struct stream_out *)stream;
1974 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001975 struct audio_usecase *usecase;
1976 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001977 struct str_parms *parms;
1978 char value[32];
1979 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001980 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07001981 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001982
Eric Laurent2e140aa2016-06-30 17:14:46 -07001983 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001984 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001985 parms = str_parms_create_str(kvpairs);
1986 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1987 if (ret >= 0) {
1988 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07001989 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001990 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001991
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001992 /*
1993 * When HDMI cable is unplugged the music playback is paused and
1994 * the policy manager sends routing=0. But the audioflinger
1995 * continues to write data until standby time (3sec).
1996 * As the HDMI core is turned off, the write gets blocked.
1997 * Avoid this by routing audio to speaker until standby.
1998 */
1999 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2000 val == AUDIO_DEVICE_NONE) {
2001 val = AUDIO_DEVICE_OUT_SPEAKER;
2002 }
2003
2004 /*
2005 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002006 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002007 * the select_devices(). But how do we undo this?
2008 *
2009 * For example, music playback is active on headset (deep-buffer usecase)
2010 * and if we go to ringtones and select a ringtone, low-latency usecase
2011 * will be started on headset+speaker. As we can't enable headset+speaker
2012 * and headset devices at the same time, select_devices() switches the music
2013 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2014 * So when the ringtone playback is completed, how do we undo the same?
2015 *
2016 * We are relying on the out_set_parameters() call on deep-buffer output,
2017 * once the ringtone playback is ended.
2018 * NOTE: We should not check if the current devices are same as new devices.
2019 * Because select_devices() must be called to switch back the music
2020 * playback to headset.
2021 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002022 audio_devices_t new_dev = val;
2023 if (new_dev != AUDIO_DEVICE_NONE) {
2024 bool same_dev = out->devices == new_dev;
2025 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002026
Eric Laurenta7657192014-10-09 21:09:33 -07002027 if (output_drives_call(adev, out)) {
2028 if (!voice_is_in_call(adev)) {
2029 if (adev->mode == AUDIO_MODE_IN_CALL) {
2030 adev->current_call_output = out;
2031 ret = voice_start_call(adev);
2032 }
2033 } else {
2034 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002035 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002036 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002037 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002038
2039 if (!out->standby) {
2040 if (!same_dev) {
2041 ALOGV("update routing change");
2042 out->routing_change = true;
2043 }
2044 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002045 audio_extn_tfa_98xx_update();
vivek mehta0d3637a2016-07-24 09:32:02 -07002046 }
2047
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002048 }
2049
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002050 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002051 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002052
2053 /*handles device and call state changes*/
2054 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002055 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002056
2057 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2058 parse_compress_metadata(out, parms);
2059 }
2060
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002061 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002062 ALOGV("%s: exit: code(%d)", __func__, status);
2063 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002064}
2065
2066static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2067{
2068 struct stream_out *out = (struct stream_out *)stream;
2069 struct str_parms *query = str_parms_create_str(keys);
2070 char *str;
2071 char value[256];
2072 struct str_parms *reply = str_parms_create();
2073 size_t i, j;
2074 int ret;
2075 bool first = true;
Eric Laurent994a6932013-07-17 11:51:42 -07002076 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002077 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2078 if (ret >= 0) {
2079 value[0] = '\0';
2080 i = 0;
2081 while (out->supported_channel_masks[i] != 0) {
2082 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2083 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2084 if (!first) {
2085 strcat(value, "|");
2086 }
2087 strcat(value, out_channels_name_to_enum_table[j].name);
2088 first = false;
2089 break;
2090 }
2091 }
2092 i++;
2093 }
2094 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2095 str = str_parms_to_str(reply);
2096 } else {
2097 str = strdup(keys);
2098 }
2099 str_parms_destroy(query);
2100 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002101 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002102 return str;
2103}
2104
2105static uint32_t out_get_latency(const struct audio_stream_out *stream)
2106{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002107 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002108 struct stream_out *out = (struct stream_out *)stream;
2109
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002110 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2111 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002112 else if ((out->realtime) ||
2113 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002114 // since the buffer won't be filled up faster than realtime,
2115 // return a smaller number
2116 period_ms = (out->af_period_multiplier * out->config.period_size *
2117 1000) / (out->config.rate);
2118 hw_delay = platform_render_latency(out->usecase)/1000;
2119 return period_ms + hw_delay;
2120 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002121
2122 return (out->config.period_count * out->config.period_size * 1000) /
2123 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002124}
2125
2126static int out_set_volume(struct audio_stream_out *stream, float left,
2127 float right)
2128{
Eric Laurenta9024de2013-04-04 09:19:12 -07002129 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002130 int volume[2];
2131
Eric Laurenta9024de2013-04-04 09:19:12 -07002132 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2133 /* only take left channel into account: the API is for stereo anyway */
2134 out->muted = (left == 0.0f);
2135 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002136 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2137 const char *mixer_ctl_name = "Compress Playback Volume";
2138 struct audio_device *adev = out->dev;
2139 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002140 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2141 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002142 /* try with the control based on device id */
2143 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2144 PCM_PLAYBACK);
2145 char ctl_name[128] = {0};
2146 snprintf(ctl_name, sizeof(ctl_name),
2147 "Compress Playback %d Volume", pcm_device_id);
2148 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2149 if (!ctl) {
2150 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2151 return -EINVAL;
2152 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002153 }
2154 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2155 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2156 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2157 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002158 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002159
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002160 return -ENOSYS;
2161}
2162
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002163// note: this call is safe only if the stream_cb is
2164// removed first in close_output_stream (as is done now).
2165static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2166{
2167 if (!stream || !parms)
2168 return;
2169
2170 struct stream_out *out = (struct stream_out *)stream;
2171 struct audio_device *adev = out->dev;
2172
2173 card_status_t status;
2174 int card;
2175 if (parse_snd_card_status(parms, &card, &status) < 0)
2176 return;
2177
2178 pthread_mutex_lock(&adev->lock);
2179 bool valid_cb = (card == adev->snd_card);
2180 pthread_mutex_unlock(&adev->lock);
2181
2182 if (!valid_cb)
2183 return;
2184
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002185 lock_output_stream(out);
2186 if (out->card_status != status)
2187 out->card_status = status;
2188 pthread_mutex_unlock(&out->lock);
2189
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002190 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2191 use_case_table[out->usecase],
2192 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2193
2194 if (status == CARD_STATUS_OFFLINE)
2195 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002196
2197 return;
2198}
2199
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002200#ifdef NO_AUDIO_OUT
2201static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002202 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002203{
2204 struct stream_out *out = (struct stream_out *)stream;
2205
2206 /* No Output device supported other than BT for playback.
2207 * Sleep for the amount of buffer duration
2208 */
Eric Laurenta1478072015-09-21 17:21:52 -07002209 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002210 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2211 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002212 out_get_sample_rate(&out->stream.common));
2213 pthread_mutex_unlock(&out->lock);
2214 return bytes;
2215}
2216#endif
2217
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002218static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2219 size_t bytes)
2220{
2221 struct stream_out *out = (struct stream_out *)stream;
2222 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002223 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002224 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002225
Eric Laurenta1478072015-09-21 17:21:52 -07002226 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002227 // this is always nonzero
2228 const int frame_size = audio_stream_out_frame_size(stream);
2229
Eric Laurent0e46adf2016-12-16 12:49:24 -08002230 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2231 error_code = ERROR_CODE_WRITE;
2232 goto exit;
2233 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002234 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002235 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002236 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002237 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002238 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002239 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002240 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002241 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002242 goto exit;
2243 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002244
2245 if (last_known_cal_step != -1) {
2246 ALOGD("%s: retry previous failed cal level set", __func__);
2247 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2248 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002249 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002250
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002251 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002252 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002253 if (out->send_new_metadata) {
2254 ALOGVV("send new gapless metadata");
2255 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2256 out->send_new_metadata = 0;
2257 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002258 unsigned int avail;
2259 struct timespec tstamp;
2260 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2261 /* Do not limit write size if the available frames count is unknown */
2262 if (ret != 0) {
2263 avail = bytes;
2264 }
2265 if (avail == 0) {
2266 ret = 0;
2267 } else {
2268 if (avail > bytes) {
2269 avail = bytes;
2270 }
2271 ret = compress_write(out->compr, buffer, avail);
2272 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2273 __func__, avail, ret);
2274 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002275
Eric Laurent6e895242013-09-05 16:10:57 -07002276 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002277 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2278 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002279 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002280 compress_start(out->compr);
2281 out->playback_started = 1;
2282 out->offload_state = OFFLOAD_STATE_PLAYING;
2283 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002284 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002285 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002286 } else {
2287 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002288 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002289 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002290 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002291 return ret;
2292 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002293 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002294 if (out->pcm) {
2295 if (out->muted)
2296 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002297
Eric Laurent0e46adf2016-12-16 12:49:24 -08002298 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002299
Haynes Mathew George03c40102016-01-29 17:57:48 -08002300 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2301 out->config.rate;
2302 request_out_focus(out, ns);
2303
2304 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2305 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002306 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002307 else
2308 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002309
Haynes Mathew George03c40102016-01-29 17:57:48 -08002310 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002311 } else {
2312 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002313 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002314 }
2315
2316exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002317 // For PCM we always consume the buffer and return #bytes regardless of ret.
2318 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2319 out->written += bytes / (out->config.channels * sizeof(short));
2320 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002321 long long sleeptime_us = 0;
Andy Hungfc044e12017-03-20 09:24:22 -07002322 const int64_t now_ns = audio_utils_get_real_time_ns();
2323
Andy Hung7401c7c2016-09-21 12:41:21 -07002324 if (ret != 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002325 error_log_log(out->error_log, error_code, now_ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002326 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2327 ALOGE_IF(out->pcm != NULL,
2328 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hungfc044e12017-03-20 09:24:22 -07002329 sleeptime_us = bytes * 1000000LL / frame_size /
Andy Hung7401c7c2016-09-21 12:41:21 -07002330 out_get_sample_rate(&out->stream.common);
2331 // usleep not guaranteed for values over 1 second but we don't limit here.
2332 }
2333 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002334
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002335 pthread_mutex_unlock(&out->lock);
2336
2337 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002338 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002339 if (sleeptime_us != 0)
2340 usleep(sleeptime_us);
Andy Hungfc044e12017-03-20 09:24:22 -07002341 } else {
2342 // only log if the data is properly written (out->power_log may be null)
2343 power_log_log(out->power_log, buffer, bytes / frame_size, now_ns);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002344 }
2345 return bytes;
2346}
2347
2348static int out_get_render_position(const struct audio_stream_out *stream,
2349 uint32_t *dsp_frames)
2350{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002351 struct stream_out *out = (struct stream_out *)stream;
2352 *dsp_frames = 0;
2353 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002354 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002355 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002356 unsigned long frames = 0;
2357 // TODO: check return value
2358 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2359 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002360 ALOGVV("%s rendered frames %d sample_rate %d",
2361 __func__, *dsp_frames, out->sample_rate);
2362 }
2363 pthread_mutex_unlock(&out->lock);
2364 return 0;
2365 } else
2366 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002367}
2368
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002369static int out_add_audio_effect(const struct audio_stream *stream __unused,
2370 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002371{
2372 return 0;
2373}
2374
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002375static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2376 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002377{
2378 return 0;
2379}
2380
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002381static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2382 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002383{
2384 return -EINVAL;
2385}
2386
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002387static int out_get_presentation_position(const struct audio_stream_out *stream,
2388 uint64_t *frames, struct timespec *timestamp)
2389{
2390 struct stream_out *out = (struct stream_out *)stream;
Andy Hung7171da22016-03-08 16:58:42 -08002391 int ret = -EINVAL;
Eric Laurent949a0892013-09-20 09:20:13 -07002392 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002393
Eric Laurenta1478072015-09-21 17:21:52 -07002394 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002395
Eric Laurent949a0892013-09-20 09:20:13 -07002396 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2397 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002398 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002399 compress_get_tstamp(out->compr, &dsp_frames,
2400 &out->sample_rate);
2401 ALOGVV("%s rendered frames %ld sample_rate %d",
2402 __func__, dsp_frames, out->sample_rate);
2403 *frames = dsp_frames;
2404 ret = 0;
2405 /* this is the best we can do */
2406 clock_gettime(CLOCK_MONOTONIC, timestamp);
2407 }
2408 } else {
2409 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002410 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002411 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2412 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002413 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002414 // This adjustment accounts for buffering after app processor.
2415 // It is based on estimated DSP latency per use case, rather than exact.
2416 signed_frames -=
2417 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2418
Eric Laurent949a0892013-09-20 09:20:13 -07002419 // It would be unusual for this value to be negative, but check just in case ...
2420 if (signed_frames >= 0) {
2421 *frames = signed_frames;
2422 ret = 0;
2423 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002424 }
2425 }
2426 }
2427
2428 pthread_mutex_unlock(&out->lock);
2429
2430 return ret;
2431}
2432
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002433static int out_set_callback(struct audio_stream_out *stream,
2434 stream_callback_t callback, void *cookie)
2435{
2436 struct stream_out *out = (struct stream_out *)stream;
2437
2438 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002439 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002440 out->offload_callback = callback;
2441 out->offload_cookie = cookie;
2442 pthread_mutex_unlock(&out->lock);
2443 return 0;
2444}
2445
2446static int out_pause(struct audio_stream_out* stream)
2447{
2448 struct stream_out *out = (struct stream_out *)stream;
2449 int status = -ENOSYS;
2450 ALOGV("%s", __func__);
2451 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002452 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002453 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2454 status = compress_pause(out->compr);
2455 out->offload_state = OFFLOAD_STATE_PAUSED;
2456 }
2457 pthread_mutex_unlock(&out->lock);
2458 }
2459 return status;
2460}
2461
2462static int out_resume(struct audio_stream_out* stream)
2463{
2464 struct stream_out *out = (struct stream_out *)stream;
2465 int status = -ENOSYS;
2466 ALOGV("%s", __func__);
2467 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2468 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002469 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002470 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2471 status = compress_resume(out->compr);
2472 out->offload_state = OFFLOAD_STATE_PLAYING;
2473 }
2474 pthread_mutex_unlock(&out->lock);
2475 }
2476 return status;
2477}
2478
2479static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2480{
2481 struct stream_out *out = (struct stream_out *)stream;
2482 int status = -ENOSYS;
2483 ALOGV("%s", __func__);
2484 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002485 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002486 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2487 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2488 else
2489 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2490 pthread_mutex_unlock(&out->lock);
2491 }
2492 return status;
2493}
2494
2495static int out_flush(struct audio_stream_out* stream)
2496{
2497 struct stream_out *out = (struct stream_out *)stream;
2498 ALOGV("%s", __func__);
2499 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002500 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002501 stop_compressed_output_l(out);
2502 pthread_mutex_unlock(&out->lock);
2503 return 0;
2504 }
2505 return -ENOSYS;
2506}
2507
Eric Laurent0e46adf2016-12-16 12:49:24 -08002508static int out_stop(const struct audio_stream_out* stream)
2509{
2510 struct stream_out *out = (struct stream_out *)stream;
2511 struct audio_device *adev = out->dev;
2512 int ret = -ENOSYS;
2513
2514 ALOGV("%s", __func__);
2515 pthread_mutex_lock(&adev->lock);
2516 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2517 out->playback_started && out->pcm != NULL) {
2518 pcm_stop(out->pcm);
2519 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08002520 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002521 }
2522 pthread_mutex_unlock(&adev->lock);
2523 return ret;
2524}
2525
2526static int out_start(const struct audio_stream_out* stream)
2527{
2528 struct stream_out *out = (struct stream_out *)stream;
2529 struct audio_device *adev = out->dev;
2530 int ret = -ENOSYS;
2531
2532 ALOGV("%s", __func__);
2533 pthread_mutex_lock(&adev->lock);
2534 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2535 !out->playback_started && out->pcm != NULL) {
2536 ret = start_output_stream(out);
2537 if (ret == 0) {
2538 out->playback_started = true;
2539 }
2540 }
2541 pthread_mutex_unlock(&adev->lock);
2542 return ret;
2543}
2544
Phil Burkbc991042017-02-24 08:06:44 -08002545/*
2546 * Modify config->period_count based on min_size_frames
2547 */
2548static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
2549{
2550 int periodCountRequested = (min_size_frames + config->period_size - 1)
2551 / config->period_size;
2552 int periodCount = MMAP_PERIOD_COUNT_MIN;
2553
2554 ALOGV("%s original config.period_size = %d config.period_count = %d",
2555 __func__, config->period_size, config->period_count);
2556
2557 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
2558 periodCount *= 2;
2559 }
2560 config->period_count = periodCount;
2561
2562 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
2563}
2564
Eric Laurent0e46adf2016-12-16 12:49:24 -08002565static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2566 int32_t min_size_frames,
2567 struct audio_mmap_buffer_info *info)
2568{
2569 struct stream_out *out = (struct stream_out *)stream;
2570 struct audio_device *adev = out->dev;
2571 int ret = 0;
2572 unsigned int offset1;
2573 unsigned int frames1;
2574 const char *step = "";
2575
2576 ALOGV("%s", __func__);
2577 pthread_mutex_lock(&adev->lock);
2578
2579 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002580 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002581 ret = -EINVAL;
2582 goto exit;
2583 }
2584 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08002585 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002586 ret = -ENOSYS;
2587 goto exit;
2588 }
2589 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
2590 if (out->pcm_device_id < 0) {
2591 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2592 __func__, out->pcm_device_id, out->usecase);
2593 ret = -EINVAL;
2594 goto exit;
2595 }
Phil Burkbc991042017-02-24 08:06:44 -08002596
2597 adjust_mmap_period_count(&out->config, min_size_frames);
2598
Eric Laurent0e46adf2016-12-16 12:49:24 -08002599 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2600 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
2601 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2602 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
2603 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2604 step = "open";
2605 ret = -ENODEV;
2606 goto exit;
2607 }
2608 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
2609 if (ret < 0) {
2610 step = "begin";
2611 goto exit;
2612 }
2613 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
2614 info->burst_size_frames = out->config.period_size;
2615 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
2616
2617 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
2618 info->buffer_size_frames));
2619
2620 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
2621 if (ret < 0) {
2622 step = "commit";
2623 goto exit;
2624 }
Phil Burkbc991042017-02-24 08:06:44 -08002625
2626 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002627 ret = 0;
2628
2629 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
2630 __func__, info->shared_memory_address, info->buffer_size_frames);
2631
2632exit:
2633 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002634 if (out->pcm == NULL) {
2635 ALOGE("%s: %s - %d", __func__, step, ret);
2636 } else {
2637 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08002638 pcm_close(out->pcm);
2639 out->pcm = NULL;
2640 }
2641 }
2642 pthread_mutex_unlock(&adev->lock);
2643 return ret;
2644}
2645
2646static int out_get_mmap_position(const struct audio_stream_out *stream,
2647 struct audio_mmap_position *position)
2648{
2649 struct stream_out *out = (struct stream_out *)stream;
2650 ALOGVV("%s", __func__);
2651 if (position == NULL) {
2652 return -EINVAL;
2653 }
2654 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
2655 return -ENOSYS;
2656 }
2657 if (out->pcm == NULL) {
2658 return -ENOSYS;
2659 }
2660
2661 struct timespec ts = { 0, 0 };
2662 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
2663 if (ret < 0) {
2664 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2665 return ret;
2666 }
Andy Hungfc044e12017-03-20 09:24:22 -07002667 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002668 return 0;
2669}
2670
2671
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002672/** audio_stream_in implementation **/
2673static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2674{
2675 struct stream_in *in = (struct stream_in *)stream;
2676
2677 return in->config.rate;
2678}
2679
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002680static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002681{
2682 return -ENOSYS;
2683}
2684
2685static size_t in_get_buffer_size(const struct audio_stream *stream)
2686{
2687 struct stream_in *in = (struct stream_in *)stream;
2688
Haynes Mathew George03c40102016-01-29 17:57:48 -08002689 return in->config.period_size * in->af_period_multiplier *
2690 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002691}
2692
2693static uint32_t in_get_channels(const struct audio_stream *stream)
2694{
2695 struct stream_in *in = (struct stream_in *)stream;
2696
2697 return in->channel_mask;
2698}
2699
vivek mehta4ed66e62016-04-15 23:33:34 -07002700static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002701{
vivek mehta4ed66e62016-04-15 23:33:34 -07002702 struct stream_in *in = (struct stream_in *)stream;
2703 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002704}
2705
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002706static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002707{
2708 return -ENOSYS;
2709}
2710
2711static int in_standby(struct audio_stream *stream)
2712{
2713 struct stream_in *in = (struct stream_in *)stream;
2714 struct audio_device *adev = in->dev;
2715 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08002716 bool do_stop = true;
2717
Eric Laurent994a6932013-07-17 11:51:42 -07002718 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002719
2720 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002721
2722 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08002723 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002724 audio_extn_sound_trigger_stop_lab(in);
2725 in->standby = true;
2726 }
2727
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002728 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002729 if (adev->adm_deregister_stream)
2730 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2731
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002732 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002733 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002734 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002735 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002736 in->capture_started = false;
2737 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002738 if (in->pcm) {
2739 pcm_close(in->pcm);
2740 in->pcm = NULL;
2741 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002742 adev->enable_voicerx = false;
2743 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08002744 if (do_stop) {
2745 status = stop_input_stream(in);
2746 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002747 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002748 }
2749 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002750 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002751 return status;
2752}
2753
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002754static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002755{
2756 return 0;
2757}
2758
2759static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2760{
2761 struct stream_in *in = (struct stream_in *)stream;
2762 struct audio_device *adev = in->dev;
2763 struct str_parms *parms;
2764 char *str;
2765 char value[32];
2766 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07002767 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002768
Eric Laurent994a6932013-07-17 11:51:42 -07002769 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002770 parms = str_parms_create_str(kvpairs);
2771
2772 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2773
Eric Laurenta1478072015-09-21 17:21:52 -07002774 lock_input_stream(in);
2775
Eric Laurent150dbfe2013-02-27 14:31:02 -08002776 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002777 if (ret >= 0) {
2778 val = atoi(value);
2779 /* no audio source uses val == 0 */
2780 if ((in->source != val) && (val != 0)) {
2781 in->source = val;
2782 }
2783 }
2784
2785 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07002786
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002787 if (ret >= 0) {
2788 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002789 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002790 in->device = val;
2791 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002792 if (!in->standby) {
2793 ALOGV("update input routing change");
2794 in->routing_change = true;
2795 select_devices(adev, in->usecase);
2796 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002797 }
2798 }
2799
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002800 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002801 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002802
2803 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002804 ALOGV("%s: exit: status(%d)", __func__, status);
2805 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002806}
2807
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002808static char* in_get_parameters(const struct audio_stream *stream __unused,
2809 const char *keys __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002810{
2811 return strdup("");
2812}
2813
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002814static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002815{
2816 return 0;
2817}
2818
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002819static void in_snd_mon_cb(void * stream, struct str_parms * parms)
2820{
2821 if (!stream || !parms)
2822 return;
2823
2824 struct stream_in *in = (struct stream_in *)stream;
2825 struct audio_device *adev = in->dev;
2826
2827 card_status_t status;
2828 int card;
2829 if (parse_snd_card_status(parms, &card, &status) < 0)
2830 return;
2831
2832 pthread_mutex_lock(&adev->lock);
2833 bool valid_cb = (card == adev->snd_card);
2834 pthread_mutex_unlock(&adev->lock);
2835
2836 if (!valid_cb)
2837 return;
2838
2839 lock_input_stream(in);
2840 if (in->card_status != status)
2841 in->card_status = status;
2842 pthread_mutex_unlock(&in->lock);
2843
2844 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
2845 use_case_table[in->usecase],
2846 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2847
2848 // a better solution would be to report error back to AF and let
2849 // it put the stream to standby
2850 if (status == CARD_STATUS_OFFLINE)
2851 in_standby(&in->stream.common);
2852
2853 return;
2854}
2855
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002856static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2857 size_t bytes)
2858{
2859 struct stream_in *in = (struct stream_in *)stream;
2860 struct audio_device *adev = in->dev;
2861 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07002862 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002863
Eric Laurenta1478072015-09-21 17:21:52 -07002864 lock_input_stream(in);
2865
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002866 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002867 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002868 /* Read from sound trigger HAL */
2869 audio_extn_sound_trigger_read(in, buffer, bytes);
2870 pthread_mutex_unlock(&in->lock);
2871 return bytes;
2872 }
2873
Eric Laurent0e46adf2016-12-16 12:49:24 -08002874 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
2875 ret = -ENOSYS;
2876 goto exit;
2877 }
2878
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002879 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002880 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002881 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002882 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002883 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002884 goto exit;
2885 }
2886 in->standby = 0;
2887 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002888
Haynes Mathew George03c40102016-01-29 17:57:48 -08002889 //what's the duration requested by the client?
2890 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
2891 in->config.rate;
2892 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002893
Haynes Mathew George03c40102016-01-29 17:57:48 -08002894 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002895 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002896 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002897 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07002898 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002899 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002900 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002901 if (ret < 0) {
2902 ALOGE("Failed to read w/err %s", strerror(errno));
2903 ret = -errno;
2904 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002905 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
2906 if (bytes % 4 == 0) {
2907 /* data from DSP comes in 24_8 format, convert it to 8_24 */
2908 int_buf_stream = buffer;
2909 for (size_t itt=0; itt < bytes/4 ; itt++) {
2910 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07002911 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002912 } else {
2913 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
2914 ret = -EINVAL;
2915 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07002916 }
2917 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002918 }
2919
Haynes Mathew George03c40102016-01-29 17:57:48 -08002920 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002921
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002922 /*
2923 * Instead of writing zeroes here, we could trust the hardware
2924 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002925 * 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 -08002926 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002927 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002928 memset(buffer, 0, bytes);
2929
2930exit:
2931 pthread_mutex_unlock(&in->lock);
2932
2933 if (ret != 0) {
2934 in_standby(&in->stream.common);
2935 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Eric Laurentfdf296a2014-07-03 16:41:51 -07002936 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002937 in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08002938 memset(buffer, 0, bytes); // clear return data
2939 }
2940 if (bytes > 0) {
Andy Hung6ebe5962016-01-15 17:46:57 -08002941 in->frames_read += bytes / audio_stream_in_frame_size(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002942 }
2943 return bytes;
2944}
2945
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002946static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002947{
2948 return 0;
2949}
2950
Andy Hung6ebe5962016-01-15 17:46:57 -08002951static int in_get_capture_position(const struct audio_stream_in *stream,
2952 int64_t *frames, int64_t *time)
2953{
2954 if (stream == NULL || frames == NULL || time == NULL) {
2955 return -EINVAL;
2956 }
2957 struct stream_in *in = (struct stream_in *)stream;
2958 int ret = -ENOSYS;
2959
2960 lock_input_stream(in);
2961 if (in->pcm) {
2962 struct timespec timestamp;
2963 unsigned int avail;
2964 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
2965 *frames = in->frames_read + avail;
2966 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
2967 ret = 0;
2968 }
2969 }
2970 pthread_mutex_unlock(&in->lock);
2971 return ret;
2972}
2973
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002974static int add_remove_audio_effect(const struct audio_stream *stream,
2975 effect_handle_t effect,
2976 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002977{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002978 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002979 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002980 int status = 0;
2981 effect_descriptor_t desc;
2982
2983 status = (*effect)->get_descriptor(effect, &desc);
2984 if (status != 0)
2985 return status;
2986
Eric Laurenta1478072015-09-21 17:21:52 -07002987 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002988 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07002989 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07002990 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07002991 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002992 in->enable_aec != enable &&
2993 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2994 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002995 if (!enable)
2996 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07002997 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2998 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
2999 adev->enable_voicerx = enable;
3000 struct audio_usecase *usecase;
3001 struct listnode *node;
3002 list_for_each(node, &adev->usecase_list) {
3003 usecase = node_to_item(node, struct audio_usecase, list);
3004 if (usecase->type == PCM_PLAYBACK) {
3005 select_devices(adev, usecase->id);
3006 break;
3007 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003008 }
3009 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003010 if (!in->standby)
3011 select_devices(in->dev, in->usecase);
3012 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003013 if (in->enable_ns != enable &&
3014 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3015 in->enable_ns = enable;
3016 if (!in->standby)
3017 select_devices(in->dev, in->usecase);
3018 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003019 pthread_mutex_unlock(&in->dev->lock);
3020 pthread_mutex_unlock(&in->lock);
3021
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003022 return 0;
3023}
3024
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003025static int in_add_audio_effect(const struct audio_stream *stream,
3026 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003027{
Eric Laurent994a6932013-07-17 11:51:42 -07003028 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003029 return add_remove_audio_effect(stream, effect, true);
3030}
3031
3032static int in_remove_audio_effect(const struct audio_stream *stream,
3033 effect_handle_t effect)
3034{
Eric Laurent994a6932013-07-17 11:51:42 -07003035 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003036 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003037}
3038
Eric Laurent0e46adf2016-12-16 12:49:24 -08003039static int in_stop(const struct audio_stream_in* stream)
3040{
3041 struct stream_in *in = (struct stream_in *)stream;
3042 struct audio_device *adev = in->dev;
3043
3044 int ret = -ENOSYS;
3045 ALOGV("%s", __func__);
3046 pthread_mutex_lock(&adev->lock);
3047 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3048 in->capture_started && in->pcm != NULL) {
3049 pcm_stop(in->pcm);
3050 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003051 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003052 }
3053 pthread_mutex_unlock(&adev->lock);
3054 return ret;
3055}
3056
3057static int in_start(const struct audio_stream_in* stream)
3058{
3059 struct stream_in *in = (struct stream_in *)stream;
3060 struct audio_device *adev = in->dev;
3061 int ret = -ENOSYS;
3062
3063 ALOGV("%s in %p", __func__, in);
3064 pthread_mutex_lock(&adev->lock);
3065 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3066 !in->capture_started && in->pcm != NULL) {
3067 if (!in->capture_started) {
3068 ret = start_input_stream(in);
3069 if (ret == 0) {
3070 in->capture_started = true;
3071 }
3072 }
3073 }
3074 pthread_mutex_unlock(&adev->lock);
3075 return ret;
3076}
3077
3078static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3079 int32_t min_size_frames,
3080 struct audio_mmap_buffer_info *info)
3081{
3082 struct stream_in *in = (struct stream_in *)stream;
3083 struct audio_device *adev = in->dev;
3084 int ret = 0;
3085 unsigned int offset1;
3086 unsigned int frames1;
3087 const char *step = "";
3088
3089 pthread_mutex_lock(&adev->lock);
3090 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003091
Eric Laurent0e46adf2016-12-16 12:49:24 -08003092 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003093 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003094 ret = -EINVAL;
3095 goto exit;
3096 }
3097 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003098 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003099 ALOGV("%s in %p", __func__, in);
3100 ret = -ENOSYS;
3101 goto exit;
3102 }
3103 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3104 if (in->pcm_device_id < 0) {
3105 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3106 __func__, in->pcm_device_id, in->usecase);
3107 ret = -EINVAL;
3108 goto exit;
3109 }
Phil Burkbc991042017-02-24 08:06:44 -08003110
3111 adjust_mmap_period_count(&in->config, min_size_frames);
3112
Eric Laurent0e46adf2016-12-16 12:49:24 -08003113 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3114 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3115 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3116 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3117 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3118 step = "open";
3119 ret = -ENODEV;
3120 goto exit;
3121 }
3122
3123 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3124 if (ret < 0) {
3125 step = "begin";
3126 goto exit;
3127 }
3128 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
3129 info->burst_size_frames = in->config.period_size;
3130 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3131
3132 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(in->pcm,
3133 info->buffer_size_frames));
3134
3135 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3136 if (ret < 0) {
3137 step = "commit";
3138 goto exit;
3139 }
3140
Phil Burkbc991042017-02-24 08:06:44 -08003141 in->standby = false;
3142 ret = 0;
3143
Eric Laurent0e46adf2016-12-16 12:49:24 -08003144 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3145 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003146
3147exit:
3148 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003149 if (in->pcm == NULL) {
3150 ALOGE("%s: %s - %d", __func__, step, ret);
3151 } else {
3152 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003153 pcm_close(in->pcm);
3154 in->pcm = NULL;
3155 }
3156 }
3157 pthread_mutex_unlock(&adev->lock);
3158 return ret;
3159}
3160
3161static int in_get_mmap_position(const struct audio_stream_in *stream,
3162 struct audio_mmap_position *position)
3163{
3164 struct stream_in *in = (struct stream_in *)stream;
3165 ALOGVV("%s", __func__);
3166 if (position == NULL) {
3167 return -EINVAL;
3168 }
3169 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
3170 return -ENOSYS;
3171 }
3172 if (in->pcm == NULL) {
3173 return -ENOSYS;
3174 }
3175 struct timespec ts = { 0, 0 };
3176 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
3177 if (ret < 0) {
3178 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3179 return ret;
3180 }
Andy Hungfc044e12017-03-20 09:24:22 -07003181 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003182 return 0;
3183}
3184
3185
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003186static int adev_open_output_stream(struct audio_hw_device *dev,
3187 audio_io_handle_t handle,
3188 audio_devices_t devices,
3189 audio_output_flags_t flags,
3190 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003191 struct audio_stream_out **stream_out,
3192 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003193{
3194 struct audio_device *adev = (struct audio_device *)dev;
3195 struct stream_out *out;
3196 int i, ret;
3197
Eric Laurent994a6932013-07-17 11:51:42 -07003198 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003199 __func__, config->sample_rate, config->channel_mask, devices, flags);
3200 *stream_out = NULL;
3201 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3202
3203 if (devices == AUDIO_DEVICE_NONE)
3204 devices = AUDIO_DEVICE_OUT_SPEAKER;
3205
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003206 out->flags = flags;
3207 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003208 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003209 out->format = config->format;
3210 out->sample_rate = config->sample_rate;
3211 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3212 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003213 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003214
3215 /* Init use case and pcm_config */
3216 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
Eric Laurent7f245042013-09-30 19:22:50 -07003217 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003218 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003219 pthread_mutex_lock(&adev->lock);
3220 ret = read_hdmi_channel_masks(out);
3221 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003222 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003223 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003224
3225 if (config->sample_rate == 0)
3226 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3227 if (config->channel_mask == 0)
3228 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Eric Laurentad1cec22015-12-16 10:12:27 -08003229 if (config->format == AUDIO_FORMAT_DEFAULT)
3230 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003231
3232 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003233 out->sample_rate = config->sample_rate;
Eric Laurentad1cec22015-12-16 10:12:27 -08003234 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003235 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3236 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003237 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003238 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003239 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003240 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003241 pthread_mutex_lock(&adev->lock);
3242 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3243 pthread_mutex_unlock(&adev->lock);
3244
3245 // reject offload during card offline to allow
3246 // fallback to s/w paths
3247 if (offline) {
3248 ret = -ENODEV;
3249 goto error_open;
3250 }
3251
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003252 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3253 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3254 ALOGE("%s: Unsupported Offload information", __func__);
3255 ret = -EINVAL;
3256 goto error_open;
3257 }
3258 if (!is_supported_format(config->offload_info.format)) {
3259 ALOGE("%s: Unsupported audio format", __func__);
3260 ret = -EINVAL;
3261 goto error_open;
3262 }
3263
3264 out->compr_config.codec = (struct snd_codec *)
3265 calloc(1, sizeof(struct snd_codec));
3266
3267 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3268 if (config->offload_info.channel_mask)
3269 out->channel_mask = config->offload_info.channel_mask;
3270 else if (config->channel_mask)
3271 out->channel_mask = config->channel_mask;
3272 out->format = config->offload_info.format;
3273 out->sample_rate = config->offload_info.sample_rate;
3274
3275 out->stream.set_callback = out_set_callback;
3276 out->stream.pause = out_pause;
3277 out->stream.resume = out_resume;
3278 out->stream.drain = out_drain;
3279 out->stream.flush = out_flush;
3280
3281 out->compr_config.codec->id =
3282 get_snd_codec_id(config->offload_info.format);
3283 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3284 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07003285 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003286 out->compr_config.codec->bit_rate =
3287 config->offload_info.bit_rate;
3288 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003289 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003290 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3291
3292 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3293 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003294
3295 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003296 create_offload_callback_thread(out);
3297 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3298 __func__, config->offload_info.version,
3299 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003300 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3301 if (config->sample_rate == 0)
3302 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3303 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3304 config->sample_rate != 8000) {
3305 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3306 ret = -EINVAL;
3307 goto error_open;
3308 }
3309 out->sample_rate = config->sample_rate;
3310 out->config.rate = config->sample_rate;
3311 if (config->format == AUDIO_FORMAT_DEFAULT)
3312 config->format = AUDIO_FORMAT_PCM_16_BIT;
3313 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3314 config->format = AUDIO_FORMAT_PCM_16_BIT;
3315 ret = -EINVAL;
3316 goto error_open;
3317 }
3318 out->format = config->format;
3319 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3320 out->config = pcm_config_afe_proxy_playback;
3321 adev->voice_tx_output = out;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003322 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003323 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3324 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3325 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003326 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
3327 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3328 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003329 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3330 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003331 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003332 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003333 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3334 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3335 out->config = pcm_config_mmap_playback;
3336 out->stream.start = out_start;
3337 out->stream.stop = out_stop;
3338 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3339 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003340 } else {
3341 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3342 out->config = pcm_config_low_latency;
3343 }
3344 if (config->format != audio_format_from_pcm_format(out->config.format)) {
3345 if (k_enable_extended_precision
3346 && pcm_params_format_test(adev->use_case_table[out->usecase],
3347 pcm_format_from_audio_format(config->format))) {
3348 out->config.format = pcm_format_from_audio_format(config->format);
3349 /* out->format already set to config->format */
3350 } else {
3351 /* deny the externally proposed config format
3352 * and use the one specified in audio_hw layer configuration.
3353 * Note: out->format is returned by out->stream.common.get_format()
3354 * and is used to set config->format in the code several lines below.
3355 */
3356 out->format = audio_format_from_pcm_format(out->config.format);
3357 }
3358 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003359 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003360 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07003361 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3362 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003363
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003364 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003365 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003366 adev->primary_output = out;
3367 else {
3368 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003369 ret = -EEXIST;
3370 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003371 }
3372 }
3373
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003374 /* Check if this usecase is already existing */
3375 pthread_mutex_lock(&adev->lock);
3376 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3377 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003378 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003379 ret = -EEXIST;
3380 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003381 }
3382 pthread_mutex_unlock(&adev->lock);
3383
3384 out->stream.common.get_sample_rate = out_get_sample_rate;
3385 out->stream.common.set_sample_rate = out_set_sample_rate;
3386 out->stream.common.get_buffer_size = out_get_buffer_size;
3387 out->stream.common.get_channels = out_get_channels;
3388 out->stream.common.get_format = out_get_format;
3389 out->stream.common.set_format = out_set_format;
3390 out->stream.common.standby = out_standby;
3391 out->stream.common.dump = out_dump;
3392 out->stream.common.set_parameters = out_set_parameters;
3393 out->stream.common.get_parameters = out_get_parameters;
3394 out->stream.common.add_audio_effect = out_add_audio_effect;
3395 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3396 out->stream.get_latency = out_get_latency;
3397 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003398#ifdef NO_AUDIO_OUT
3399 out->stream.write = out_write_for_no_output;
3400#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003401 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003402#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003403 out->stream.get_render_position = out_get_render_position;
3404 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003405 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003406
Eric Laurent0e46adf2016-12-16 12:49:24 -08003407 if (out->realtime)
3408 out->af_period_multiplier = af_period_multiplier;
3409 else
3410 out->af_period_multiplier = 1;
3411
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003412 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003413 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003414 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003415
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003416 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003417 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003418 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3419
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003420 config->format = out->stream.common.get_format(&out->stream.common);
3421 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3422 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3423
Andy Hunga452b0a2017-03-15 14:51:15 -07003424 out->error_log = error_log_create(
3425 ERROR_LOG_ENTRIES,
3426 1000000000 /* aggregate consecutive identical errors within one second in ns */);
3427
Andy Hungfc044e12017-03-20 09:24:22 -07003428 const size_t POWER_LOG_FRAMES_PER_ENTRY =
3429 config->sample_rate * POWER_LOG_SAMPLING_INTERVAL_MS / 1000;
3430 // power_log may be null if the format is not supported
3431 out->power_log = power_log_create(
3432 config->sample_rate,
3433 audio_channel_count_from_out_mask(config->channel_mask),
3434 config->format,
3435 POWER_LOG_ENTRIES,
3436 POWER_LOG_FRAMES_PER_ENTRY);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003437
3438 /*
3439 By locking output stream before registering, we allow the callback
3440 to update stream's state only after stream's initial state is set to
3441 adev state.
3442 */
3443 lock_output_stream(out);
3444 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3445 pthread_mutex_lock(&adev->lock);
3446 out->card_status = adev->card_status;
3447 pthread_mutex_unlock(&adev->lock);
3448 pthread_mutex_unlock(&out->lock);
3449
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003450 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003451
Eric Laurent994a6932013-07-17 11:51:42 -07003452 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003453 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003454
3455error_open:
3456 free(out);
3457 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003458 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003459 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003460}
3461
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003462static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003463 struct audio_stream_out *stream)
3464{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003465 struct stream_out *out = (struct stream_out *)stream;
3466 struct audio_device *adev = out->dev;
3467
Eric Laurent994a6932013-07-17 11:51:42 -07003468 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003469
3470 // must deregister from sndmonitor first to prevent races
3471 // between the callback and close_stream
3472 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003473 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003474 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3475 destroy_offload_callback_thread(out);
3476
3477 if (out->compr_config.codec != NULL)
3478 free(out->compr_config.codec);
3479 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003480
3481 if (adev->voice_tx_output == out)
3482 adev->voice_tx_output = NULL;
3483
Andy Hungfc044e12017-03-20 09:24:22 -07003484 power_log_destroy(out->power_log);
3485 out->power_log = NULL;
3486
Andy Hunga452b0a2017-03-15 14:51:15 -07003487 error_log_destroy(out->error_log);
3488 out->error_log = NULL;
3489
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003490 pthread_cond_destroy(&out->cond);
3491 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003492 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003493 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003494}
3495
3496static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3497{
3498 struct audio_device *adev = (struct audio_device *)dev;
3499 struct str_parms *parms;
3500 char *str;
3501 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003502 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003503 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003504 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003505
Joe Onorato188b6222016-03-01 11:02:27 -08003506 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003507
3508 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003509
3510 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003511 status = voice_set_parameters(adev, parms);
3512 if (status != 0) {
3513 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003514 }
3515
3516 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3517 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003518 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003519 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3520 adev->bluetooth_nrec = true;
3521 else
3522 adev->bluetooth_nrec = false;
3523 }
3524
3525 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3526 if (ret >= 0) {
3527 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3528 adev->screen_off = false;
3529 else
3530 adev->screen_off = true;
3531 }
3532
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003533 ret = str_parms_get_int(parms, "rotation", &val);
3534 if (ret >= 0) {
3535 bool reverse_speakers = false;
3536 switch(val) {
3537 // FIXME: note that the code below assumes that the speakers are in the correct placement
3538 // relative to the user when the device is rotated 90deg from its default rotation. This
3539 // assumption is device-specific, not platform-specific like this code.
3540 case 270:
3541 reverse_speakers = true;
3542 break;
3543 case 0:
3544 case 90:
3545 case 180:
3546 break;
3547 default:
3548 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003549 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003550 }
Eric Laurent03f09432014-03-25 18:09:11 -07003551 if (status == 0) {
Ravi Kumar Alamanda1f60cf82015-04-23 19:45:17 -07003552 platform_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003553 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003554 }
3555
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003556 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3557 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003558 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003559 }
3560
David Linee3fe402017-03-13 10:00:42 -07003561 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3562 if (ret >= 0) {
3563 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
3564 if (device == AUDIO_DEVICE_OUT_USB_DEVICE) {
3565 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3566 if (ret >= 0) {
3567 const int card = atoi(value);
3568 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, card);
3569 }
3570 } else if (device == AUDIO_DEVICE_IN_USB_DEVICE) {
3571 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3572 if (ret >= 0) {
3573 const int card = atoi(value);
3574 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, card);
3575 }
3576 }
3577 }
3578
3579 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3580 if (ret >= 0) {
3581 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
3582 if (device == AUDIO_DEVICE_OUT_USB_DEVICE) {
3583 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3584 if (ret >= 0) {
3585 const int card = atoi(value);
3586
3587 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, card);
3588 }
3589 } else if (device == AUDIO_DEVICE_IN_USB_DEVICE) {
3590 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3591 if (ret >= 0) {
3592 const int card = atoi(value);
3593 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, card);
3594 }
3595 }
3596 }
3597
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08003598 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003599done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003600 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003601 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07003602 ALOGV("%s: exit with code(%d)", __func__, status);
3603 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003604}
3605
3606static char* adev_get_parameters(const struct audio_hw_device *dev,
3607 const char *keys)
3608{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003609 struct audio_device *adev = (struct audio_device *)dev;
3610 struct str_parms *reply = str_parms_create();
3611 struct str_parms *query = str_parms_create_str(keys);
3612 char *str;
3613
3614 pthread_mutex_lock(&adev->lock);
3615
3616 voice_get_parameters(adev, query, reply);
3617 str = str_parms_to_str(reply);
3618 str_parms_destroy(query);
3619 str_parms_destroy(reply);
3620
3621 pthread_mutex_unlock(&adev->lock);
3622 ALOGV("%s: exit: returns - %s", __func__, str);
3623 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003624}
3625
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003626static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003627{
3628 return 0;
3629}
3630
Haynes Mathew George5191a852013-09-11 14:19:36 -07003631static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3632{
3633 int ret;
3634 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003635
Eric Laurent4cc4ce12014-09-10 13:21:01 -05003636 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
3637
Haynes Mathew George5191a852013-09-11 14:19:36 -07003638 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003639 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003640 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003641
Haynes Mathew George5191a852013-09-11 14:19:36 -07003642 return ret;
3643}
3644
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003645static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003646{
3647 return -ENOSYS;
3648}
3649
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003650static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3651 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003652{
3653 return -ENOSYS;
3654}
3655
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003656static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003657{
3658 return -ENOSYS;
3659}
3660
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003661static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003662{
3663 return -ENOSYS;
3664}
3665
3666static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3667{
3668 struct audio_device *adev = (struct audio_device *)dev;
3669
3670 pthread_mutex_lock(&adev->lock);
3671 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07003672 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003673 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07003674 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3675 voice_is_in_call(adev)) {
3676 voice_stop_call(adev);
3677 adev->current_call_output = NULL;
3678 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003679 }
3680 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003681
3682 audio_extn_extspk_set_mode(adev->extspk, mode);
3683
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003684 return 0;
3685}
3686
3687static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3688{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003689 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003690 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003691
Eric Laurent2bafff12016-03-17 12:17:23 -07003692 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003693 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08003694 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
3695 ret = audio_extn_hfp_set_mic_mute(adev, state);
3696 } else {
3697 ret = voice_set_mic_mute(adev, state);
3698 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003699 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00003700 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003701
3702 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003703}
3704
3705static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3706{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003707 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003708 return 0;
3709}
3710
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003711static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003712 const struct audio_config *config)
3713{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003714 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003715
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003716 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3717 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003718}
3719
3720static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003721 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003722 audio_devices_t devices,
3723 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003724 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07003725 audio_input_flags_t flags,
3726 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05003727 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003728{
3729 struct audio_device *adev = (struct audio_device *)dev;
3730 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003731 int ret = 0, buffer_size, frame_size;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003732 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003733 bool is_low_latency = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003734
Eric Laurent994a6932013-07-17 11:51:42 -07003735 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003736 *stream_in = NULL;
3737 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3738 return -EINVAL;
3739
Zheng Zhang6185d572016-12-01 20:35:17 +08003740 if (audio_extn_tfa_98xx_is_supported() && (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08003741 return -EINVAL;
3742
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003743 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
3744
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003745 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003746 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003747
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003748 in->stream.common.get_sample_rate = in_get_sample_rate;
3749 in->stream.common.set_sample_rate = in_set_sample_rate;
3750 in->stream.common.get_buffer_size = in_get_buffer_size;
3751 in->stream.common.get_channels = in_get_channels;
3752 in->stream.common.get_format = in_get_format;
3753 in->stream.common.set_format = in_set_format;
3754 in->stream.common.standby = in_standby;
3755 in->stream.common.dump = in_dump;
3756 in->stream.common.set_parameters = in_set_parameters;
3757 in->stream.common.get_parameters = in_get_parameters;
3758 in->stream.common.add_audio_effect = in_add_audio_effect;
3759 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3760 in->stream.set_gain = in_set_gain;
3761 in->stream.read = in_read;
3762 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08003763 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003764
3765 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003766 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003767 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003768 in->standby = 1;
3769 in->channel_mask = config->channel_mask;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003770 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003771 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003772
vivek mehta57ff9b52016-04-28 14:13:08 -07003773 // restrict 24 bit capture for unprocessed source only
3774 // for other sources if 24 bit requested reject 24 and set 16 bit capture only
3775 if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07003776 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07003777 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
3778 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
3779 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
3780 bool ret_error = false;
3781 /* 24 bit is restricted to UNPROCESSED source only,also format supported
3782 from HAL is 8_24
3783 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
3784 8_24 return error indicating supported format is 8_24
3785 *> In case of any other source requesting 24 bit or float return error
3786 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07003787
vivek mehta57ff9b52016-04-28 14:13:08 -07003788 on error flinger will retry with supported format passed
3789 */
3790 if (source != AUDIO_SOURCE_UNPROCESSED) {
3791 config->format = AUDIO_FORMAT_PCM_16_BIT;
3792 ret_error = true;
3793 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
3794 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
3795 ret_error = true;
3796 }
3797
3798 if (ret_error) {
3799 ret = -EINVAL;
3800 goto err_open;
3801 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003802 }
3803
vivek mehta57ff9b52016-04-28 14:13:08 -07003804 in->format = config->format;
3805
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003806 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003807 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
3808 if (config->sample_rate == 0)
3809 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3810 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3811 config->sample_rate != 8000) {
3812 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3813 ret = -EINVAL;
3814 goto err_open;
3815 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003816
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003817 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3818 config->format = AUDIO_FORMAT_PCM_16_BIT;
3819 ret = -EINVAL;
3820 goto err_open;
3821 }
3822
3823 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3824 in->config = pcm_config_afe_proxy_record;
David Lin73f45252017-03-29 13:37:33 -07003825 in->af_period_multiplier = 1;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003826 } else {
3827 in->usecase = USECASE_AUDIO_RECORD;
3828 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08003829 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003830 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07003831#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003832 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07003833#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08003834 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003835 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08003836 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003837 frame_size = audio_stream_in_frame_size(&in->stream);
3838 buffer_size = get_input_buffer_size(config->sample_rate,
3839 config->format,
3840 channel_count,
3841 is_low_latency);
3842 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003843 in->config.rate = config->sample_rate;
3844 in->af_period_multiplier = 1;
3845 } else {
3846 // period size is left untouched for rt mode playback
3847 in->config = pcm_config_audio_capture_rt;
3848 in->af_period_multiplier = af_period_multiplier;
3849 }
3850 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
3851 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
3852 in->usecase = USECASE_AUDIO_RECORD_MMAP;
3853 in->config = pcm_config_mmap_capture;
3854 in->stream.start = in_start;
3855 in->stream.stop = in_stop;
3856 in->stream.create_mmap_buffer = in_create_mmap_buffer;
3857 in->stream.get_mmap_position = in_get_mmap_position;
3858 in->af_period_multiplier = 1;
3859 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
3860 } else {
3861 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003862 frame_size = audio_stream_in_frame_size(&in->stream);
3863 buffer_size = get_input_buffer_size(config->sample_rate,
3864 config->format,
3865 channel_count,
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003866 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003867 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003868 in->config.rate = config->sample_rate;
3869 in->af_period_multiplier = 1;
3870 }
3871 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
3872 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003873 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003874
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003875 in->config.channels = channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003876
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003877 /* This stream could be for sound trigger lab,
3878 get sound trigger pcm if present */
3879 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003880
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003881 lock_input_stream(in);
3882 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
3883 pthread_mutex_lock(&adev->lock);
3884 in->card_status = adev->card_status;
3885 pthread_mutex_unlock(&adev->lock);
3886 pthread_mutex_unlock(&in->lock);
3887
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003888 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003889 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003890 return 0;
3891
3892err_open:
3893 free(in);
3894 *stream_in = NULL;
3895 return ret;
3896}
3897
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003898static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003899 struct audio_stream_in *stream)
3900{
Eric Laurent994a6932013-07-17 11:51:42 -07003901 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003902
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003903 // must deregister from sndmonitor first to prevent races
3904 // between the callback and close_stream
3905 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003906 in_standby(&stream->common);
3907 free(stream);
3908
3909 return;
3910}
3911
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003912static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003913{
3914 return 0;
3915}
3916
Andy Hung31aca912014-03-20 17:14:59 -07003917/* verifies input and output devices and their capabilities.
3918 *
3919 * This verification is required when enabling extended bit-depth or
3920 * sampling rates, as not all qcom products support it.
3921 *
3922 * Suitable for calling only on initialization such as adev_open().
3923 * It fills the audio_device use_case_table[] array.
3924 *
3925 * Has a side-effect that it needs to configure audio routing / devices
3926 * in order to power up the devices and read the device parameters.
3927 * It does not acquire any hw device lock. Should restore the devices
3928 * back to "normal state" upon completion.
3929 */
3930static int adev_verify_devices(struct audio_device *adev)
3931{
3932 /* enumeration is a bit difficult because one really wants to pull
3933 * the use_case, device id, etc from the hidden pcm_device_table[].
3934 * In this case there are the following use cases and device ids.
3935 *
3936 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
3937 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
3938 * [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
3939 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
3940 * [USECASE_AUDIO_RECORD] = {0, 0},
3941 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
3942 * [USECASE_VOICE_CALL] = {2, 2},
3943 *
3944 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_MULTI_CH omitted.
3945 * USECASE_VOICE_CALL omitted, but possible for either input or output.
3946 */
3947
3948 /* should be the usecases enabled in adev_open_input_stream() */
3949 static const int test_in_usecases[] = {
3950 USECASE_AUDIO_RECORD,
3951 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
3952 };
3953 /* should be the usecases enabled in adev_open_output_stream()*/
3954 static const int test_out_usecases[] = {
3955 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
3956 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
3957 };
3958 static const usecase_type_t usecase_type_by_dir[] = {
3959 PCM_PLAYBACK,
3960 PCM_CAPTURE,
3961 };
3962 static const unsigned flags_by_dir[] = {
3963 PCM_OUT,
3964 PCM_IN,
3965 };
3966
3967 size_t i;
3968 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003969 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07003970 char info[512]; /* for possible debug info */
3971
3972 for (dir = 0; dir < 2; ++dir) {
3973 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
3974 const unsigned flags_dir = flags_by_dir[dir];
3975 const size_t testsize =
3976 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
3977 const int *testcases =
3978 dir ? test_in_usecases : test_out_usecases;
3979 const audio_devices_t audio_device =
3980 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
3981
3982 for (i = 0; i < testsize; ++i) {
3983 const audio_usecase_t audio_usecase = testcases[i];
3984 int device_id;
3985 snd_device_t snd_device;
3986 struct pcm_params **pparams;
3987 struct stream_out out;
3988 struct stream_in in;
3989 struct audio_usecase uc_info;
3990 int retval;
3991
3992 pparams = &adev->use_case_table[audio_usecase];
3993 pcm_params_free(*pparams); /* can accept null input */
3994 *pparams = NULL;
3995
3996 /* find the device ID for the use case (signed, for error) */
3997 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
3998 if (device_id < 0)
3999 continue;
4000
4001 /* prepare structures for device probing */
4002 memset(&uc_info, 0, sizeof(uc_info));
4003 uc_info.id = audio_usecase;
4004 uc_info.type = usecase_type;
4005 if (dir) {
4006 adev->active_input = &in;
4007 memset(&in, 0, sizeof(in));
4008 in.device = audio_device;
4009 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4010 uc_info.stream.in = &in;
4011 } else {
4012 adev->active_input = NULL;
4013 }
4014 memset(&out, 0, sizeof(out));
4015 out.devices = audio_device; /* only field needed in select_devices */
4016 uc_info.stream.out = &out;
4017 uc_info.devices = audio_device;
4018 uc_info.in_snd_device = SND_DEVICE_NONE;
4019 uc_info.out_snd_device = SND_DEVICE_NONE;
4020 list_add_tail(&adev->usecase_list, &uc_info.list);
4021
4022 /* select device - similar to start_(in/out)put_stream() */
4023 retval = select_devices(adev, audio_usecase);
4024 if (retval >= 0) {
4025 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4026#if LOG_NDEBUG == 0
4027 if (*pparams) {
4028 ALOGV("%s: (%s) card %d device %d", __func__,
4029 dir ? "input" : "output", card_id, device_id);
4030 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004031 } else {
4032 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4033 }
4034#endif
4035 }
4036
4037 /* deselect device - similar to stop_(in/out)put_stream() */
4038 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004039 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004040 /* 2. Disable the rx device */
4041 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004042 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004043 list_remove(&uc_info.list);
4044 }
4045 }
4046 adev->active_input = NULL; /* restore adev state */
4047 return 0;
4048}
4049
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004050static int adev_close(hw_device_t *device)
4051{
Andy Hung31aca912014-03-20 17:14:59 -07004052 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004053 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004054
4055 if (!adev)
4056 return 0;
4057
Kevin Rocarda5453442017-05-02 15:09:20 -07004058 audio_extn_snd_mon_unregister_listener(adev);
Kevin Rocard8342c2c2017-04-07 18:50:00 -07004059 audio_extn_snd_mon_deinit();
Kevin Rocarda5453442017-05-02 15:09:20 -07004060
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004061 audio_extn_tfa_98xx_deinit();
4062
vivek mehta1a9b7c02015-06-25 11:49:38 -07004063 pthread_mutex_lock(&adev_init_lock);
4064
4065 if ((--audio_device_ref_count) == 0) {
4066 audio_route_free(adev->audio_route);
4067 free(adev->snd_dev_ref_cnt);
4068 platform_deinit(adev->platform);
4069 audio_extn_extspk_deinit(adev->extspk);
4070 audio_extn_sound_trigger_deinit(adev);
4071 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4072 pcm_params_free(adev->use_case_table[i]);
4073 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004074 if (adev->adm_deinit)
4075 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004076 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004077 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004078
4079 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004080
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004081 return 0;
4082}
4083
Glenn Kasten4f993392014-05-14 07:30:48 -07004084/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4085 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4086 * just that it _might_ work.
4087 */
4088static int period_size_is_plausible_for_low_latency(int period_size)
4089{
4090 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004091 case 48:
4092 case 96:
4093 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004094 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004095 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004096 case 240:
4097 case 320:
4098 case 480:
4099 return 1;
4100 default:
4101 return 0;
4102 }
4103}
4104
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004105static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4106{
4107 int card;
4108 card_status_t status;
4109
4110 if (!parms)
4111 return;
4112
4113 if (parse_snd_card_status(parms, &card, &status) < 0)
4114 return;
4115
4116 pthread_mutex_lock(&adev->lock);
4117 bool valid_cb = (card == adev->snd_card);
4118 if (valid_cb) {
4119 if (adev->card_status != status) {
4120 adev->card_status = status;
4121 platform_snd_card_update(adev->platform, status);
4122 }
4123 }
4124 pthread_mutex_unlock(&adev->lock);
4125 return;
4126}
4127
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004128static int adev_open(const hw_module_t *module, const char *name,
4129 hw_device_t **device)
4130{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004131 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004132
Eric Laurent2bafff12016-03-17 12:17:23 -07004133 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004134 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004135 pthread_mutex_lock(&adev_init_lock);
4136 if (audio_device_ref_count != 0) {
4137 *device = &adev->device.common;
4138 audio_device_ref_count++;
4139 ALOGV("%s: returning existing instance of adev", __func__);
4140 ALOGV("%s: exit", __func__);
4141 pthread_mutex_unlock(&adev_init_lock);
4142 return 0;
4143 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004144 adev = calloc(1, sizeof(struct audio_device));
4145
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004146 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4147
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004148 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4149 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4150 adev->device.common.module = (struct hw_module_t *)module;
4151 adev->device.common.close = adev_close;
4152
4153 adev->device.init_check = adev_init_check;
4154 adev->device.set_voice_volume = adev_set_voice_volume;
4155 adev->device.set_master_volume = adev_set_master_volume;
4156 adev->device.get_master_volume = adev_get_master_volume;
4157 adev->device.set_master_mute = adev_set_master_mute;
4158 adev->device.get_master_mute = adev_get_master_mute;
4159 adev->device.set_mode = adev_set_mode;
4160 adev->device.set_mic_mute = adev_set_mic_mute;
4161 adev->device.get_mic_mute = adev_get_mic_mute;
4162 adev->device.set_parameters = adev_set_parameters;
4163 adev->device.get_parameters = adev_get_parameters;
4164 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4165 adev->device.open_output_stream = adev_open_output_stream;
4166 adev->device.close_output_stream = adev_close_output_stream;
4167 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004168
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004169 adev->device.close_input_stream = adev_close_input_stream;
4170 adev->device.dump = adev_dump;
4171
4172 /* Set the default route before the PCM stream is opened */
4173 pthread_mutex_lock(&adev->lock);
4174 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004175 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004176 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004177 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004178 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004179 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004180 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004181 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004182 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004183 pthread_mutex_unlock(&adev->lock);
4184
4185 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004186 adev->platform = platform_init(adev);
4187 if (!adev->platform) {
4188 free(adev->snd_dev_ref_cnt);
4189 free(adev);
4190 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4191 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004192 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004193 return -EINVAL;
4194 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05004195 adev->extspk = audio_extn_extspk_init(adev);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004196 audio_extn_sound_trigger_init(adev);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004197
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004198 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4199 if (adev->visualizer_lib == NULL) {
4200 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4201 } else {
4202 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4203 adev->visualizer_start_output =
4204 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4205 "visualizer_hal_start_output");
4206 adev->visualizer_stop_output =
4207 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4208 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07004209 }
4210
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004211 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4212 if (adev->offload_effects_lib == NULL) {
4213 ALOGW("%s: DLOPEN failed for %s", __func__,
4214 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4215 } else {
4216 ALOGV("%s: DLOPEN successful for %s", __func__,
4217 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4218 adev->offload_effects_start_output =
4219 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4220 "offload_effects_bundle_hal_start_output");
4221 adev->offload_effects_stop_output =
4222 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4223 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07004224 }
4225
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004226 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4227 if (adev->adm_lib == NULL) {
4228 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4229 } else {
4230 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4231 adev->adm_init = (adm_init_t)
4232 dlsym(adev->adm_lib, "adm_init");
4233 adev->adm_deinit = (adm_deinit_t)
4234 dlsym(adev->adm_lib, "adm_deinit");
4235 adev->adm_register_input_stream = (adm_register_input_stream_t)
4236 dlsym(adev->adm_lib, "adm_register_input_stream");
4237 adev->adm_register_output_stream = (adm_register_output_stream_t)
4238 dlsym(adev->adm_lib, "adm_register_output_stream");
4239 adev->adm_deregister_stream = (adm_deregister_stream_t)
4240 dlsym(adev->adm_lib, "adm_deregister_stream");
4241 adev->adm_request_focus = (adm_request_focus_t)
4242 dlsym(adev->adm_lib, "adm_request_focus");
4243 adev->adm_abandon_focus = (adm_abandon_focus_t)
4244 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08004245 adev->adm_set_config = (adm_set_config_t)
4246 dlsym(adev->adm_lib, "adm_set_config");
4247 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4248 dlsym(adev->adm_lib, "adm_request_focus_v2");
4249 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4250 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4251 adev->adm_on_routing_change = (adm_on_routing_change_t)
4252 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004253 }
4254
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004255 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004256 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004257
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004258 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004259
Andy Hung31aca912014-03-20 17:14:59 -07004260 if (k_enable_extended_precision)
4261 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004262
Glenn Kasten4f993392014-05-14 07:30:48 -07004263 char value[PROPERTY_VALUE_MAX];
4264 int trial;
4265 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4266 trial = atoi(value);
4267 if (period_size_is_plausible_for_low_latency(trial)) {
4268 pcm_config_low_latency.period_size = trial;
4269 pcm_config_low_latency.start_threshold = trial / 4;
4270 pcm_config_low_latency.avail_min = trial / 4;
4271 configured_low_latency_capture_period_size = trial;
4272 }
4273 }
4274 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4275 trial = atoi(value);
4276 if (period_size_is_plausible_for_low_latency(trial)) {
4277 configured_low_latency_capture_period_size = trial;
4278 }
4279 }
4280
Yamit Mehtae3b99562016-09-16 22:44:00 +05304281 audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004282 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004283
4284 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4285 af_period_multiplier = atoi(value);
4286 if (af_period_multiplier < 0) {
4287 af_period_multiplier = 2;
4288 } else if (af_period_multiplier > 4) {
4289 af_period_multiplier = 4;
4290 }
4291 ALOGV("new period_multiplier = %d", af_period_multiplier);
4292 }
4293
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004294 audio_extn_tfa_98xx_init(adev);
4295
vivek mehta1a9b7c02015-06-25 11:49:38 -07004296 pthread_mutex_unlock(&adev_init_lock);
4297
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004298 if (adev->adm_init)
4299 adev->adm_data = adev->adm_init();
4300
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004301 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004302 audio_extn_snd_mon_init();
4303 pthread_mutex_lock(&adev->lock);
4304 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
4305 adev->card_status = CARD_STATUS_ONLINE;
4306 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004307
Eric Laurent2bafff12016-03-17 12:17:23 -07004308 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004309 return 0;
4310}
4311
4312static struct hw_module_methods_t hal_module_methods = {
4313 .open = adev_open,
4314};
4315
4316struct audio_module HAL_MODULE_INFO_SYM = {
4317 .common = {
4318 .tag = HARDWARE_MODULE_TAG,
4319 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4320 .hal_api_version = HARDWARE_HAL_API_VERSION,
4321 .id = AUDIO_HARDWARE_MODULE_ID,
4322 .name = "QCOM Audio HAL",
4323 .author = "Code Aurora Forum",
4324 .methods = &hal_module_methods,
4325 },
4326};