blob: 1f762e962831e7414f8d5439ea04a89d68c36be6 [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>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036
37#include <cutils/log.h>
Haynes Mathew George03c40102016-01-29 17:57:48 -080038#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080039#include <cutils/str_parms.h>
40#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041#include <cutils/atomic.h>
42#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080043
Eric Laurentb23d5282013-05-14 15:27:20 -070044#include <hardware/audio_effect.h>
Andy Hung31aca912014-03-20 17:14:59 -070045#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070046#include <system/thread_defs.h>
Phil Burkbc991042017-02-24 08:06:44 -080047#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070048#include <audio_effects/effect_aec.h>
49#include <audio_effects/effect_ns.h>
Andy Hungfc044e12017-03-20 09:24:22 -070050#include <audio_utils/clock.h>
51#include <audio_utils/power.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052#include "audio_hw.h"
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -080053#include "audio_extn.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070054#include "platform_api.h"
55#include <platform.h>
Vineeta Srivastava4b89e372014-06-19 14:21:42 -070056#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070058#include "sound/compress_params.h"
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -080059#include "audio_extn/tfa_98xx.h"
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070060
Eric Laurent397db572016-05-11 11:31:47 -070061/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
62 * COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
Marco Nelissen32093f52015-04-08 15:14:02 -070063#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070064// 2 buffers causes problems with high bitrate files
65#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066/* ToDo: Check and update a proper value in msec */
67#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
68#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
69
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070070#define PROXY_OPEN_RETRY_COUNT 100
71#define PROXY_OPEN_WAIT_TIME 20
72
vivek mehtadae44712015-07-27 14:13:18 -070073#define MIN_CHANNEL_COUNT 1
74#define DEFAULT_CHANNEL_COUNT 2
75
Jean-Michel Trivic0750692015-10-12 12:12:32 -070076#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
77#define MAX_CHANNEL_COUNT 1
78#else
vivek mehtadae44712015-07-27 14:13:18 -070079#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
80#define XSTR(x) STR(x)
81#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070082#endif
vivek mehtadae44712015-07-27 14:13:18 -070083
Haynes Mathew George03c40102016-01-29 17:57:48 -080084#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
85
Glenn Kasten4f993392014-05-14 07:30:48 -070086static unsigned int configured_low_latency_capture_period_size =
87 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
88
Eric Laurent0e46adf2016-12-16 12:49:24 -080089
90#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Phil Burkbc991042017-02-24 08:06:44 -080091#define MMAP_PERIOD_COUNT_MIN 32
92#define MMAP_PERIOD_COUNT_MAX 512
93#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
Eric Laurent0e46adf2016-12-16 12:49:24 -080094
95
Andy Hung31aca912014-03-20 17:14:59 -070096/* This constant enables extended precision handling.
97 * TODO The flag is off until more testing is done.
98 */
99static const bool k_enable_extended_precision = false;
100
Eric Laurentb23d5282013-05-14 15:27:20 -0700101struct pcm_config pcm_config_deep_buffer = {
vivek mehtadae44712015-07-27 14:13:18 -0700102 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700103 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
104 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
105 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
106 .format = PCM_FORMAT_S16_LE,
107 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
108 .stop_threshold = INT_MAX,
109 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
110};
111
112struct pcm_config pcm_config_low_latency = {
vivek mehtadae44712015-07-27 14:13:18 -0700113 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700114 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
115 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
116 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
117 .format = PCM_FORMAT_S16_LE,
118 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
119 .stop_threshold = INT_MAX,
120 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
121};
122
Haynes Mathew George03c40102016-01-29 17:57:48 -0800123static int af_period_multiplier = 4;
124struct pcm_config pcm_config_rt = {
125 .channels = DEFAULT_CHANNEL_COUNT,
126 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
127 .period_size = ULL_PERIOD_SIZE, //1 ms
128 .period_count = 512, //=> buffer size is 512ms
129 .format = PCM_FORMAT_S16_LE,
130 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
131 .stop_threshold = INT_MAX,
132 .silence_threshold = 0,
133 .silence_size = 0,
134 .avail_min = ULL_PERIOD_SIZE, //1 ms
135};
136
Eric Laurentb23d5282013-05-14 15:27:20 -0700137struct pcm_config pcm_config_hdmi_multi = {
138 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
139 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
140 .period_size = HDMI_MULTI_PERIOD_SIZE,
141 .period_count = HDMI_MULTI_PERIOD_COUNT,
142 .format = PCM_FORMAT_S16_LE,
143 .start_threshold = 0,
144 .stop_threshold = INT_MAX,
145 .avail_min = 0,
146};
147
Eric Laurent0e46adf2016-12-16 12:49:24 -0800148struct pcm_config pcm_config_mmap_playback = {
149 .channels = DEFAULT_CHANNEL_COUNT,
150 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
151 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800152 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800153 .format = PCM_FORMAT_S16_LE,
154 .start_threshold = MMAP_PERIOD_SIZE*8,
155 .stop_threshold = INT32_MAX,
156 .silence_threshold = 0,
157 .silence_size = 0,
158 .avail_min = MMAP_PERIOD_SIZE, //1 ms
159};
160
Eric Laurentb23d5282013-05-14 15:27:20 -0700161struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700162 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700163 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
164 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700165 .stop_threshold = INT_MAX,
166 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700167};
168
Haynes Mathew George03c40102016-01-29 17:57:48 -0800169struct pcm_config pcm_config_audio_capture_rt = {
170 .channels = DEFAULT_CHANNEL_COUNT,
171 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
172 .period_size = ULL_PERIOD_SIZE,
173 .period_count = 512,
174 .format = PCM_FORMAT_S16_LE,
175 .start_threshold = 0,
176 .stop_threshold = INT_MAX,
177 .silence_threshold = 0,
178 .silence_size = 0,
179 .avail_min = ULL_PERIOD_SIZE, //1 ms
180};
181
Eric Laurent0e46adf2016-12-16 12:49:24 -0800182struct pcm_config pcm_config_mmap_capture = {
183 .channels = DEFAULT_CHANNEL_COUNT,
184 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
185 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800186 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800187 .format = PCM_FORMAT_S16_LE,
188 .start_threshold = 0,
189 .stop_threshold = INT_MAX,
190 .silence_threshold = 0,
191 .silence_size = 0,
192 .avail_min = MMAP_PERIOD_SIZE, //1 ms
193};
194
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700195#define AFE_PROXY_CHANNEL_COUNT 2
196#define AFE_PROXY_SAMPLING_RATE 48000
197
198#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
199#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
200
201struct pcm_config pcm_config_afe_proxy_playback = {
202 .channels = AFE_PROXY_CHANNEL_COUNT,
203 .rate = AFE_PROXY_SAMPLING_RATE,
204 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
205 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
206 .format = PCM_FORMAT_S16_LE,
207 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
208 .stop_threshold = INT_MAX,
209 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
210};
211
212#define AFE_PROXY_RECORD_PERIOD_SIZE 768
213#define AFE_PROXY_RECORD_PERIOD_COUNT 4
214
215struct pcm_config pcm_config_afe_proxy_record = {
216 .channels = AFE_PROXY_CHANNEL_COUNT,
217 .rate = AFE_PROXY_SAMPLING_RATE,
218 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
219 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
220 .format = PCM_FORMAT_S16_LE,
221 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
222 .stop_threshold = INT_MAX,
223 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
224};
225
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700226const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700227 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
228 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
229 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700230 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700231 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700232 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800233 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700234
Eric Laurentb23d5282013-05-14 15:27:20 -0700235 [USECASE_AUDIO_RECORD] = "audio-record",
236 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800237 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700238
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800239 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
240 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700241
Eric Laurentb23d5282013-05-14 15:27:20 -0700242 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700243 [USECASE_VOICE2_CALL] = "voice2-call",
244 [USECASE_VOLTE_CALL] = "volte-call",
245 [USECASE_QCHAT_CALL] = "qchat-call",
246 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800247 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
248 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700249
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700250 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
251 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
252
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700253 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
254 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700255};
256
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800257
258#define STRING_TO_ENUM(string) { #string, string }
259
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800260struct string_to_enum {
261 const char *name;
262 uint32_t value;
263};
264
265static const struct string_to_enum out_channels_name_to_enum_table[] = {
266 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
267 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
268 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
269};
270
Haynes Mathew George5191a852013-09-11 14:19:36 -0700271static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700272static struct audio_device *adev = NULL;
273static pthread_mutex_t adev_init_lock;
274static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700275//cache last MBDRC cal step level
276static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700277
Haynes Mathew George03c40102016-01-29 17:57:48 -0800278static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
279 int flags __unused)
280{
281 int dir = 0;
282 switch (uc_id) {
283 case USECASE_AUDIO_RECORD_LOW_LATENCY:
284 dir = 1;
285 case USECASE_AUDIO_PLAYBACK_ULL:
286 break;
287 default:
288 return false;
289 }
290
291 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
292 PCM_PLAYBACK : PCM_CAPTURE);
293 if (adev->adm_is_noirq_avail)
294 return adev->adm_is_noirq_avail(adev->adm_data,
295 adev->snd_card, dev_id, dir);
296 return false;
297}
298
299static void register_out_stream(struct stream_out *out)
300{
301 struct audio_device *adev = out->dev;
302 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
303 return;
304
305 if (!adev->adm_register_output_stream)
306 return;
307
308 adev->adm_register_output_stream(adev->adm_data,
309 out->handle,
310 out->flags);
311
312 if (!adev->adm_set_config)
313 return;
314
315 if (out->realtime) {
316 adev->adm_set_config(adev->adm_data,
317 out->handle,
318 out->pcm, &out->config);
319 }
320}
321
322static void register_in_stream(struct stream_in *in)
323{
324 struct audio_device *adev = in->dev;
325 if (!adev->adm_register_input_stream)
326 return;
327
328 adev->adm_register_input_stream(adev->adm_data,
329 in->capture_handle,
330 in->flags);
331
332 if (!adev->adm_set_config)
333 return;
334
335 if (in->realtime) {
336 adev->adm_set_config(adev->adm_data,
337 in->capture_handle,
338 in->pcm,
339 &in->config);
340 }
341}
342
343static void request_out_focus(struct stream_out *out, long ns)
344{
345 struct audio_device *adev = out->dev;
346
347 if (out->routing_change) {
348 out->routing_change = false;
349 if (adev->adm_on_routing_change)
350 adev->adm_on_routing_change(adev->adm_data, out->handle);
351 }
352
353 if (adev->adm_request_focus_v2) {
354 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
355 } else if (adev->adm_request_focus) {
356 adev->adm_request_focus(adev->adm_data, out->handle);
357 }
358}
359
360static void request_in_focus(struct stream_in *in, long ns)
361{
362 struct audio_device *adev = in->dev;
363
364 if (in->routing_change) {
365 in->routing_change = false;
366 if (adev->adm_on_routing_change)
367 adev->adm_on_routing_change(adev->adm_data, in->capture_handle);
368 }
369
370 if (adev->adm_request_focus_v2) {
371 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
372 } else if (adev->adm_request_focus) {
373 adev->adm_request_focus(adev->adm_data, in->capture_handle);
374 }
375}
376
377static void release_out_focus(struct stream_out *out, long ns __unused)
378{
379 struct audio_device *adev = out->dev;
380
381 if (adev->adm_abandon_focus)
382 adev->adm_abandon_focus(adev->adm_data, out->handle);
383}
384
385static void release_in_focus(struct stream_in *in, long ns __unused)
386{
387 struct audio_device *adev = in->dev;
388 if (adev->adm_abandon_focus)
389 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
390}
391
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700392static int parse_snd_card_status(struct str_parms * parms, int * card,
393 card_status_t * status)
394{
395 char value[32]={0};
396 char state[32]={0};
397
398 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
399
400 if (ret < 0)
401 return -1;
402
403 // sscanf should be okay as value is of max length 32.
404 // same as sizeof state.
405 if (sscanf(value, "%d,%s", card, state) < 2)
406 return -1;
407
408 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
409 CARD_STATUS_OFFLINE;
410 return 0;
411}
412
vivek mehta1a9b7c02015-06-25 11:49:38 -0700413__attribute__ ((visibility ("default")))
414bool audio_hw_send_gain_dep_calibration(int level) {
415 bool ret_val = false;
416 ALOGV("%s: enter ... ", __func__);
417
418 pthread_mutex_lock(&adev_init_lock);
419
420 if (adev != NULL && adev->platform != NULL) {
421 pthread_mutex_lock(&adev->lock);
422 ret_val = platform_send_gain_dep_cal(adev->platform, level);
423 pthread_mutex_unlock(&adev->lock);
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700424
425 // if cal set fails, cache level info
426 // if cal set succeds, reset known last cal set
427 if (!ret_val)
428 last_known_cal_step = level;
429 else if (last_known_cal_step != -1)
430 last_known_cal_step = -1;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700431 } else {
432 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
433 }
434
435 pthread_mutex_unlock(&adev_init_lock);
436
437 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
438 return ret_val;
439}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700440
vivek mehtaa8d7c922016-05-25 14:40:44 -0700441__attribute__ ((visibility ("default")))
442int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
443 int table_size) {
444 int ret_val = 0;
445 ALOGV("%s: enter ... ", __func__);
446
447 pthread_mutex_lock(&adev_init_lock);
448 if (adev == NULL) {
449 ALOGW("%s: adev is NULL .... ", __func__);
450 goto done;
451 }
452
453 pthread_mutex_lock(&adev->lock);
454 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
455 pthread_mutex_unlock(&adev->lock);
456done:
457 pthread_mutex_unlock(&adev_init_lock);
458 ALOGV("%s: exit ... ", __func__);
459 return ret_val;
460}
461
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700462static bool is_supported_format(audio_format_t format)
463{
Eric Laurent8251ac82014-07-23 11:00:25 -0700464 switch (format) {
465 case AUDIO_FORMAT_MP3:
466 case AUDIO_FORMAT_AAC_LC:
467 case AUDIO_FORMAT_AAC_HE_V1:
468 case AUDIO_FORMAT_AAC_HE_V2:
469 return true;
470 default:
471 break;
472 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700473 return false;
474}
475
Haynes Mathew George03c40102016-01-29 17:57:48 -0800476static inline bool is_mmap_usecase(audio_usecase_t uc_id)
477{
478 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
479 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
480}
481
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700482static int get_snd_codec_id(audio_format_t format)
483{
484 int id = 0;
485
Eric Laurent8251ac82014-07-23 11:00:25 -0700486 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700487 case AUDIO_FORMAT_MP3:
488 id = SND_AUDIOCODEC_MP3;
489 break;
490 case AUDIO_FORMAT_AAC:
491 id = SND_AUDIOCODEC_AAC;
492 break;
493 default:
494 ALOGE("%s: Unsupported audio format", __func__);
495 }
496
497 return id;
498}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800499
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800500static int audio_ssr_status(struct audio_device *adev)
501{
502 int ret = 0;
503 struct mixer_ctl *ctl;
504 const char *mixer_ctl_name = "Audio SSR Status";
505
506 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
507 ret = mixer_ctl_get_value(ctl, 0);
508 ALOGD("%s: value: %d", __func__, ret);
509 return ret;
510}
511
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800512int enable_audio_route(struct audio_device *adev,
513 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800514{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700515 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800516 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800517
518 if (usecase == NULL)
519 return -EINVAL;
520
521 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
522
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800523 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700524 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800525 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700526 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800527
Yamit Mehtae3b99562016-09-16 22:44:00 +0530528 audio_extn_utils_send_app_type_cfg(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800529 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500530 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700531 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700532 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800533
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800534 ALOGV("%s: exit", __func__);
535 return 0;
536}
537
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800538int disable_audio_route(struct audio_device *adev,
539 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800540{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700541 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800542 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800543
544 if (usecase == NULL)
545 return -EINVAL;
546
547 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700548 if (usecase->type == PCM_CAPTURE)
549 snd_device = usecase->in_snd_device;
550 else
551 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800552 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500553 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700554 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700555 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800556
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800557 ALOGV("%s: exit", __func__);
558 return 0;
559}
560
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800561int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700562 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800563{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700564 int i, num_devices = 0;
565 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800566 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800567 if (snd_device < SND_DEVICE_MIN ||
568 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800569 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800570 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800571 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700572
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700573 platform_send_audio_calibration(adev->platform, snd_device);
574
vivek mehtade4849c2016-03-03 17:23:38 -0800575 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700576 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700577 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800578 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700579 }
580
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700581 /* due to the possibility of calibration overwrite between listen
582 and audio, notify sound trigger hal before audio calibration is sent */
583 audio_extn_sound_trigger_update_device_status(snd_device,
584 ST_EVENT_SND_DEVICE_BUSY);
585
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700586 if (audio_extn_spkr_prot_is_enabled())
587 audio_extn_spkr_prot_calib_cancel(adev);
588
zhaoyang yin4211fad2015-06-04 21:13:25 +0800589 audio_extn_dsm_feedback_enable(adev, snd_device, true);
590
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700591 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
592 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
593 audio_extn_spkr_prot_is_enabled()) {
594 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800595 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700596 }
597 if (audio_extn_spkr_prot_start_processing(snd_device)) {
598 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800599 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700600 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700601 } else if (platform_can_split_snd_device(snd_device,
602 &num_devices,
603 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700604 for (i = 0; i < num_devices; i++) {
605 enable_snd_device(adev, new_snd_devices[i]);
606 }
vivek mehtab6506412015-08-07 16:55:17 -0700607 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700608 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800609 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
610 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
611 ALOGE(" %s: Invalid sound device returned", __func__);
612 goto on_error;
613 }
Ed Tam70b5c142016-03-21 19:14:29 -0700614
Eric Laurent2e140aa2016-06-30 17:14:46 -0700615 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800616 audio_route_apply_and_update_path(adev->audio_route, device_name);
617 }
618on_success:
619 adev->snd_dev_ref_cnt[snd_device]++;
620 ret_val = 0;
621on_error:
622 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800623}
624
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800625int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700626 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800627{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700628 int i, num_devices = 0;
629 snd_device_t new_snd_devices[2];
630
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800631 if (snd_device < SND_DEVICE_MIN ||
632 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800633 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800634 return -EINVAL;
635 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700636 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
637 ALOGE("%s: device ref cnt is already 0", __func__);
638 return -EINVAL;
639 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800640 audio_extn_tfa_98xx_disable_speaker(snd_device);
641
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700642 adev->snd_dev_ref_cnt[snd_device]--;
643 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800644 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700645 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
646 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
647 audio_extn_spkr_prot_is_enabled()) {
648 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700649 } else if (platform_can_split_snd_device(snd_device,
650 &num_devices,
651 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700652 for (i = 0; i < num_devices; i++) {
653 disable_snd_device(adev, new_snd_devices[i]);
654 }
vivek mehtab6506412015-08-07 16:55:17 -0700655 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700656 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800657 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
658 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
659 ALOGE(" %s: Invalid sound device returned", __func__);
660 return -EINVAL;
661 }
662
Eric Laurent2e140aa2016-06-30 17:14:46 -0700663 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800664 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700665 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700666 audio_extn_sound_trigger_update_device_status(snd_device,
667 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700668 }
vivek mehtab6506412015-08-07 16:55:17 -0700669
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800670 return 0;
671}
672
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700673/*
674 legend:
675 uc - existing usecase
676 new_uc - new usecase
677 d1, d11, d2 - SND_DEVICE enums
678 a1, a2 - corresponding ANDROID device enums
679 B, B1, B2 - backend strings
680
681case 1
682 uc->dev d1 (a1) B1
683 new_uc->dev d1 (a1), d2 (a2) B1, B2
684
685 resolution: disable and enable uc->dev on d1
686
687case 2
688 uc->dev d1 (a1) B1
689 new_uc->dev d11 (a1) B1
690
691 resolution: need to switch uc since d1 and d11 are related
692 (e.g. speaker and voice-speaker)
693 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
694
695case 3
696 uc->dev d1 (a1) B1
697 new_uc->dev d2 (a2) B2
698
699 resolution: no need to switch uc
700
701case 4
702 uc->dev d1 (a1) B
703 new_uc->dev d2 (a2) B
704
705 resolution: disable enable uc-dev on d2 since backends match
706 we cannot enable two streams on two different devices if they
707 share the same backend. e.g. if offload is on speaker device using
708 QUAD_MI2S backend and a low-latency stream is started on voice-handset
709 using the same backend, offload must also be switched to voice-handset.
710
711case 5
712 uc->dev d1 (a1) B
713 new_uc->dev d1 (a1), d2 (a2) B
714
715 resolution: disable enable uc-dev on d2 since backends match
716 we cannot enable two streams on two different devices if they
717 share the same backend.
718
719case 6
720 uc->dev d1 a1 B1
721 new_uc->dev d2 a1 B2
722
723 resolution: no need to switch
724
725case 7
726
727 uc->dev d1 (a1), d2 (a2) B1, B2
728 new_uc->dev d1 B1
729
730 resolution: no need to switch
731
732*/
733static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
734 struct audio_usecase *new_uc,
735 snd_device_t new_snd_device)
736{
737 audio_devices_t a1 = uc->stream.out->devices;
738 audio_devices_t a2 = new_uc->stream.out->devices;
739
740 snd_device_t d1 = uc->out_snd_device;
741 snd_device_t d2 = new_snd_device;
742
743 // Treat as a special case when a1 and a2 are not disjoint
744 if ((a1 != a2) && (a1 & a2)) {
745 snd_device_t d3[2];
746 int num_devices = 0;
747 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
748 &num_devices,
749 d3);
750 if (ret < 0) {
751 if (ret != -ENOSYS) {
752 ALOGW("%s failed to split snd_device %d",
753 __func__,
754 popcount(a1) > 1 ? d1 : d2);
755 }
756 goto end;
757 }
758
759 // NB: case 7 is hypothetical and isn't a practical usecase yet.
760 // But if it does happen, we need to give priority to d2 if
761 // the combo devices active on the existing usecase share a backend.
762 // This is because we cannot have a usecase active on a combo device
763 // and a new usecase requests one device in this combo pair.
764 if (platform_check_backends_match(d3[0], d3[1])) {
765 return d2; // case 5
766 } else {
767 return d1; // case 1
768 }
769 } else {
770 if (platform_check_backends_match(d1, d2)) {
771 return d2; // case 2, 4
772 } else {
773 return d1; // case 6, 3
774 }
775 }
776
777end:
778 return d2; // return whatever was calculated before.
779}
780
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700781static void check_and_route_playback_usecases(struct audio_device *adev,
782 struct audio_usecase *uc_info,
783 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700784{
785 struct listnode *node;
786 struct audio_usecase *usecase;
787 bool switch_device[AUDIO_USECASE_MAX];
788 int i, num_uc_to_switch = 0;
789
David Linee3fe402017-03-13 10:00:42 -0700790 platform_check_and_set_playback_backend_cfg(adev, uc_info, snd_device);
791
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700792 /*
793 * This function is to make sure that all the usecases that are active on
794 * the hardware codec backend are always routed to any one device that is
795 * handled by the hardware codec.
796 * For example, if low-latency and deep-buffer usecases are currently active
797 * on speaker and out_set_parameters(headset) is received on low-latency
798 * output, then we have to make sure deep-buffer is also switched to headset,
799 * because of the limitation that both the devices cannot be enabled
800 * at the same time as they share the same backend.
801 */
802 /* Disable all the usecases on the shared backend other than the
803 specified usecase */
804 for (i = 0; i < AUDIO_USECASE_MAX; i++)
805 switch_device[i] = false;
806
807 list_for_each(node, &adev->usecase_list) {
808 usecase = node_to_item(node, struct audio_usecase, list);
809 if (usecase->type != PCM_CAPTURE &&
810 usecase != uc_info &&
811 usecase->out_snd_device != snd_device &&
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700812 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
813 platform_check_backends_match(snd_device, usecase->out_snd_device)) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700814 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
815 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700816 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700817 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700818 switch_device[usecase->id] = true;
819 num_uc_to_switch++;
820 }
821 }
822
823 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700824 list_for_each(node, &adev->usecase_list) {
825 usecase = node_to_item(node, struct audio_usecase, list);
826 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700827 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900828 }
829 }
830
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700831 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900832 list_for_each(node, &adev->usecase_list) {
833 usecase = node_to_item(node, struct audio_usecase, list);
834 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700835 d_device = derive_playback_snd_device(usecase, uc_info,
836 snd_device);
837 enable_snd_device(adev, d_device);
838 /* Update the out_snd_device before enabling the audio route */
839 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700840 }
841 }
842
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700843 /* Re-route all the usecases on the shared backend other than the
844 specified usecase to new snd devices */
845 list_for_each(node, &adev->usecase_list) {
846 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700847 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700848 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700849 }
850 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700851 }
852}
853
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700854static void check_and_route_capture_usecases(struct audio_device *adev,
855 struct audio_usecase *uc_info,
856 snd_device_t snd_device)
857{
858 struct listnode *node;
859 struct audio_usecase *usecase;
860 bool switch_device[AUDIO_USECASE_MAX];
861 int i, num_uc_to_switch = 0;
862
vivek mehta4ed66e62016-04-15 23:33:34 -0700863 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
864
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700865 /*
866 * This function is to make sure that all the active capture usecases
867 * are always routed to the same input sound device.
868 * For example, if audio-record and voice-call usecases are currently
869 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
870 * is received for voice call then we have to make sure that audio-record
871 * usecase is also switched to earpiece i.e. voice-dmic-ef,
872 * because of the limitation that two devices cannot be enabled
873 * at the same time if they share the same backend.
874 */
875 for (i = 0; i < AUDIO_USECASE_MAX; i++)
876 switch_device[i] = false;
877
878 list_for_each(node, &adev->usecase_list) {
879 usecase = node_to_item(node, struct audio_usecase, list);
880 if (usecase->type != PCM_PLAYBACK &&
881 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700882 usecase->in_snd_device != snd_device &&
883 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700884 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
885 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700886 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700887 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700888 switch_device[usecase->id] = true;
889 num_uc_to_switch++;
890 }
891 }
892
893 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700894 list_for_each(node, &adev->usecase_list) {
895 usecase = node_to_item(node, struct audio_usecase, list);
896 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700897 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700898 }
899 }
900
901 list_for_each(node, &adev->usecase_list) {
902 usecase = node_to_item(node, struct audio_usecase, list);
903 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700904 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700905 }
906 }
907
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700908 /* Re-route all the usecases on the shared backend other than the
909 specified usecase to new snd devices */
910 list_for_each(node, &adev->usecase_list) {
911 usecase = node_to_item(node, struct audio_usecase, list);
912 /* Update the in_snd_device only before enabling the audio route */
913 if (switch_device[usecase->id] ) {
914 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700915 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700916 }
917 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700918 }
919}
920
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800921/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700922static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800923{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700924 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700925 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800926
927 switch (channels) {
928 /*
929 * Do not handle stereo output in Multi-channel cases
930 * Stereo case is handled in normal playback path
931 */
932 case 6:
933 ALOGV("%s: HDMI supports 5.1", __func__);
934 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
935 break;
936 case 8:
937 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
938 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
939 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
940 break;
941 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700942 ALOGE("HDMI does not support multi channel playback");
943 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800944 break;
945 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700946 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800947}
948
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -0700949static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
950{
951 struct audio_usecase *usecase;
952 struct listnode *node;
953
954 list_for_each(node, &adev->usecase_list) {
955 usecase = node_to_item(node, struct audio_usecase, list);
956 if (usecase->type == VOICE_CALL) {
957 ALOGV("%s: usecase id %d", __func__, usecase->id);
958 return usecase->id;
959 }
960 }
961 return USECASE_INVALID;
962}
963
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800964struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
965 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700966{
967 struct audio_usecase *usecase;
968 struct listnode *node;
969
970 list_for_each(node, &adev->usecase_list) {
971 usecase = node_to_item(node, struct audio_usecase, list);
972 if (usecase->id == uc_id)
973 return usecase;
974 }
975 return NULL;
976}
977
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800978int select_devices(struct audio_device *adev,
979 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800980{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800981 snd_device_t out_snd_device = SND_DEVICE_NONE;
982 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700983 struct audio_usecase *usecase = NULL;
984 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800985 struct audio_usecase *hfp_usecase = NULL;
986 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800987 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700988 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800989
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700990 usecase = get_usecase_from_list(adev, uc_id);
991 if (usecase == NULL) {
992 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
993 return -EINVAL;
994 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800995
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800996 if ((usecase->type == VOICE_CALL) ||
997 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700998 out_snd_device = platform_get_output_snd_device(adev->platform,
999 usecase->stream.out->devices);
1000 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001001 usecase->devices = usecase->stream.out->devices;
1002 } else {
1003 /*
1004 * If the voice call is active, use the sound devices of voice call usecase
1005 * so that it would not result any device switch. All the usecases will
1006 * be switched to new device when select_devices() is called for voice call
1007 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001008 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001009 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001010 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001011 vc_usecase = get_usecase_from_list(adev,
1012 get_voice_usecase_id_from_list(adev));
1013 if ((vc_usecase != NULL) &&
1014 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1015 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001016 in_snd_device = vc_usecase->in_snd_device;
1017 out_snd_device = vc_usecase->out_snd_device;
1018 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001019 } else if (audio_extn_hfp_is_active(adev)) {
1020 hfp_ucid = audio_extn_hfp_get_usecase();
1021 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1022 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1023 in_snd_device = hfp_usecase->in_snd_device;
1024 out_snd_device = hfp_usecase->out_snd_device;
1025 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001026 }
1027 if (usecase->type == PCM_PLAYBACK) {
1028 usecase->devices = usecase->stream.out->devices;
1029 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001030 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001031 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001032 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001033 if (usecase->stream.out == adev->primary_output &&
1034 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001035 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1036 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001037 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001038 select_devices(adev, adev->active_input->usecase);
1039 }
1040 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001041 } else if (usecase->type == PCM_CAPTURE) {
1042 usecase->devices = usecase->stream.in->device;
1043 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001044 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001045 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001046 if (adev->active_input &&
1047 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1048 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001049 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001050 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1051 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
1052 } else if (adev->primary_output) {
1053 out_device = adev->primary_output->devices;
1054 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001055 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001056 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001057 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001058 }
1059 }
1060
1061 if (out_snd_device == usecase->out_snd_device &&
1062 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001063 return 0;
1064 }
1065
Eric Laurent2bafff12016-03-17 12:17:23 -07001066 if (out_snd_device != SND_DEVICE_NONE &&
1067 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1068 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1069 __func__,
1070 use_case_table[uc_id],
1071 adev->last_logged_snd_device[uc_id][0],
1072 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1073 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1074 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1075 -1,
1076 out_snd_device,
1077 platform_get_snd_device_name(out_snd_device),
1078 platform_get_snd_device_acdb_id(out_snd_device));
1079 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1080 }
1081 if (in_snd_device != SND_DEVICE_NONE &&
1082 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1083 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1084 __func__,
1085 use_case_table[uc_id],
1086 adev->last_logged_snd_device[uc_id][1],
1087 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1088 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1089 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1090 -1,
1091 in_snd_device,
1092 platform_get_snd_device_name(in_snd_device),
1093 platform_get_snd_device_acdb_id(in_snd_device));
1094 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1095 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001096
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001097 /*
1098 * Limitation: While in call, to do a device switch we need to disable
1099 * and enable both RX and TX devices though one of them is same as current
1100 * device.
1101 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001102 if ((usecase->type == VOICE_CALL) &&
1103 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1104 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001105 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001106 /* Disable sidetone only if voice call already exists */
1107 if (voice_is_call_state_active(adev))
1108 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001109 }
1110
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001111 /* Disable current sound devices */
1112 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001113 disable_audio_route(adev, usecase);
1114 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001115 }
1116
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001117 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001118 disable_audio_route(adev, usecase);
1119 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001120 }
1121
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001122 /* Applicable only on the targets that has external modem.
1123 * New device information should be sent to modem before enabling
1124 * the devices to reduce in-call device switch time.
1125 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001126 if ((usecase->type == VOICE_CALL) &&
1127 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1128 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001129 status = platform_switch_voice_call_enable_device_config(adev->platform,
1130 out_snd_device,
1131 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001132 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001133
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001134 /* Enable new sound devices */
1135 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001136 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1137 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001138 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001139 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001140 }
1141
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001142 if (in_snd_device != SND_DEVICE_NONE) {
1143 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001144 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001145 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001146
Eric Laurentb23d5282013-05-14 15:27:20 -07001147 if (usecase->type == VOICE_CALL)
1148 status = platform_switch_voice_call_device_post(adev->platform,
1149 out_snd_device,
1150 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001151
sangwoo170731f2013-06-08 15:36:36 +09001152 usecase->in_snd_device = in_snd_device;
1153 usecase->out_snd_device = out_snd_device;
1154
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001155 audio_extn_tfa_98xx_set_mode();
1156
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001157 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001158
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001159 /* Applicable only on the targets that has external modem.
1160 * Enable device command should be sent to modem only after
1161 * enabling voice call mixer controls
1162 */
vivek mehta765eb642015-08-07 19:46:06 -07001163 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001164 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1165 out_snd_device,
1166 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001167 /* Enable sidetone only if voice call already exists */
1168 if (voice_is_call_state_active(adev))
1169 voice_set_sidetone(adev, out_snd_device, true);
1170 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001171
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001172 return status;
1173}
1174
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001175static int stop_input_stream(struct stream_in *in)
1176{
1177 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001178 struct audio_usecase *uc_info;
1179 struct audio_device *adev = in->dev;
1180
Eric Laurentc8400632013-02-14 19:04:54 -08001181 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001182
Eric Laurent994a6932013-07-17 11:51:42 -07001183 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001184 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001185 uc_info = get_usecase_from_list(adev, in->usecase);
1186 if (uc_info == NULL) {
1187 ALOGE("%s: Could not find the usecase (%d) in the list",
1188 __func__, in->usecase);
1189 return -EINVAL;
1190 }
1191
Eric Laurent150dbfe2013-02-27 14:31:02 -08001192 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001193 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001194
1195 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001196 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001197
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001198 list_remove(&uc_info->list);
1199 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001200
Eric Laurent994a6932013-07-17 11:51:42 -07001201 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001202 return ret;
1203}
1204
1205int start_input_stream(struct stream_in *in)
1206{
1207 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001208 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001209 struct audio_usecase *uc_info;
1210 struct audio_device *adev = in->dev;
1211
Eric Laurent994a6932013-07-17 11:51:42 -07001212 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001213
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001214 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1215 return -EIO;
1216
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001217 if (in->card_status == CARD_STATUS_OFFLINE ||
1218 adev->card_status == CARD_STATUS_OFFLINE) {
1219 ALOGW("in->card_status or adev->card_status offline, try again");
1220 ret = -EAGAIN;
1221 goto error_config;
1222 }
1223
Eric Laurentb23d5282013-05-14 15:27:20 -07001224 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001225 if (in->pcm_device_id < 0) {
1226 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1227 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001228 ret = -EINVAL;
1229 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001230 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001231
1232 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001233 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1234 uc_info->id = in->usecase;
1235 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001236 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001237 uc_info->devices = in->device;
1238 uc_info->in_snd_device = SND_DEVICE_NONE;
1239 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001240
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001241 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001242
1243 audio_extn_perf_lock_acquire();
1244
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001245 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001246
Eric Laurent0e46adf2016-12-16 12:49:24 -08001247 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001248 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001249 ALOGE("%s: pcm stream not ready", __func__);
1250 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001251 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001252 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001253 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001254 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1255 goto error_open;
1256 }
1257 } else {
1258 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1259 unsigned int pcm_open_retry_count = 0;
1260
1261 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1262 flags |= PCM_MMAP | PCM_NOIRQ;
1263 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1264 } else if (in->realtime) {
1265 flags |= PCM_MMAP | PCM_NOIRQ;
1266 }
1267
1268 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1269 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1270
1271 while (1) {
1272 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1273 flags, &in->config);
1274 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1275 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1276 if (in->pcm != NULL) {
1277 pcm_close(in->pcm);
1278 in->pcm = NULL;
1279 }
1280 if (pcm_open_retry_count-- == 0) {
1281 ret = -EIO;
1282 goto error_open;
1283 }
1284 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1285 continue;
1286 }
1287 break;
1288 }
1289
1290 ALOGV("%s: pcm_prepare", __func__);
1291 ret = pcm_prepare(in->pcm);
1292 if (ret < 0) {
1293 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001294 pcm_close(in->pcm);
1295 in->pcm = NULL;
1296 goto error_open;
1297 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001298 if (in->realtime) {
1299 ret = pcm_start(in->pcm);
1300 if (ret < 0) {
1301 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1302 pcm_close(in->pcm);
1303 in->pcm = NULL;
1304 goto error_open;
1305 }
1306 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001307 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001308 register_in_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001309 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001310 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001311
Eric Laurent0e46adf2016-12-16 12:49:24 -08001312 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001313
1314error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001315 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001316 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001317
1318error_config:
1319 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001320 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001321
1322 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001323}
1324
Eric Laurenta1478072015-09-21 17:21:52 -07001325void lock_input_stream(struct stream_in *in)
1326{
1327 pthread_mutex_lock(&in->pre_lock);
1328 pthread_mutex_lock(&in->lock);
1329 pthread_mutex_unlock(&in->pre_lock);
1330}
1331
1332void lock_output_stream(struct stream_out *out)
1333{
1334 pthread_mutex_lock(&out->pre_lock);
1335 pthread_mutex_lock(&out->lock);
1336 pthread_mutex_unlock(&out->pre_lock);
1337}
1338
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001339/* must be called with out->lock locked */
1340static int send_offload_cmd_l(struct stream_out* out, int command)
1341{
1342 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1343
1344 ALOGVV("%s %d", __func__, command);
1345
1346 cmd->cmd = command;
1347 list_add_tail(&out->offload_cmd_list, &cmd->node);
1348 pthread_cond_signal(&out->offload_cond);
1349 return 0;
1350}
1351
1352/* must be called iwth out->lock locked */
1353static void stop_compressed_output_l(struct stream_out *out)
1354{
1355 out->offload_state = OFFLOAD_STATE_IDLE;
1356 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001357 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001358 if (out->compr != NULL) {
1359 compress_stop(out->compr);
1360 while (out->offload_thread_blocked) {
1361 pthread_cond_wait(&out->cond, &out->lock);
1362 }
1363 }
1364}
1365
1366static void *offload_thread_loop(void *context)
1367{
1368 struct stream_out *out = (struct stream_out *) context;
1369 struct listnode *item;
1370
1371 out->offload_state = OFFLOAD_STATE_IDLE;
1372 out->playback_started = 0;
1373
1374 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1375 set_sched_policy(0, SP_FOREGROUND);
1376 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1377
1378 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001379 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001380 for (;;) {
1381 struct offload_cmd *cmd = NULL;
1382 stream_callback_event_t event;
1383 bool send_callback = false;
1384
1385 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1386 __func__, list_empty(&out->offload_cmd_list),
1387 out->offload_state);
1388 if (list_empty(&out->offload_cmd_list)) {
1389 ALOGV("%s SLEEPING", __func__);
1390 pthread_cond_wait(&out->offload_cond, &out->lock);
1391 ALOGV("%s RUNNING", __func__);
1392 continue;
1393 }
1394
1395 item = list_head(&out->offload_cmd_list);
1396 cmd = node_to_item(item, struct offload_cmd, node);
1397 list_remove(item);
1398
1399 ALOGVV("%s STATE %d CMD %d out->compr %p",
1400 __func__, out->offload_state, cmd->cmd, out->compr);
1401
1402 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1403 free(cmd);
1404 break;
1405 }
1406
1407 if (out->compr == NULL) {
1408 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001409 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001410 pthread_cond_signal(&out->cond);
1411 continue;
1412 }
1413 out->offload_thread_blocked = true;
1414 pthread_mutex_unlock(&out->lock);
1415 send_callback = false;
1416 switch(cmd->cmd) {
1417 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1418 compress_wait(out->compr, -1);
1419 send_callback = true;
1420 event = STREAM_CBK_EVENT_WRITE_READY;
1421 break;
1422 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001423 compress_next_track(out->compr);
1424 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001425 send_callback = true;
1426 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001427 /* Resend the metadata for next iteration */
1428 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001429 break;
1430 case OFFLOAD_CMD_DRAIN:
1431 compress_drain(out->compr);
1432 send_callback = true;
1433 event = STREAM_CBK_EVENT_DRAIN_READY;
1434 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001435 case OFFLOAD_CMD_ERROR:
1436 send_callback = true;
1437 event = STREAM_CBK_EVENT_ERROR;
1438 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001439 default:
1440 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1441 break;
1442 }
Eric Laurenta1478072015-09-21 17:21:52 -07001443 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001444 out->offload_thread_blocked = false;
1445 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001446 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001447 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001448 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001449 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001450 free(cmd);
1451 }
1452
1453 pthread_cond_signal(&out->cond);
1454 while (!list_empty(&out->offload_cmd_list)) {
1455 item = list_head(&out->offload_cmd_list);
1456 list_remove(item);
1457 free(node_to_item(item, struct offload_cmd, node));
1458 }
1459 pthread_mutex_unlock(&out->lock);
1460
1461 return NULL;
1462}
1463
1464static int create_offload_callback_thread(struct stream_out *out)
1465{
1466 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1467 list_init(&out->offload_cmd_list);
1468 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1469 offload_thread_loop, out);
1470 return 0;
1471}
1472
1473static int destroy_offload_callback_thread(struct stream_out *out)
1474{
Eric Laurenta1478072015-09-21 17:21:52 -07001475 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001476 stop_compressed_output_l(out);
1477 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1478
1479 pthread_mutex_unlock(&out->lock);
1480 pthread_join(out->offload_thread, (void **) NULL);
1481 pthread_cond_destroy(&out->offload_cond);
1482
1483 return 0;
1484}
1485
Eric Laurent07eeafd2013-10-06 12:52:49 -07001486static bool allow_hdmi_channel_config(struct audio_device *adev)
1487{
1488 struct listnode *node;
1489 struct audio_usecase *usecase;
1490 bool ret = true;
1491
1492 list_for_each(node, &adev->usecase_list) {
1493 usecase = node_to_item(node, struct audio_usecase, list);
1494 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1495 /*
1496 * If voice call is already existing, do not proceed further to avoid
1497 * disabling/enabling both RX and TX devices, CSD calls, etc.
1498 * Once the voice call done, the HDMI channels can be configured to
1499 * max channels of remaining use cases.
1500 */
1501 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001502 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001503 __func__);
1504 ret = false;
1505 break;
1506 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
Joe Onorato188b6222016-03-01 11:02:27 -08001507 ALOGV("%s: multi channel playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001508 "no change in HDMI channels", __func__);
1509 ret = false;
1510 break;
1511 }
1512 }
1513 }
1514 return ret;
1515}
1516
1517static int check_and_set_hdmi_channels(struct audio_device *adev,
1518 unsigned int channels)
1519{
1520 struct listnode *node;
1521 struct audio_usecase *usecase;
1522
1523 /* Check if change in HDMI channel config is allowed */
1524 if (!allow_hdmi_channel_config(adev))
1525 return 0;
1526
1527 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001528 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001529 return 0;
1530 }
1531
1532 platform_set_hdmi_channels(adev->platform, channels);
1533 adev->cur_hdmi_channels = channels;
1534
1535 /*
1536 * Deroute all the playback streams routed to HDMI so that
1537 * the back end is deactivated. Note that backend will not
1538 * be deactivated if any one stream is connected to it.
1539 */
1540 list_for_each(node, &adev->usecase_list) {
1541 usecase = node_to_item(node, struct audio_usecase, list);
1542 if (usecase->type == PCM_PLAYBACK &&
1543 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001544 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001545 }
1546 }
1547
1548 /*
1549 * Enable all the streams disabled above. Now the HDMI backend
1550 * will be activated with new channel configuration
1551 */
1552 list_for_each(node, &adev->usecase_list) {
1553 usecase = node_to_item(node, struct audio_usecase, list);
1554 if (usecase->type == PCM_PLAYBACK &&
1555 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001556 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001557 }
1558 }
1559
1560 return 0;
1561}
1562
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001563static int stop_output_stream(struct stream_out *out)
1564{
1565 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001566 struct audio_usecase *uc_info;
1567 struct audio_device *adev = out->dev;
1568
Eric Laurent994a6932013-07-17 11:51:42 -07001569 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001570 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001571 uc_info = get_usecase_from_list(adev, out->usecase);
1572 if (uc_info == NULL) {
1573 ALOGE("%s: Could not find the usecase (%d) in the list",
1574 __func__, out->usecase);
1575 return -EINVAL;
1576 }
1577
Haynes Mathew George41f86652014-06-17 14:22:15 -07001578 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1579 if (adev->visualizer_stop_output != NULL)
1580 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1581 if (adev->offload_effects_stop_output != NULL)
1582 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1583 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001584
Eric Laurent150dbfe2013-02-27 14:31:02 -08001585 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001586 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001587
1588 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001589 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001590
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001591 list_remove(&uc_info->list);
1592 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001593
Eric Laurent0499d4f2014-08-25 22:39:29 -05001594 audio_extn_extspk_update(adev->extspk);
1595
Eric Laurent07eeafd2013-10-06 12:52:49 -07001596 /* Must be called after removing the usecase from list */
1597 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1598 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1599
Eric Laurent994a6932013-07-17 11:51:42 -07001600 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001601 return ret;
1602}
1603
1604int start_output_stream(struct stream_out *out)
1605{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001606 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001607 struct audio_usecase *uc_info;
1608 struct audio_device *adev = out->dev;
1609
Eric Laurent994a6932013-07-17 11:51:42 -07001610 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001611 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001612
1613 if (out->card_status == CARD_STATUS_OFFLINE ||
1614 adev->card_status == CARD_STATUS_OFFLINE) {
1615 ALOGW("out->card_status or adev->card_status offline, try again");
1616 ret = -EAGAIN;
1617 goto error_config;
1618 }
1619
Eric Laurentb23d5282013-05-14 15:27:20 -07001620 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001621 if (out->pcm_device_id < 0) {
1622 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1623 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001624 ret = -EINVAL;
1625 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001626 }
1627
1628 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1629 uc_info->id = out->usecase;
1630 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001631 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001632 uc_info->devices = out->devices;
1633 uc_info->in_snd_device = SND_DEVICE_NONE;
1634 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001635
Eric Laurent07eeafd2013-10-06 12:52:49 -07001636 /* This must be called before adding this usecase to the list */
1637 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1638 check_and_set_hdmi_channels(adev, out->config.channels);
1639
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001640 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001641
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001642 audio_extn_perf_lock_acquire();
1643
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001644 select_devices(adev, out->usecase);
1645
Eric Laurent0499d4f2014-08-25 22:39:29 -05001646 audio_extn_extspk_update(adev->extspk);
1647
Andy Hung31aca912014-03-20 17:14:59 -07001648 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001649 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001650 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1651 out->pcm = NULL;
1652 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1653 COMPRESS_IN, &out->compr_config);
1654 if (out->compr && !is_compress_ready(out->compr)) {
1655 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1656 compress_close(out->compr);
1657 out->compr = NULL;
1658 ret = -EIO;
1659 goto error_open;
1660 }
1661 if (out->offload_callback)
1662 compress_nonblock(out->compr, out->non_blocking);
1663
1664 if (adev->visualizer_start_output != NULL)
1665 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1666 if (adev->offload_effects_start_output != NULL)
1667 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
1668 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001669 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001670 ALOGE("%s: pcm stream not ready", __func__);
1671 goto error_open;
1672 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001673 ret = pcm_start(out->pcm);
1674 if (ret < 0) {
1675 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1676 goto error_open;
1677 }
1678 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001679 unsigned int flags = PCM_OUT;
1680 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001681
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001682 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1683 flags |= PCM_MMAP | PCM_NOIRQ;
1684 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001685 } else if (out->realtime) {
1686 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001687 } else
1688 flags |= PCM_MONOTONIC;
1689
1690 while (1) {
1691 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1692 flags, &out->config);
1693 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1694 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1695 if (out->pcm != NULL) {
1696 pcm_close(out->pcm);
1697 out->pcm = NULL;
1698 }
1699 if (pcm_open_retry_count-- == 0) {
1700 ret = -EIO;
1701 goto error_open;
1702 }
1703 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1704 continue;
1705 }
1706 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001707 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001708 ALOGV("%s: pcm_prepare", __func__);
1709 if (pcm_is_ready(out->pcm)) {
1710 ret = pcm_prepare(out->pcm);
1711 if (ret < 0) {
1712 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1713 pcm_close(out->pcm);
1714 out->pcm = NULL;
1715 goto error_open;
1716 }
1717 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001718 if (out->realtime) {
1719 ret = pcm_start(out->pcm);
1720 if (ret < 0) {
1721 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1722 pcm_close(out->pcm);
1723 out->pcm = NULL;
1724 goto error_open;
1725 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001726 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001727 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001728 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001729 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001730 audio_extn_tfa_98xx_enable_speaker();
1731
Eric Laurent994a6932013-07-17 11:51:42 -07001732 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001733 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001734error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001735 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001736 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001737error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001738 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001739}
1740
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001741static int check_input_parameters(uint32_t sample_rate,
1742 audio_format_t format,
1743 int channel_count)
1744{
vivek mehta4ed66e62016-04-15 23:33:34 -07001745 if ((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT)) {
vivek mehtadae44712015-07-27 14:13:18 -07001746 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1747 return -EINVAL;
1748 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001749
vivek mehtadae44712015-07-27 14:13:18 -07001750 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > MAX_CHANNEL_COUNT)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001751 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
vivek mehtadae44712015-07-27 14:13:18 -07001752 channel_count, MIN_CHANNEL_COUNT, MAX_CHANNEL_COUNT);
1753 return -EINVAL;
1754 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001755
1756 switch (sample_rate) {
1757 case 8000:
1758 case 11025:
1759 case 12000:
1760 case 16000:
1761 case 22050:
1762 case 24000:
1763 case 32000:
1764 case 44100:
1765 case 48000:
1766 break;
1767 default:
vivek mehtadae44712015-07-27 14:13:18 -07001768 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001769 return -EINVAL;
1770 }
1771
1772 return 0;
1773}
1774
1775static size_t get_input_buffer_size(uint32_t sample_rate,
1776 audio_format_t format,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001777 int channel_count,
1778 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001779{
1780 size_t size = 0;
1781
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001782 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1783 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001784
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001785 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001786 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001787 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07001788
1789 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001790
Glenn Kasten4f993392014-05-14 07:30:48 -07001791 /* make sure the size is multiple of 32 bytes
1792 * At 48 kHz mono 16-bit PCM:
1793 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1794 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1795 */
1796 size += 0x1f;
1797 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001798
1799 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001800}
1801
1802static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1803{
1804 struct stream_out *out = (struct stream_out *)stream;
1805
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001806 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001807}
1808
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001809static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001810{
1811 return -ENOSYS;
1812}
1813
1814static size_t out_get_buffer_size(const struct audio_stream *stream)
1815{
1816 struct stream_out *out = (struct stream_out *)stream;
1817
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001818 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1819 return out->compr_config.fragment_size;
1820 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001821 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07001822 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001823}
1824
1825static uint32_t out_get_channels(const struct audio_stream *stream)
1826{
1827 struct stream_out *out = (struct stream_out *)stream;
1828
1829 return out->channel_mask;
1830}
1831
1832static audio_format_t out_get_format(const struct audio_stream *stream)
1833{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001834 struct stream_out *out = (struct stream_out *)stream;
1835
1836 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001837}
1838
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001839static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001840{
1841 return -ENOSYS;
1842}
1843
1844static int out_standby(struct audio_stream *stream)
1845{
1846 struct stream_out *out = (struct stream_out *)stream;
1847 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08001848 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001849
Eric Laurent994a6932013-07-17 11:51:42 -07001850 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001851 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001852
Eric Laurenta1478072015-09-21 17:21:52 -07001853 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001854 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001855 if (adev->adm_deregister_stream)
1856 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001857 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001858 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001859 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1860 if (out->pcm) {
1861 pcm_close(out->pcm);
1862 out->pcm = NULL;
1863 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001864 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001865 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08001866 out->playback_started = false;
1867 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001868 } else {
1869 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001870 out->gapless_mdata.encoder_delay = 0;
1871 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001872 if (out->compr != NULL) {
1873 compress_close(out->compr);
1874 out->compr = NULL;
1875 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001876 }
Phil Burkbc991042017-02-24 08:06:44 -08001877 if (do_stop) {
1878 stop_output_stream(out);
1879 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001880 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001881 }
1882 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001883 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001884 return 0;
1885}
1886
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001887static int out_on_error(struct audio_stream *stream)
1888{
1889 struct stream_out *out = (struct stream_out *)stream;
1890 struct audio_device *adev = out->dev;
1891 bool do_standby = false;
1892
1893 lock_output_stream(out);
1894 if (!out->standby) {
1895 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1896 stop_compressed_output_l(out);
1897 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
1898 } else
1899 do_standby = true;
1900 }
1901 pthread_mutex_unlock(&out->lock);
1902
1903 if (do_standby)
1904 return out_standby(&out->stream.common);
1905
1906 return 0;
1907}
1908
Andy Hung7401c7c2016-09-21 12:41:21 -07001909static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001910{
Andy Hung7401c7c2016-09-21 12:41:21 -07001911 struct stream_out *out = (struct stream_out *)stream;
1912
1913 // We try to get the lock for consistency,
1914 // but it isn't necessary for these variables.
1915 // If we're not in standby, we may be blocked on a write.
1916 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
1917 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
1918 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
1919
1920 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07001921 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07001922 }
Andy Hunga452b0a2017-03-15 14:51:15 -07001923
1924 // dump error info
1925 (void)error_log_dump(
1926 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hungfc044e12017-03-20 09:24:22 -07001927 // dump power info (out->power_log may be null)
Andy Hung62c9b882017-03-22 16:43:42 -07001928 (void)power_log_dump(
1929 out->power_log, fd, " " /* prefix */, POWER_LOG_LINES, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001930 return 0;
1931}
1932
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001933static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1934{
1935 int ret = 0;
1936 char value[32];
1937 struct compr_gapless_mdata tmp_mdata;
1938
1939 if (!out || !parms) {
1940 return -EINVAL;
1941 }
1942
1943 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1944 if (ret >= 0) {
1945 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
1946 } else {
1947 return -EINVAL;
1948 }
1949
1950 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1951 if (ret >= 0) {
1952 tmp_mdata.encoder_padding = atoi(value);
1953 } else {
1954 return -EINVAL;
1955 }
1956
1957 out->gapless_mdata = tmp_mdata;
1958 out->send_new_metadata = 1;
1959 ALOGV("%s new encoder delay %u and padding %u", __func__,
1960 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1961
1962 return 0;
1963}
1964
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001965static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1966{
1967 return out == adev->primary_output || out == adev->voice_tx_output;
1968}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001969
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001970static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1971{
1972 struct stream_out *out = (struct stream_out *)stream;
1973 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001974 struct audio_usecase *usecase;
1975 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001976 struct str_parms *parms;
1977 char value[32];
1978 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001979 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07001980 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001981
Eric Laurent2e140aa2016-06-30 17:14:46 -07001982 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001983 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001984 parms = str_parms_create_str(kvpairs);
1985 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1986 if (ret >= 0) {
1987 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07001988 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001989 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001990
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001991 /*
1992 * When HDMI cable is unplugged the music playback is paused and
1993 * the policy manager sends routing=0. But the audioflinger
1994 * continues to write data until standby time (3sec).
1995 * As the HDMI core is turned off, the write gets blocked.
1996 * Avoid this by routing audio to speaker until standby.
1997 */
1998 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
1999 val == AUDIO_DEVICE_NONE) {
2000 val = AUDIO_DEVICE_OUT_SPEAKER;
2001 }
2002
2003 /*
2004 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002005 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002006 * the select_devices(). But how do we undo this?
2007 *
2008 * For example, music playback is active on headset (deep-buffer usecase)
2009 * and if we go to ringtones and select a ringtone, low-latency usecase
2010 * will be started on headset+speaker. As we can't enable headset+speaker
2011 * and headset devices at the same time, select_devices() switches the music
2012 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2013 * So when the ringtone playback is completed, how do we undo the same?
2014 *
2015 * We are relying on the out_set_parameters() call on deep-buffer output,
2016 * once the ringtone playback is ended.
2017 * NOTE: We should not check if the current devices are same as new devices.
2018 * Because select_devices() must be called to switch back the music
2019 * playback to headset.
2020 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002021 audio_devices_t new_dev = val;
2022 if (new_dev != AUDIO_DEVICE_NONE) {
2023 bool same_dev = out->devices == new_dev;
2024 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002025
Eric Laurenta7657192014-10-09 21:09:33 -07002026 if (output_drives_call(adev, out)) {
2027 if (!voice_is_in_call(adev)) {
2028 if (adev->mode == AUDIO_MODE_IN_CALL) {
2029 adev->current_call_output = out;
2030 ret = voice_start_call(adev);
2031 }
2032 } else {
2033 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002034 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002035 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002036 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002037
2038 if (!out->standby) {
2039 if (!same_dev) {
2040 ALOGV("update routing change");
2041 out->routing_change = true;
2042 }
2043 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002044 audio_extn_tfa_98xx_update();
vivek mehta0d3637a2016-07-24 09:32:02 -07002045 }
2046
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002047 }
2048
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002049 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002050 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002051
2052 /*handles device and call state changes*/
2053 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002054 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002055
2056 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2057 parse_compress_metadata(out, parms);
2058 }
2059
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002060 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002061 ALOGV("%s: exit: code(%d)", __func__, status);
2062 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002063}
2064
2065static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2066{
2067 struct stream_out *out = (struct stream_out *)stream;
2068 struct str_parms *query = str_parms_create_str(keys);
2069 char *str;
2070 char value[256];
2071 struct str_parms *reply = str_parms_create();
2072 size_t i, j;
2073 int ret;
2074 bool first = true;
Eric Laurent994a6932013-07-17 11:51:42 -07002075 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002076 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2077 if (ret >= 0) {
2078 value[0] = '\0';
2079 i = 0;
2080 while (out->supported_channel_masks[i] != 0) {
2081 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2082 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2083 if (!first) {
2084 strcat(value, "|");
2085 }
2086 strcat(value, out_channels_name_to_enum_table[j].name);
2087 first = false;
2088 break;
2089 }
2090 }
2091 i++;
2092 }
2093 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2094 str = str_parms_to_str(reply);
2095 } else {
2096 str = strdup(keys);
2097 }
2098 str_parms_destroy(query);
2099 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002100 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002101 return str;
2102}
2103
2104static uint32_t out_get_latency(const struct audio_stream_out *stream)
2105{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002106 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002107 struct stream_out *out = (struct stream_out *)stream;
2108
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002109 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2110 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002111 else if ((out->realtime) ||
2112 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002113 // since the buffer won't be filled up faster than realtime,
2114 // return a smaller number
2115 period_ms = (out->af_period_multiplier * out->config.period_size *
2116 1000) / (out->config.rate);
2117 hw_delay = platform_render_latency(out->usecase)/1000;
2118 return period_ms + hw_delay;
2119 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002120
2121 return (out->config.period_count * out->config.period_size * 1000) /
2122 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002123}
2124
2125static int out_set_volume(struct audio_stream_out *stream, float left,
2126 float right)
2127{
Eric Laurenta9024de2013-04-04 09:19:12 -07002128 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002129 int volume[2];
2130
Eric Laurenta9024de2013-04-04 09:19:12 -07002131 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2132 /* only take left channel into account: the API is for stereo anyway */
2133 out->muted = (left == 0.0f);
2134 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002135 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2136 const char *mixer_ctl_name = "Compress Playback Volume";
2137 struct audio_device *adev = out->dev;
2138 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002139 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2140 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002141 /* try with the control based on device id */
2142 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2143 PCM_PLAYBACK);
2144 char ctl_name[128] = {0};
2145 snprintf(ctl_name, sizeof(ctl_name),
2146 "Compress Playback %d Volume", pcm_device_id);
2147 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2148 if (!ctl) {
2149 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2150 return -EINVAL;
2151 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002152 }
2153 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2154 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2155 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2156 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002157 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002158
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002159 return -ENOSYS;
2160}
2161
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002162// note: this call is safe only if the stream_cb is
2163// removed first in close_output_stream (as is done now).
2164static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2165{
2166 if (!stream || !parms)
2167 return;
2168
2169 struct stream_out *out = (struct stream_out *)stream;
2170 struct audio_device *adev = out->dev;
2171
2172 card_status_t status;
2173 int card;
2174 if (parse_snd_card_status(parms, &card, &status) < 0)
2175 return;
2176
2177 pthread_mutex_lock(&adev->lock);
2178 bool valid_cb = (card == adev->snd_card);
2179 pthread_mutex_unlock(&adev->lock);
2180
2181 if (!valid_cb)
2182 return;
2183
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002184 lock_output_stream(out);
2185 if (out->card_status != status)
2186 out->card_status = status;
2187 pthread_mutex_unlock(&out->lock);
2188
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002189 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2190 use_case_table[out->usecase],
2191 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2192
2193 if (status == CARD_STATUS_OFFLINE)
2194 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002195
2196 return;
2197}
2198
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002199#ifdef NO_AUDIO_OUT
2200static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002201 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002202{
2203 struct stream_out *out = (struct stream_out *)stream;
2204
2205 /* No Output device supported other than BT for playback.
2206 * Sleep for the amount of buffer duration
2207 */
Eric Laurenta1478072015-09-21 17:21:52 -07002208 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002209 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2210 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002211 out_get_sample_rate(&out->stream.common));
2212 pthread_mutex_unlock(&out->lock);
2213 return bytes;
2214}
2215#endif
2216
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002217static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2218 size_t bytes)
2219{
2220 struct stream_out *out = (struct stream_out *)stream;
2221 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002222 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002223 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002224
Eric Laurenta1478072015-09-21 17:21:52 -07002225 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002226 // this is always nonzero
2227 const int frame_size = audio_stream_out_frame_size(stream);
2228
Eric Laurent0e46adf2016-12-16 12:49:24 -08002229 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2230 error_code = ERROR_CODE_WRITE;
2231 goto exit;
2232 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002233 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002234 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002235 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002236 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002237 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002238 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002239 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002240 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002241 goto exit;
2242 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002243
2244 if (last_known_cal_step != -1) {
2245 ALOGD("%s: retry previous failed cal level set", __func__);
2246 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2247 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002248 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002249
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002250 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002251 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002252 if (out->send_new_metadata) {
2253 ALOGVV("send new gapless metadata");
2254 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2255 out->send_new_metadata = 0;
2256 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002257 unsigned int avail;
2258 struct timespec tstamp;
2259 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2260 /* Do not limit write size if the available frames count is unknown */
2261 if (ret != 0) {
2262 avail = bytes;
2263 }
2264 if (avail == 0) {
2265 ret = 0;
2266 } else {
2267 if (avail > bytes) {
2268 avail = bytes;
2269 }
2270 ret = compress_write(out->compr, buffer, avail);
2271 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2272 __func__, avail, ret);
2273 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002274
Eric Laurent6e895242013-09-05 16:10:57 -07002275 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002276 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2277 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002278 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002279 compress_start(out->compr);
2280 out->playback_started = 1;
2281 out->offload_state = OFFLOAD_STATE_PLAYING;
2282 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002283 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002284 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002285 } else {
2286 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002287 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002288 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002289 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002290 return ret;
2291 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002292 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002293 if (out->pcm) {
2294 if (out->muted)
2295 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002296
Eric Laurent0e46adf2016-12-16 12:49:24 -08002297 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002298
Haynes Mathew George03c40102016-01-29 17:57:48 -08002299 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2300 out->config.rate;
2301 request_out_focus(out, ns);
2302
2303 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2304 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002305 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002306 else
2307 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002308
Haynes Mathew George03c40102016-01-29 17:57:48 -08002309 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002310 } else {
2311 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002312 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002313 }
2314
2315exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002316 // For PCM we always consume the buffer and return #bytes regardless of ret.
2317 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2318 out->written += bytes / (out->config.channels * sizeof(short));
2319 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002320 long long sleeptime_us = 0;
Andy Hungfc044e12017-03-20 09:24:22 -07002321 const int64_t now_ns = audio_utils_get_real_time_ns();
2322
Andy Hung7401c7c2016-09-21 12:41:21 -07002323 if (ret != 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002324 error_log_log(out->error_log, error_code, now_ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002325 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2326 ALOGE_IF(out->pcm != NULL,
2327 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hungfc044e12017-03-20 09:24:22 -07002328 sleeptime_us = bytes * 1000000LL / frame_size /
Andy Hung7401c7c2016-09-21 12:41:21 -07002329 out_get_sample_rate(&out->stream.common);
2330 // usleep not guaranteed for values over 1 second but we don't limit here.
2331 }
2332 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002333
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002334 pthread_mutex_unlock(&out->lock);
2335
2336 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002337 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002338 if (sleeptime_us != 0)
2339 usleep(sleeptime_us);
Andy Hungfc044e12017-03-20 09:24:22 -07002340 } else {
2341 // only log if the data is properly written (out->power_log may be null)
2342 power_log_log(out->power_log, buffer, bytes / frame_size, now_ns);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002343 }
2344 return bytes;
2345}
2346
2347static int out_get_render_position(const struct audio_stream_out *stream,
2348 uint32_t *dsp_frames)
2349{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002350 struct stream_out *out = (struct stream_out *)stream;
2351 *dsp_frames = 0;
2352 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002353 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002354 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002355 unsigned long frames = 0;
2356 // TODO: check return value
2357 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2358 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002359 ALOGVV("%s rendered frames %d sample_rate %d",
2360 __func__, *dsp_frames, out->sample_rate);
2361 }
2362 pthread_mutex_unlock(&out->lock);
2363 return 0;
2364 } else
2365 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002366}
2367
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002368static int out_add_audio_effect(const struct audio_stream *stream __unused,
2369 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002370{
2371 return 0;
2372}
2373
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002374static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2375 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002376{
2377 return 0;
2378}
2379
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002380static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2381 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002382{
2383 return -EINVAL;
2384}
2385
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002386static int out_get_presentation_position(const struct audio_stream_out *stream,
2387 uint64_t *frames, struct timespec *timestamp)
2388{
2389 struct stream_out *out = (struct stream_out *)stream;
Andy Hung7171da22016-03-08 16:58:42 -08002390 int ret = -EINVAL;
Eric Laurent949a0892013-09-20 09:20:13 -07002391 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002392
Eric Laurenta1478072015-09-21 17:21:52 -07002393 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002394
Eric Laurent949a0892013-09-20 09:20:13 -07002395 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2396 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002397 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002398 compress_get_tstamp(out->compr, &dsp_frames,
2399 &out->sample_rate);
2400 ALOGVV("%s rendered frames %ld sample_rate %d",
2401 __func__, dsp_frames, out->sample_rate);
2402 *frames = dsp_frames;
2403 ret = 0;
2404 /* this is the best we can do */
2405 clock_gettime(CLOCK_MONOTONIC, timestamp);
2406 }
2407 } else {
2408 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002409 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002410 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2411 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002412 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002413 // This adjustment accounts for buffering after app processor.
2414 // It is based on estimated DSP latency per use case, rather than exact.
2415 signed_frames -=
2416 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2417
Eric Laurent949a0892013-09-20 09:20:13 -07002418 // It would be unusual for this value to be negative, but check just in case ...
2419 if (signed_frames >= 0) {
2420 *frames = signed_frames;
2421 ret = 0;
2422 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002423 }
2424 }
2425 }
2426
2427 pthread_mutex_unlock(&out->lock);
2428
2429 return ret;
2430}
2431
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002432static int out_set_callback(struct audio_stream_out *stream,
2433 stream_callback_t callback, void *cookie)
2434{
2435 struct stream_out *out = (struct stream_out *)stream;
2436
2437 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002438 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002439 out->offload_callback = callback;
2440 out->offload_cookie = cookie;
2441 pthread_mutex_unlock(&out->lock);
2442 return 0;
2443}
2444
2445static int out_pause(struct audio_stream_out* stream)
2446{
2447 struct stream_out *out = (struct stream_out *)stream;
2448 int status = -ENOSYS;
2449 ALOGV("%s", __func__);
2450 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002451 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002452 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2453 status = compress_pause(out->compr);
2454 out->offload_state = OFFLOAD_STATE_PAUSED;
2455 }
2456 pthread_mutex_unlock(&out->lock);
2457 }
2458 return status;
2459}
2460
2461static int out_resume(struct audio_stream_out* stream)
2462{
2463 struct stream_out *out = (struct stream_out *)stream;
2464 int status = -ENOSYS;
2465 ALOGV("%s", __func__);
2466 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2467 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002468 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002469 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2470 status = compress_resume(out->compr);
2471 out->offload_state = OFFLOAD_STATE_PLAYING;
2472 }
2473 pthread_mutex_unlock(&out->lock);
2474 }
2475 return status;
2476}
2477
2478static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2479{
2480 struct stream_out *out = (struct stream_out *)stream;
2481 int status = -ENOSYS;
2482 ALOGV("%s", __func__);
2483 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002484 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002485 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2486 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2487 else
2488 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2489 pthread_mutex_unlock(&out->lock);
2490 }
2491 return status;
2492}
2493
2494static int out_flush(struct audio_stream_out* stream)
2495{
2496 struct stream_out *out = (struct stream_out *)stream;
2497 ALOGV("%s", __func__);
2498 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002499 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002500 stop_compressed_output_l(out);
2501 pthread_mutex_unlock(&out->lock);
2502 return 0;
2503 }
2504 return -ENOSYS;
2505}
2506
Eric Laurent0e46adf2016-12-16 12:49:24 -08002507static int out_stop(const struct audio_stream_out* stream)
2508{
2509 struct stream_out *out = (struct stream_out *)stream;
2510 struct audio_device *adev = out->dev;
2511 int ret = -ENOSYS;
2512
2513 ALOGV("%s", __func__);
2514 pthread_mutex_lock(&adev->lock);
2515 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2516 out->playback_started && out->pcm != NULL) {
2517 pcm_stop(out->pcm);
2518 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08002519 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002520 }
2521 pthread_mutex_unlock(&adev->lock);
2522 return ret;
2523}
2524
2525static int out_start(const struct audio_stream_out* stream)
2526{
2527 struct stream_out *out = (struct stream_out *)stream;
2528 struct audio_device *adev = out->dev;
2529 int ret = -ENOSYS;
2530
2531 ALOGV("%s", __func__);
2532 pthread_mutex_lock(&adev->lock);
2533 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2534 !out->playback_started && out->pcm != NULL) {
2535 ret = start_output_stream(out);
2536 if (ret == 0) {
2537 out->playback_started = true;
2538 }
2539 }
2540 pthread_mutex_unlock(&adev->lock);
2541 return ret;
2542}
2543
Phil Burkbc991042017-02-24 08:06:44 -08002544/*
2545 * Modify config->period_count based on min_size_frames
2546 */
2547static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
2548{
2549 int periodCountRequested = (min_size_frames + config->period_size - 1)
2550 / config->period_size;
2551 int periodCount = MMAP_PERIOD_COUNT_MIN;
2552
2553 ALOGV("%s original config.period_size = %d config.period_count = %d",
2554 __func__, config->period_size, config->period_count);
2555
2556 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
2557 periodCount *= 2;
2558 }
2559 config->period_count = periodCount;
2560
2561 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
2562}
2563
Eric Laurent0e46adf2016-12-16 12:49:24 -08002564static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2565 int32_t min_size_frames,
2566 struct audio_mmap_buffer_info *info)
2567{
2568 struct stream_out *out = (struct stream_out *)stream;
2569 struct audio_device *adev = out->dev;
2570 int ret = 0;
2571 unsigned int offset1;
2572 unsigned int frames1;
2573 const char *step = "";
2574
2575 ALOGV("%s", __func__);
2576 pthread_mutex_lock(&adev->lock);
2577
2578 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002579 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002580 ret = -EINVAL;
2581 goto exit;
2582 }
2583 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08002584 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002585 ret = -ENOSYS;
2586 goto exit;
2587 }
2588 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
2589 if (out->pcm_device_id < 0) {
2590 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2591 __func__, out->pcm_device_id, out->usecase);
2592 ret = -EINVAL;
2593 goto exit;
2594 }
Phil Burkbc991042017-02-24 08:06:44 -08002595
2596 adjust_mmap_period_count(&out->config, min_size_frames);
2597
Eric Laurent0e46adf2016-12-16 12:49:24 -08002598 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2599 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
2600 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2601 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
2602 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2603 step = "open";
2604 ret = -ENODEV;
2605 goto exit;
2606 }
2607 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
2608 if (ret < 0) {
2609 step = "begin";
2610 goto exit;
2611 }
2612 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
2613 info->burst_size_frames = out->config.period_size;
2614 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
2615
2616 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
2617 info->buffer_size_frames));
2618
2619 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
2620 if (ret < 0) {
2621 step = "commit";
2622 goto exit;
2623 }
Phil Burkbc991042017-02-24 08:06:44 -08002624
2625 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002626 ret = 0;
2627
2628 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
2629 __func__, info->shared_memory_address, info->buffer_size_frames);
2630
2631exit:
2632 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002633 if (out->pcm == NULL) {
2634 ALOGE("%s: %s - %d", __func__, step, ret);
2635 } else {
2636 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08002637 pcm_close(out->pcm);
2638 out->pcm = NULL;
2639 }
2640 }
2641 pthread_mutex_unlock(&adev->lock);
2642 return ret;
2643}
2644
2645static int out_get_mmap_position(const struct audio_stream_out *stream,
2646 struct audio_mmap_position *position)
2647{
2648 struct stream_out *out = (struct stream_out *)stream;
2649 ALOGVV("%s", __func__);
2650 if (position == NULL) {
2651 return -EINVAL;
2652 }
2653 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
2654 return -ENOSYS;
2655 }
2656 if (out->pcm == NULL) {
2657 return -ENOSYS;
2658 }
2659
2660 struct timespec ts = { 0, 0 };
2661 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
2662 if (ret < 0) {
2663 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2664 return ret;
2665 }
Andy Hungfc044e12017-03-20 09:24:22 -07002666 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002667 return 0;
2668}
2669
2670
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002671/** audio_stream_in implementation **/
2672static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2673{
2674 struct stream_in *in = (struct stream_in *)stream;
2675
2676 return in->config.rate;
2677}
2678
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002679static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002680{
2681 return -ENOSYS;
2682}
2683
2684static size_t in_get_buffer_size(const struct audio_stream *stream)
2685{
2686 struct stream_in *in = (struct stream_in *)stream;
2687
Haynes Mathew George03c40102016-01-29 17:57:48 -08002688 return in->config.period_size * in->af_period_multiplier *
2689 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002690}
2691
2692static uint32_t in_get_channels(const struct audio_stream *stream)
2693{
2694 struct stream_in *in = (struct stream_in *)stream;
2695
2696 return in->channel_mask;
2697}
2698
vivek mehta4ed66e62016-04-15 23:33:34 -07002699static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002700{
vivek mehta4ed66e62016-04-15 23:33:34 -07002701 struct stream_in *in = (struct stream_in *)stream;
2702 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002703}
2704
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002705static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002706{
2707 return -ENOSYS;
2708}
2709
2710static int in_standby(struct audio_stream *stream)
2711{
2712 struct stream_in *in = (struct stream_in *)stream;
2713 struct audio_device *adev = in->dev;
2714 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08002715 bool do_stop = true;
2716
Eric Laurent994a6932013-07-17 11:51:42 -07002717 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002718
2719 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002720
2721 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08002722 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002723 audio_extn_sound_trigger_stop_lab(in);
2724 in->standby = true;
2725 }
2726
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002727 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002728 if (adev->adm_deregister_stream)
2729 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2730
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002731 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002732 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002733 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002734 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002735 in->capture_started = false;
2736 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002737 if (in->pcm) {
2738 pcm_close(in->pcm);
2739 in->pcm = NULL;
2740 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002741 adev->enable_voicerx = false;
2742 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08002743 if (do_stop) {
2744 status = stop_input_stream(in);
2745 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002746 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002747 }
2748 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002749 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002750 return status;
2751}
2752
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002753static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002754{
2755 return 0;
2756}
2757
2758static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2759{
2760 struct stream_in *in = (struct stream_in *)stream;
2761 struct audio_device *adev = in->dev;
2762 struct str_parms *parms;
2763 char *str;
2764 char value[32];
2765 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07002766 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002767
Eric Laurent994a6932013-07-17 11:51:42 -07002768 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002769 parms = str_parms_create_str(kvpairs);
2770
2771 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2772
Eric Laurenta1478072015-09-21 17:21:52 -07002773 lock_input_stream(in);
2774
Eric Laurent150dbfe2013-02-27 14:31:02 -08002775 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002776 if (ret >= 0) {
2777 val = atoi(value);
2778 /* no audio source uses val == 0 */
2779 if ((in->source != val) && (val != 0)) {
2780 in->source = val;
2781 }
2782 }
2783
2784 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07002785
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002786 if (ret >= 0) {
2787 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002788 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002789 in->device = val;
2790 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002791 if (!in->standby) {
2792 ALOGV("update input routing change");
2793 in->routing_change = true;
2794 select_devices(adev, in->usecase);
2795 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002796 }
2797 }
2798
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002799 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002800 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002801
2802 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002803 ALOGV("%s: exit: status(%d)", __func__, status);
2804 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002805}
2806
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002807static char* in_get_parameters(const struct audio_stream *stream __unused,
2808 const char *keys __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002809{
2810 return strdup("");
2811}
2812
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002813static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002814{
2815 return 0;
2816}
2817
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002818static void in_snd_mon_cb(void * stream, struct str_parms * parms)
2819{
2820 if (!stream || !parms)
2821 return;
2822
2823 struct stream_in *in = (struct stream_in *)stream;
2824 struct audio_device *adev = in->dev;
2825
2826 card_status_t status;
2827 int card;
2828 if (parse_snd_card_status(parms, &card, &status) < 0)
2829 return;
2830
2831 pthread_mutex_lock(&adev->lock);
2832 bool valid_cb = (card == adev->snd_card);
2833 pthread_mutex_unlock(&adev->lock);
2834
2835 if (!valid_cb)
2836 return;
2837
2838 lock_input_stream(in);
2839 if (in->card_status != status)
2840 in->card_status = status;
2841 pthread_mutex_unlock(&in->lock);
2842
2843 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
2844 use_case_table[in->usecase],
2845 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2846
2847 // a better solution would be to report error back to AF and let
2848 // it put the stream to standby
2849 if (status == CARD_STATUS_OFFLINE)
2850 in_standby(&in->stream.common);
2851
2852 return;
2853}
2854
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002855static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2856 size_t bytes)
2857{
2858 struct stream_in *in = (struct stream_in *)stream;
2859 struct audio_device *adev = in->dev;
2860 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07002861 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002862
Eric Laurenta1478072015-09-21 17:21:52 -07002863 lock_input_stream(in);
2864
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002865 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002866 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002867 /* Read from sound trigger HAL */
2868 audio_extn_sound_trigger_read(in, buffer, bytes);
2869 pthread_mutex_unlock(&in->lock);
2870 return bytes;
2871 }
2872
Eric Laurent0e46adf2016-12-16 12:49:24 -08002873 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
2874 ret = -ENOSYS;
2875 goto exit;
2876 }
2877
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002878 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002879 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002880 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002881 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002882 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002883 goto exit;
2884 }
2885 in->standby = 0;
2886 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002887
Haynes Mathew George03c40102016-01-29 17:57:48 -08002888 //what's the duration requested by the client?
2889 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
2890 in->config.rate;
2891 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002892
Haynes Mathew George03c40102016-01-29 17:57:48 -08002893 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002894 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002895 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002896 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07002897 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002898 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002899 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002900 if (ret < 0) {
2901 ALOGE("Failed to read w/err %s", strerror(errno));
2902 ret = -errno;
2903 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002904 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
2905 if (bytes % 4 == 0) {
2906 /* data from DSP comes in 24_8 format, convert it to 8_24 */
2907 int_buf_stream = buffer;
2908 for (size_t itt=0; itt < bytes/4 ; itt++) {
2909 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07002910 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002911 } else {
2912 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
2913 ret = -EINVAL;
2914 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07002915 }
2916 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002917 }
2918
Haynes Mathew George03c40102016-01-29 17:57:48 -08002919 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002920
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002921 /*
2922 * Instead of writing zeroes here, we could trust the hardware
2923 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002924 * 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 -08002925 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002926 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002927 memset(buffer, 0, bytes);
2928
2929exit:
2930 pthread_mutex_unlock(&in->lock);
2931
2932 if (ret != 0) {
2933 in_standby(&in->stream.common);
2934 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Eric Laurentfdf296a2014-07-03 16:41:51 -07002935 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002936 in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08002937 memset(buffer, 0, bytes); // clear return data
2938 }
2939 if (bytes > 0) {
Andy Hung6ebe5962016-01-15 17:46:57 -08002940 in->frames_read += bytes / audio_stream_in_frame_size(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002941 }
2942 return bytes;
2943}
2944
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002945static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002946{
2947 return 0;
2948}
2949
Andy Hung6ebe5962016-01-15 17:46:57 -08002950static int in_get_capture_position(const struct audio_stream_in *stream,
2951 int64_t *frames, int64_t *time)
2952{
2953 if (stream == NULL || frames == NULL || time == NULL) {
2954 return -EINVAL;
2955 }
2956 struct stream_in *in = (struct stream_in *)stream;
2957 int ret = -ENOSYS;
2958
2959 lock_input_stream(in);
2960 if (in->pcm) {
2961 struct timespec timestamp;
2962 unsigned int avail;
2963 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
2964 *frames = in->frames_read + avail;
2965 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
2966 ret = 0;
2967 }
2968 }
2969 pthread_mutex_unlock(&in->lock);
2970 return ret;
2971}
2972
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002973static int add_remove_audio_effect(const struct audio_stream *stream,
2974 effect_handle_t effect,
2975 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002976{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002977 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002978 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002979 int status = 0;
2980 effect_descriptor_t desc;
2981
2982 status = (*effect)->get_descriptor(effect, &desc);
2983 if (status != 0)
2984 return status;
2985
Eric Laurenta1478072015-09-21 17:21:52 -07002986 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002987 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07002988 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07002989 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07002990 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002991 in->enable_aec != enable &&
2992 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2993 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002994 if (!enable)
2995 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07002996 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2997 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
2998 adev->enable_voicerx = enable;
2999 struct audio_usecase *usecase;
3000 struct listnode *node;
3001 list_for_each(node, &adev->usecase_list) {
3002 usecase = node_to_item(node, struct audio_usecase, list);
3003 if (usecase->type == PCM_PLAYBACK) {
3004 select_devices(adev, usecase->id);
3005 break;
3006 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003007 }
3008 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003009 if (!in->standby)
3010 select_devices(in->dev, in->usecase);
3011 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003012 if (in->enable_ns != enable &&
3013 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3014 in->enable_ns = enable;
3015 if (!in->standby)
3016 select_devices(in->dev, in->usecase);
3017 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003018 pthread_mutex_unlock(&in->dev->lock);
3019 pthread_mutex_unlock(&in->lock);
3020
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003021 return 0;
3022}
3023
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003024static int in_add_audio_effect(const struct audio_stream *stream,
3025 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003026{
Eric Laurent994a6932013-07-17 11:51:42 -07003027 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003028 return add_remove_audio_effect(stream, effect, true);
3029}
3030
3031static int in_remove_audio_effect(const struct audio_stream *stream,
3032 effect_handle_t effect)
3033{
Eric Laurent994a6932013-07-17 11:51:42 -07003034 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003035 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003036}
3037
Eric Laurent0e46adf2016-12-16 12:49:24 -08003038static int in_stop(const struct audio_stream_in* stream)
3039{
3040 struct stream_in *in = (struct stream_in *)stream;
3041 struct audio_device *adev = in->dev;
3042
3043 int ret = -ENOSYS;
3044 ALOGV("%s", __func__);
3045 pthread_mutex_lock(&adev->lock);
3046 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3047 in->capture_started && in->pcm != NULL) {
3048 pcm_stop(in->pcm);
3049 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003050 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003051 }
3052 pthread_mutex_unlock(&adev->lock);
3053 return ret;
3054}
3055
3056static int in_start(const struct audio_stream_in* stream)
3057{
3058 struct stream_in *in = (struct stream_in *)stream;
3059 struct audio_device *adev = in->dev;
3060 int ret = -ENOSYS;
3061
3062 ALOGV("%s in %p", __func__, in);
3063 pthread_mutex_lock(&adev->lock);
3064 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3065 !in->capture_started && in->pcm != NULL) {
3066 if (!in->capture_started) {
3067 ret = start_input_stream(in);
3068 if (ret == 0) {
3069 in->capture_started = true;
3070 }
3071 }
3072 }
3073 pthread_mutex_unlock(&adev->lock);
3074 return ret;
3075}
3076
3077static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3078 int32_t min_size_frames,
3079 struct audio_mmap_buffer_info *info)
3080{
3081 struct stream_in *in = (struct stream_in *)stream;
3082 struct audio_device *adev = in->dev;
3083 int ret = 0;
3084 unsigned int offset1;
3085 unsigned int frames1;
3086 const char *step = "";
3087
3088 pthread_mutex_lock(&adev->lock);
3089 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003090
Eric Laurent0e46adf2016-12-16 12:49:24 -08003091 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003092 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003093 ret = -EINVAL;
3094 goto exit;
3095 }
3096 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003097 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003098 ALOGV("%s in %p", __func__, in);
3099 ret = -ENOSYS;
3100 goto exit;
3101 }
3102 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3103 if (in->pcm_device_id < 0) {
3104 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3105 __func__, in->pcm_device_id, in->usecase);
3106 ret = -EINVAL;
3107 goto exit;
3108 }
Phil Burkbc991042017-02-24 08:06:44 -08003109
3110 adjust_mmap_period_count(&in->config, min_size_frames);
3111
Eric Laurent0e46adf2016-12-16 12:49:24 -08003112 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3113 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3114 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3115 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3116 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3117 step = "open";
3118 ret = -ENODEV;
3119 goto exit;
3120 }
3121
3122 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3123 if (ret < 0) {
3124 step = "begin";
3125 goto exit;
3126 }
3127 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
3128 info->burst_size_frames = in->config.period_size;
3129 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3130
3131 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(in->pcm,
3132 info->buffer_size_frames));
3133
3134 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3135 if (ret < 0) {
3136 step = "commit";
3137 goto exit;
3138 }
3139
Phil Burkbc991042017-02-24 08:06:44 -08003140 in->standby = false;
3141 ret = 0;
3142
Eric Laurent0e46adf2016-12-16 12:49:24 -08003143 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3144 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003145
3146exit:
3147 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003148 if (in->pcm == NULL) {
3149 ALOGE("%s: %s - %d", __func__, step, ret);
3150 } else {
3151 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003152 pcm_close(in->pcm);
3153 in->pcm = NULL;
3154 }
3155 }
3156 pthread_mutex_unlock(&adev->lock);
3157 return ret;
3158}
3159
3160static int in_get_mmap_position(const struct audio_stream_in *stream,
3161 struct audio_mmap_position *position)
3162{
3163 struct stream_in *in = (struct stream_in *)stream;
3164 ALOGVV("%s", __func__);
3165 if (position == NULL) {
3166 return -EINVAL;
3167 }
3168 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
3169 return -ENOSYS;
3170 }
3171 if (in->pcm == NULL) {
3172 return -ENOSYS;
3173 }
3174 struct timespec ts = { 0, 0 };
3175 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
3176 if (ret < 0) {
3177 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3178 return ret;
3179 }
Andy Hungfc044e12017-03-20 09:24:22 -07003180 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003181 return 0;
3182}
3183
3184
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003185static int adev_open_output_stream(struct audio_hw_device *dev,
3186 audio_io_handle_t handle,
3187 audio_devices_t devices,
3188 audio_output_flags_t flags,
3189 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003190 struct audio_stream_out **stream_out,
3191 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003192{
3193 struct audio_device *adev = (struct audio_device *)dev;
3194 struct stream_out *out;
3195 int i, ret;
3196
Eric Laurent994a6932013-07-17 11:51:42 -07003197 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003198 __func__, config->sample_rate, config->channel_mask, devices, flags);
3199 *stream_out = NULL;
3200 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3201
3202 if (devices == AUDIO_DEVICE_NONE)
3203 devices = AUDIO_DEVICE_OUT_SPEAKER;
3204
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003205 out->flags = flags;
3206 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003207 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003208 out->format = config->format;
3209 out->sample_rate = config->sample_rate;
3210 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3211 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003212 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003213
3214 /* Init use case and pcm_config */
3215 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
Eric Laurent7f245042013-09-30 19:22:50 -07003216 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003217 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003218 pthread_mutex_lock(&adev->lock);
3219 ret = read_hdmi_channel_masks(out);
3220 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003221 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003222 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003223
3224 if (config->sample_rate == 0)
3225 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3226 if (config->channel_mask == 0)
3227 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Eric Laurentad1cec22015-12-16 10:12:27 -08003228 if (config->format == AUDIO_FORMAT_DEFAULT)
3229 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003230
3231 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003232 out->sample_rate = config->sample_rate;
Eric Laurentad1cec22015-12-16 10:12:27 -08003233 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003234 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3235 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003236 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003237 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003238 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003239 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003240 pthread_mutex_lock(&adev->lock);
3241 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3242 pthread_mutex_unlock(&adev->lock);
3243
3244 // reject offload during card offline to allow
3245 // fallback to s/w paths
3246 if (offline) {
3247 ret = -ENODEV;
3248 goto error_open;
3249 }
3250
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003251 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3252 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3253 ALOGE("%s: Unsupported Offload information", __func__);
3254 ret = -EINVAL;
3255 goto error_open;
3256 }
3257 if (!is_supported_format(config->offload_info.format)) {
3258 ALOGE("%s: Unsupported audio format", __func__);
3259 ret = -EINVAL;
3260 goto error_open;
3261 }
3262
3263 out->compr_config.codec = (struct snd_codec *)
3264 calloc(1, sizeof(struct snd_codec));
3265
3266 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3267 if (config->offload_info.channel_mask)
3268 out->channel_mask = config->offload_info.channel_mask;
3269 else if (config->channel_mask)
3270 out->channel_mask = config->channel_mask;
3271 out->format = config->offload_info.format;
3272 out->sample_rate = config->offload_info.sample_rate;
3273
3274 out->stream.set_callback = out_set_callback;
3275 out->stream.pause = out_pause;
3276 out->stream.resume = out_resume;
3277 out->stream.drain = out_drain;
3278 out->stream.flush = out_flush;
3279
3280 out->compr_config.codec->id =
3281 get_snd_codec_id(config->offload_info.format);
3282 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3283 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07003284 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003285 out->compr_config.codec->bit_rate =
3286 config->offload_info.bit_rate;
3287 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003288 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003289 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3290
3291 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3292 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003293
3294 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003295 create_offload_callback_thread(out);
3296 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3297 __func__, config->offload_info.version,
3298 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003299 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3300 if (config->sample_rate == 0)
3301 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3302 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3303 config->sample_rate != 8000) {
3304 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3305 ret = -EINVAL;
3306 goto error_open;
3307 }
3308 out->sample_rate = config->sample_rate;
3309 out->config.rate = config->sample_rate;
3310 if (config->format == AUDIO_FORMAT_DEFAULT)
3311 config->format = AUDIO_FORMAT_PCM_16_BIT;
3312 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3313 config->format = AUDIO_FORMAT_PCM_16_BIT;
3314 ret = -EINVAL;
3315 goto error_open;
3316 }
3317 out->format = config->format;
3318 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3319 out->config = pcm_config_afe_proxy_playback;
3320 adev->voice_tx_output = out;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003321 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003322 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3323 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3324 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003325 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
3326 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3327 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003328 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3329 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003330 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003331 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003332 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3333 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3334 out->config = pcm_config_mmap_playback;
3335 out->stream.start = out_start;
3336 out->stream.stop = out_stop;
3337 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3338 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003339 } else {
3340 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3341 out->config = pcm_config_low_latency;
3342 }
3343 if (config->format != audio_format_from_pcm_format(out->config.format)) {
3344 if (k_enable_extended_precision
3345 && pcm_params_format_test(adev->use_case_table[out->usecase],
3346 pcm_format_from_audio_format(config->format))) {
3347 out->config.format = pcm_format_from_audio_format(config->format);
3348 /* out->format already set to config->format */
3349 } else {
3350 /* deny the externally proposed config format
3351 * and use the one specified in audio_hw layer configuration.
3352 * Note: out->format is returned by out->stream.common.get_format()
3353 * and is used to set config->format in the code several lines below.
3354 */
3355 out->format = audio_format_from_pcm_format(out->config.format);
3356 }
3357 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003358 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003359 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07003360 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3361 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003362
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003363 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003364 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003365 adev->primary_output = out;
3366 else {
3367 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003368 ret = -EEXIST;
3369 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003370 }
3371 }
3372
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003373 /* Check if this usecase is already existing */
3374 pthread_mutex_lock(&adev->lock);
3375 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3376 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003377 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003378 ret = -EEXIST;
3379 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003380 }
3381 pthread_mutex_unlock(&adev->lock);
3382
3383 out->stream.common.get_sample_rate = out_get_sample_rate;
3384 out->stream.common.set_sample_rate = out_set_sample_rate;
3385 out->stream.common.get_buffer_size = out_get_buffer_size;
3386 out->stream.common.get_channels = out_get_channels;
3387 out->stream.common.get_format = out_get_format;
3388 out->stream.common.set_format = out_set_format;
3389 out->stream.common.standby = out_standby;
3390 out->stream.common.dump = out_dump;
3391 out->stream.common.set_parameters = out_set_parameters;
3392 out->stream.common.get_parameters = out_get_parameters;
3393 out->stream.common.add_audio_effect = out_add_audio_effect;
3394 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3395 out->stream.get_latency = out_get_latency;
3396 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003397#ifdef NO_AUDIO_OUT
3398 out->stream.write = out_write_for_no_output;
3399#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003400 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003401#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003402 out->stream.get_render_position = out_get_render_position;
3403 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003404 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003405
Eric Laurent0e46adf2016-12-16 12:49:24 -08003406 if (out->realtime)
3407 out->af_period_multiplier = af_period_multiplier;
3408 else
3409 out->af_period_multiplier = 1;
3410
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003411 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003412 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003413 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003414
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003415 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003416 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003417 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3418
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003419 config->format = out->stream.common.get_format(&out->stream.common);
3420 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3421 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3422
Andy Hunga452b0a2017-03-15 14:51:15 -07003423 out->error_log = error_log_create(
3424 ERROR_LOG_ENTRIES,
3425 1000000000 /* aggregate consecutive identical errors within one second in ns */);
3426
Andy Hungfc044e12017-03-20 09:24:22 -07003427 const size_t POWER_LOG_FRAMES_PER_ENTRY =
3428 config->sample_rate * POWER_LOG_SAMPLING_INTERVAL_MS / 1000;
3429 // power_log may be null if the format is not supported
3430 out->power_log = power_log_create(
3431 config->sample_rate,
3432 audio_channel_count_from_out_mask(config->channel_mask),
3433 config->format,
3434 POWER_LOG_ENTRIES,
3435 POWER_LOG_FRAMES_PER_ENTRY);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003436
3437 /*
3438 By locking output stream before registering, we allow the callback
3439 to update stream's state only after stream's initial state is set to
3440 adev state.
3441 */
3442 lock_output_stream(out);
3443 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3444 pthread_mutex_lock(&adev->lock);
3445 out->card_status = adev->card_status;
3446 pthread_mutex_unlock(&adev->lock);
3447 pthread_mutex_unlock(&out->lock);
3448
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003449 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003450
Eric Laurent994a6932013-07-17 11:51:42 -07003451 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003452 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003453
3454error_open:
3455 free(out);
3456 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003457 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003458 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003459}
3460
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003461static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003462 struct audio_stream_out *stream)
3463{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003464 struct stream_out *out = (struct stream_out *)stream;
3465 struct audio_device *adev = out->dev;
3466
Eric Laurent994a6932013-07-17 11:51:42 -07003467 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003468
3469 // must deregister from sndmonitor first to prevent races
3470 // between the callback and close_stream
3471 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003472 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003473 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3474 destroy_offload_callback_thread(out);
3475
3476 if (out->compr_config.codec != NULL)
3477 free(out->compr_config.codec);
3478 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003479
3480 if (adev->voice_tx_output == out)
3481 adev->voice_tx_output = NULL;
3482
Andy Hungfc044e12017-03-20 09:24:22 -07003483 power_log_destroy(out->power_log);
3484 out->power_log = NULL;
3485
Andy Hunga452b0a2017-03-15 14:51:15 -07003486 error_log_destroy(out->error_log);
3487 out->error_log = NULL;
3488
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003489 pthread_cond_destroy(&out->cond);
3490 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003491 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003492 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003493}
3494
3495static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3496{
3497 struct audio_device *adev = (struct audio_device *)dev;
3498 struct str_parms *parms;
3499 char *str;
3500 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003501 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003502 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003503 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003504
Joe Onorato188b6222016-03-01 11:02:27 -08003505 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003506
3507 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003508
3509 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003510 status = voice_set_parameters(adev, parms);
3511 if (status != 0) {
3512 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003513 }
3514
3515 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3516 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003517 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003518 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3519 adev->bluetooth_nrec = true;
3520 else
3521 adev->bluetooth_nrec = false;
3522 }
3523
3524 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3525 if (ret >= 0) {
3526 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3527 adev->screen_off = false;
3528 else
3529 adev->screen_off = true;
3530 }
3531
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003532 ret = str_parms_get_int(parms, "rotation", &val);
3533 if (ret >= 0) {
3534 bool reverse_speakers = false;
3535 switch(val) {
3536 // FIXME: note that the code below assumes that the speakers are in the correct placement
3537 // relative to the user when the device is rotated 90deg from its default rotation. This
3538 // assumption is device-specific, not platform-specific like this code.
3539 case 270:
3540 reverse_speakers = true;
3541 break;
3542 case 0:
3543 case 90:
3544 case 180:
3545 break;
3546 default:
3547 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003548 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003549 }
Eric Laurent03f09432014-03-25 18:09:11 -07003550 if (status == 0) {
Ravi Kumar Alamanda1f60cf82015-04-23 19:45:17 -07003551 platform_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003552 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003553 }
3554
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003555 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3556 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003557 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003558 }
3559
David Linee3fe402017-03-13 10:00:42 -07003560 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3561 if (ret >= 0) {
3562 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
3563 if (device == AUDIO_DEVICE_OUT_USB_DEVICE) {
3564 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3565 if (ret >= 0) {
3566 const int card = atoi(value);
3567 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, card);
3568 }
3569 } else if (device == AUDIO_DEVICE_IN_USB_DEVICE) {
3570 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3571 if (ret >= 0) {
3572 const int card = atoi(value);
3573 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, card);
3574 }
3575 }
3576 }
3577
3578 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3579 if (ret >= 0) {
3580 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
3581 if (device == AUDIO_DEVICE_OUT_USB_DEVICE) {
3582 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3583 if (ret >= 0) {
3584 const int card = atoi(value);
3585
3586 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, card);
3587 }
3588 } else if (device == AUDIO_DEVICE_IN_USB_DEVICE) {
3589 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3590 if (ret >= 0) {
3591 const int card = atoi(value);
3592 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, card);
3593 }
3594 }
3595 }
3596
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08003597 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003598done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003599 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003600 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07003601 ALOGV("%s: exit with code(%d)", __func__, status);
3602 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003603}
3604
3605static char* adev_get_parameters(const struct audio_hw_device *dev,
3606 const char *keys)
3607{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003608 struct audio_device *adev = (struct audio_device *)dev;
3609 struct str_parms *reply = str_parms_create();
3610 struct str_parms *query = str_parms_create_str(keys);
3611 char *str;
3612
3613 pthread_mutex_lock(&adev->lock);
3614
3615 voice_get_parameters(adev, query, reply);
3616 str = str_parms_to_str(reply);
3617 str_parms_destroy(query);
3618 str_parms_destroy(reply);
3619
3620 pthread_mutex_unlock(&adev->lock);
3621 ALOGV("%s: exit: returns - %s", __func__, str);
3622 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003623}
3624
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003625static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003626{
3627 return 0;
3628}
3629
Haynes Mathew George5191a852013-09-11 14:19:36 -07003630static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3631{
3632 int ret;
3633 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003634
Eric Laurent4cc4ce12014-09-10 13:21:01 -05003635 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
3636
Haynes Mathew George5191a852013-09-11 14:19:36 -07003637 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003638 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003639 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003640
Haynes Mathew George5191a852013-09-11 14:19:36 -07003641 return ret;
3642}
3643
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003644static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003645{
3646 return -ENOSYS;
3647}
3648
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003649static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3650 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003651{
3652 return -ENOSYS;
3653}
3654
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003655static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003656{
3657 return -ENOSYS;
3658}
3659
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003660static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003661{
3662 return -ENOSYS;
3663}
3664
3665static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3666{
3667 struct audio_device *adev = (struct audio_device *)dev;
3668
3669 pthread_mutex_lock(&adev->lock);
3670 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07003671 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003672 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07003673 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3674 voice_is_in_call(adev)) {
3675 voice_stop_call(adev);
3676 adev->current_call_output = NULL;
3677 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003678 }
3679 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003680
3681 audio_extn_extspk_set_mode(adev->extspk, mode);
3682
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003683 return 0;
3684}
3685
3686static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3687{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003688 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003689 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003690
Eric Laurent2bafff12016-03-17 12:17:23 -07003691 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003692 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08003693 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
3694 ret = audio_extn_hfp_set_mic_mute(adev, state);
3695 } else {
3696 ret = voice_set_mic_mute(adev, state);
3697 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003698 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00003699 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003700
3701 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003702}
3703
3704static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3705{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003706 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003707 return 0;
3708}
3709
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003710static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003711 const struct audio_config *config)
3712{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003713 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003714
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003715 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3716 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003717}
3718
3719static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003720 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003721 audio_devices_t devices,
3722 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003723 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07003724 audio_input_flags_t flags,
3725 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05003726 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003727{
3728 struct audio_device *adev = (struct audio_device *)dev;
3729 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003730 int ret = 0, buffer_size, frame_size;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003731 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003732 bool is_low_latency = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003733
Eric Laurent994a6932013-07-17 11:51:42 -07003734 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003735 *stream_in = NULL;
3736 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3737 return -EINVAL;
3738
Zheng Zhang6185d572016-12-01 20:35:17 +08003739 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 -08003740 return -EINVAL;
3741
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003742 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
3743
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003744 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003745 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003746
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003747 in->stream.common.get_sample_rate = in_get_sample_rate;
3748 in->stream.common.set_sample_rate = in_set_sample_rate;
3749 in->stream.common.get_buffer_size = in_get_buffer_size;
3750 in->stream.common.get_channels = in_get_channels;
3751 in->stream.common.get_format = in_get_format;
3752 in->stream.common.set_format = in_set_format;
3753 in->stream.common.standby = in_standby;
3754 in->stream.common.dump = in_dump;
3755 in->stream.common.set_parameters = in_set_parameters;
3756 in->stream.common.get_parameters = in_get_parameters;
3757 in->stream.common.add_audio_effect = in_add_audio_effect;
3758 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3759 in->stream.set_gain = in_set_gain;
3760 in->stream.read = in_read;
3761 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08003762 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003763
3764 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003765 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003766 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003767 in->standby = 1;
3768 in->channel_mask = config->channel_mask;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003769 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003770 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003771
vivek mehta57ff9b52016-04-28 14:13:08 -07003772 // restrict 24 bit capture for unprocessed source only
3773 // for other sources if 24 bit requested reject 24 and set 16 bit capture only
3774 if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07003775 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07003776 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
3777 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
3778 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
3779 bool ret_error = false;
3780 /* 24 bit is restricted to UNPROCESSED source only,also format supported
3781 from HAL is 8_24
3782 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
3783 8_24 return error indicating supported format is 8_24
3784 *> In case of any other source requesting 24 bit or float return error
3785 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07003786
vivek mehta57ff9b52016-04-28 14:13:08 -07003787 on error flinger will retry with supported format passed
3788 */
3789 if (source != AUDIO_SOURCE_UNPROCESSED) {
3790 config->format = AUDIO_FORMAT_PCM_16_BIT;
3791 ret_error = true;
3792 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
3793 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
3794 ret_error = true;
3795 }
3796
3797 if (ret_error) {
3798 ret = -EINVAL;
3799 goto err_open;
3800 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003801 }
3802
vivek mehta57ff9b52016-04-28 14:13:08 -07003803 in->format = config->format;
3804
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003805 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003806 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
3807 if (config->sample_rate == 0)
3808 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3809 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3810 config->sample_rate != 8000) {
3811 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3812 ret = -EINVAL;
3813 goto err_open;
3814 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003815
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003816 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3817 config->format = AUDIO_FORMAT_PCM_16_BIT;
3818 ret = -EINVAL;
3819 goto err_open;
3820 }
3821
3822 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3823 in->config = pcm_config_afe_proxy_record;
David Lin73f45252017-03-29 13:37:33 -07003824 in->af_period_multiplier = 1;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003825 } else {
3826 in->usecase = USECASE_AUDIO_RECORD;
3827 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08003828 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003829 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07003830#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003831 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07003832#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08003833 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003834 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08003835 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003836 frame_size = audio_stream_in_frame_size(&in->stream);
3837 buffer_size = get_input_buffer_size(config->sample_rate,
3838 config->format,
3839 channel_count,
3840 is_low_latency);
3841 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003842 in->config.rate = config->sample_rate;
3843 in->af_period_multiplier = 1;
3844 } else {
3845 // period size is left untouched for rt mode playback
3846 in->config = pcm_config_audio_capture_rt;
3847 in->af_period_multiplier = af_period_multiplier;
3848 }
3849 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
3850 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
3851 in->usecase = USECASE_AUDIO_RECORD_MMAP;
3852 in->config = pcm_config_mmap_capture;
3853 in->stream.start = in_start;
3854 in->stream.stop = in_stop;
3855 in->stream.create_mmap_buffer = in_create_mmap_buffer;
3856 in->stream.get_mmap_position = in_get_mmap_position;
3857 in->af_period_multiplier = 1;
3858 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
3859 } else {
3860 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003861 frame_size = audio_stream_in_frame_size(&in->stream);
3862 buffer_size = get_input_buffer_size(config->sample_rate,
3863 config->format,
3864 channel_count,
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003865 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003866 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003867 in->config.rate = config->sample_rate;
3868 in->af_period_multiplier = 1;
3869 }
3870 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
3871 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003872 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003873
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003874 in->config.channels = channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003875
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003876 /* This stream could be for sound trigger lab,
3877 get sound trigger pcm if present */
3878 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003879
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003880 lock_input_stream(in);
3881 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
3882 pthread_mutex_lock(&adev->lock);
3883 in->card_status = adev->card_status;
3884 pthread_mutex_unlock(&adev->lock);
3885 pthread_mutex_unlock(&in->lock);
3886
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003887 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003888 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003889 return 0;
3890
3891err_open:
3892 free(in);
3893 *stream_in = NULL;
3894 return ret;
3895}
3896
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003897static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003898 struct audio_stream_in *stream)
3899{
Eric Laurent994a6932013-07-17 11:51:42 -07003900 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003901
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003902 // must deregister from sndmonitor first to prevent races
3903 // between the callback and close_stream
3904 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003905 in_standby(&stream->common);
3906 free(stream);
3907
3908 return;
3909}
3910
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003911static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003912{
3913 return 0;
3914}
3915
Andy Hung31aca912014-03-20 17:14:59 -07003916/* verifies input and output devices and their capabilities.
3917 *
3918 * This verification is required when enabling extended bit-depth or
3919 * sampling rates, as not all qcom products support it.
3920 *
3921 * Suitable for calling only on initialization such as adev_open().
3922 * It fills the audio_device use_case_table[] array.
3923 *
3924 * Has a side-effect that it needs to configure audio routing / devices
3925 * in order to power up the devices and read the device parameters.
3926 * It does not acquire any hw device lock. Should restore the devices
3927 * back to "normal state" upon completion.
3928 */
3929static int adev_verify_devices(struct audio_device *adev)
3930{
3931 /* enumeration is a bit difficult because one really wants to pull
3932 * the use_case, device id, etc from the hidden pcm_device_table[].
3933 * In this case there are the following use cases and device ids.
3934 *
3935 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
3936 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
3937 * [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
3938 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
3939 * [USECASE_AUDIO_RECORD] = {0, 0},
3940 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
3941 * [USECASE_VOICE_CALL] = {2, 2},
3942 *
3943 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_MULTI_CH omitted.
3944 * USECASE_VOICE_CALL omitted, but possible for either input or output.
3945 */
3946
3947 /* should be the usecases enabled in adev_open_input_stream() */
3948 static const int test_in_usecases[] = {
3949 USECASE_AUDIO_RECORD,
3950 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
3951 };
3952 /* should be the usecases enabled in adev_open_output_stream()*/
3953 static const int test_out_usecases[] = {
3954 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
3955 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
3956 };
3957 static const usecase_type_t usecase_type_by_dir[] = {
3958 PCM_PLAYBACK,
3959 PCM_CAPTURE,
3960 };
3961 static const unsigned flags_by_dir[] = {
3962 PCM_OUT,
3963 PCM_IN,
3964 };
3965
3966 size_t i;
3967 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003968 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07003969 char info[512]; /* for possible debug info */
3970
3971 for (dir = 0; dir < 2; ++dir) {
3972 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
3973 const unsigned flags_dir = flags_by_dir[dir];
3974 const size_t testsize =
3975 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
3976 const int *testcases =
3977 dir ? test_in_usecases : test_out_usecases;
3978 const audio_devices_t audio_device =
3979 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
3980
3981 for (i = 0; i < testsize; ++i) {
3982 const audio_usecase_t audio_usecase = testcases[i];
3983 int device_id;
3984 snd_device_t snd_device;
3985 struct pcm_params **pparams;
3986 struct stream_out out;
3987 struct stream_in in;
3988 struct audio_usecase uc_info;
3989 int retval;
3990
3991 pparams = &adev->use_case_table[audio_usecase];
3992 pcm_params_free(*pparams); /* can accept null input */
3993 *pparams = NULL;
3994
3995 /* find the device ID for the use case (signed, for error) */
3996 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
3997 if (device_id < 0)
3998 continue;
3999
4000 /* prepare structures for device probing */
4001 memset(&uc_info, 0, sizeof(uc_info));
4002 uc_info.id = audio_usecase;
4003 uc_info.type = usecase_type;
4004 if (dir) {
4005 adev->active_input = &in;
4006 memset(&in, 0, sizeof(in));
4007 in.device = audio_device;
4008 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4009 uc_info.stream.in = &in;
4010 } else {
4011 adev->active_input = NULL;
4012 }
4013 memset(&out, 0, sizeof(out));
4014 out.devices = audio_device; /* only field needed in select_devices */
4015 uc_info.stream.out = &out;
4016 uc_info.devices = audio_device;
4017 uc_info.in_snd_device = SND_DEVICE_NONE;
4018 uc_info.out_snd_device = SND_DEVICE_NONE;
4019 list_add_tail(&adev->usecase_list, &uc_info.list);
4020
4021 /* select device - similar to start_(in/out)put_stream() */
4022 retval = select_devices(adev, audio_usecase);
4023 if (retval >= 0) {
4024 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4025#if LOG_NDEBUG == 0
4026 if (*pparams) {
4027 ALOGV("%s: (%s) card %d device %d", __func__,
4028 dir ? "input" : "output", card_id, device_id);
4029 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004030 } else {
4031 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4032 }
4033#endif
4034 }
4035
4036 /* deselect device - similar to stop_(in/out)put_stream() */
4037 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004038 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004039 /* 2. Disable the rx device */
4040 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004041 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004042 list_remove(&uc_info.list);
4043 }
4044 }
4045 adev->active_input = NULL; /* restore adev state */
4046 return 0;
4047}
4048
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004049static int adev_close(hw_device_t *device)
4050{
Andy Hung31aca912014-03-20 17:14:59 -07004051 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004052 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004053
4054 if (!adev)
4055 return 0;
4056
Kevin Rocard8342c2c2017-04-07 18:50:00 -07004057 audio_extn_snd_mon_deinit();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004058 audio_extn_tfa_98xx_deinit();
4059
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004060 audio_extn_snd_mon_unregister_listener(adev);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004061 pthread_mutex_lock(&adev_init_lock);
4062
4063 if ((--audio_device_ref_count) == 0) {
4064 audio_route_free(adev->audio_route);
4065 free(adev->snd_dev_ref_cnt);
4066 platform_deinit(adev->platform);
4067 audio_extn_extspk_deinit(adev->extspk);
4068 audio_extn_sound_trigger_deinit(adev);
4069 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4070 pcm_params_free(adev->use_case_table[i]);
4071 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004072 if (adev->adm_deinit)
4073 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004074 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004075 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004076
4077 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004078
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004079 return 0;
4080}
4081
Glenn Kasten4f993392014-05-14 07:30:48 -07004082/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4083 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4084 * just that it _might_ work.
4085 */
4086static int period_size_is_plausible_for_low_latency(int period_size)
4087{
4088 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004089 case 48:
4090 case 96:
4091 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004092 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004093 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004094 case 240:
4095 case 320:
4096 case 480:
4097 return 1;
4098 default:
4099 return 0;
4100 }
4101}
4102
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004103static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4104{
4105 int card;
4106 card_status_t status;
4107
4108 if (!parms)
4109 return;
4110
4111 if (parse_snd_card_status(parms, &card, &status) < 0)
4112 return;
4113
4114 pthread_mutex_lock(&adev->lock);
4115 bool valid_cb = (card == adev->snd_card);
4116 if (valid_cb) {
4117 if (adev->card_status != status) {
4118 adev->card_status = status;
4119 platform_snd_card_update(adev->platform, status);
4120 }
4121 }
4122 pthread_mutex_unlock(&adev->lock);
4123 return;
4124}
4125
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004126static int adev_open(const hw_module_t *module, const char *name,
4127 hw_device_t **device)
4128{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004129 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004130
Eric Laurent2bafff12016-03-17 12:17:23 -07004131 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004132 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004133 pthread_mutex_lock(&adev_init_lock);
4134 if (audio_device_ref_count != 0) {
4135 *device = &adev->device.common;
4136 audio_device_ref_count++;
4137 ALOGV("%s: returning existing instance of adev", __func__);
4138 ALOGV("%s: exit", __func__);
4139 pthread_mutex_unlock(&adev_init_lock);
4140 return 0;
4141 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004142 adev = calloc(1, sizeof(struct audio_device));
4143
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004144 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4145
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004146 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4147 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4148 adev->device.common.module = (struct hw_module_t *)module;
4149 adev->device.common.close = adev_close;
4150
4151 adev->device.init_check = adev_init_check;
4152 adev->device.set_voice_volume = adev_set_voice_volume;
4153 adev->device.set_master_volume = adev_set_master_volume;
4154 adev->device.get_master_volume = adev_get_master_volume;
4155 adev->device.set_master_mute = adev_set_master_mute;
4156 adev->device.get_master_mute = adev_get_master_mute;
4157 adev->device.set_mode = adev_set_mode;
4158 adev->device.set_mic_mute = adev_set_mic_mute;
4159 adev->device.get_mic_mute = adev_get_mic_mute;
4160 adev->device.set_parameters = adev_set_parameters;
4161 adev->device.get_parameters = adev_get_parameters;
4162 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4163 adev->device.open_output_stream = adev_open_output_stream;
4164 adev->device.close_output_stream = adev_close_output_stream;
4165 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004166
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004167 adev->device.close_input_stream = adev_close_input_stream;
4168 adev->device.dump = adev_dump;
4169
4170 /* Set the default route before the PCM stream is opened */
4171 pthread_mutex_lock(&adev->lock);
4172 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004173 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004174 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004175 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004176 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004177 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004178 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004179 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004180 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004181 pthread_mutex_unlock(&adev->lock);
4182
4183 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004184 adev->platform = platform_init(adev);
4185 if (!adev->platform) {
4186 free(adev->snd_dev_ref_cnt);
4187 free(adev);
4188 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4189 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004190 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004191 return -EINVAL;
4192 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05004193 adev->extspk = audio_extn_extspk_init(adev);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004194 audio_extn_sound_trigger_init(adev);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004195
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004196 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4197 if (adev->visualizer_lib == NULL) {
4198 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4199 } else {
4200 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4201 adev->visualizer_start_output =
4202 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4203 "visualizer_hal_start_output");
4204 adev->visualizer_stop_output =
4205 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4206 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07004207 }
4208
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004209 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4210 if (adev->offload_effects_lib == NULL) {
4211 ALOGW("%s: DLOPEN failed for %s", __func__,
4212 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4213 } else {
4214 ALOGV("%s: DLOPEN successful for %s", __func__,
4215 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4216 adev->offload_effects_start_output =
4217 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4218 "offload_effects_bundle_hal_start_output");
4219 adev->offload_effects_stop_output =
4220 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4221 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07004222 }
4223
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004224 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4225 if (adev->adm_lib == NULL) {
4226 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4227 } else {
4228 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4229 adev->adm_init = (adm_init_t)
4230 dlsym(adev->adm_lib, "adm_init");
4231 adev->adm_deinit = (adm_deinit_t)
4232 dlsym(adev->adm_lib, "adm_deinit");
4233 adev->adm_register_input_stream = (adm_register_input_stream_t)
4234 dlsym(adev->adm_lib, "adm_register_input_stream");
4235 adev->adm_register_output_stream = (adm_register_output_stream_t)
4236 dlsym(adev->adm_lib, "adm_register_output_stream");
4237 adev->adm_deregister_stream = (adm_deregister_stream_t)
4238 dlsym(adev->adm_lib, "adm_deregister_stream");
4239 adev->adm_request_focus = (adm_request_focus_t)
4240 dlsym(adev->adm_lib, "adm_request_focus");
4241 adev->adm_abandon_focus = (adm_abandon_focus_t)
4242 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08004243 adev->adm_set_config = (adm_set_config_t)
4244 dlsym(adev->adm_lib, "adm_set_config");
4245 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4246 dlsym(adev->adm_lib, "adm_request_focus_v2");
4247 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4248 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4249 adev->adm_on_routing_change = (adm_on_routing_change_t)
4250 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004251 }
4252
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004253 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004254 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004255
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004256 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004257
Andy Hung31aca912014-03-20 17:14:59 -07004258 if (k_enable_extended_precision)
4259 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004260
Glenn Kasten4f993392014-05-14 07:30:48 -07004261 char value[PROPERTY_VALUE_MAX];
4262 int trial;
4263 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4264 trial = atoi(value);
4265 if (period_size_is_plausible_for_low_latency(trial)) {
4266 pcm_config_low_latency.period_size = trial;
4267 pcm_config_low_latency.start_threshold = trial / 4;
4268 pcm_config_low_latency.avail_min = trial / 4;
4269 configured_low_latency_capture_period_size = trial;
4270 }
4271 }
4272 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4273 trial = atoi(value);
4274 if (period_size_is_plausible_for_low_latency(trial)) {
4275 configured_low_latency_capture_period_size = trial;
4276 }
4277 }
4278
Yamit Mehtae3b99562016-09-16 22:44:00 +05304279 audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004280 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004281
4282 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4283 af_period_multiplier = atoi(value);
4284 if (af_period_multiplier < 0) {
4285 af_period_multiplier = 2;
4286 } else if (af_period_multiplier > 4) {
4287 af_period_multiplier = 4;
4288 }
4289 ALOGV("new period_multiplier = %d", af_period_multiplier);
4290 }
4291
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004292 audio_extn_tfa_98xx_init(adev);
4293
vivek mehta1a9b7c02015-06-25 11:49:38 -07004294 pthread_mutex_unlock(&adev_init_lock);
4295
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004296 if (adev->adm_init)
4297 adev->adm_data = adev->adm_init();
4298
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004299 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004300 audio_extn_snd_mon_init();
4301 pthread_mutex_lock(&adev->lock);
4302 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
4303 adev->card_status = CARD_STATUS_ONLINE;
4304 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004305
Eric Laurent2bafff12016-03-17 12:17:23 -07004306 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004307 return 0;
4308}
4309
4310static struct hw_module_methods_t hal_module_methods = {
4311 .open = adev_open,
4312};
4313
4314struct audio_module HAL_MODULE_INFO_SYM = {
4315 .common = {
4316 .tag = HARDWARE_MODULE_TAG,
4317 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4318 .hal_api_version = HARDWARE_HAL_API_VERSION,
4319 .id = AUDIO_HARDWARE_MODULE_ID,
4320 .name = "QCOM Audio HAL",
4321 .author = "Code Aurora Forum",
4322 .methods = &hal_module_methods,
4323 },
4324};