blob: badc8897e69215daeaa40a834b75020000ac9354 [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)
1928 (void)power_log_dump(out->power_log, fd, POWER_LOG_LINES, 0 /* limitNs */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001929 return 0;
1930}
1931
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001932static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1933{
1934 int ret = 0;
1935 char value[32];
1936 struct compr_gapless_mdata tmp_mdata;
1937
1938 if (!out || !parms) {
1939 return -EINVAL;
1940 }
1941
1942 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1943 if (ret >= 0) {
1944 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
1945 } else {
1946 return -EINVAL;
1947 }
1948
1949 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1950 if (ret >= 0) {
1951 tmp_mdata.encoder_padding = atoi(value);
1952 } else {
1953 return -EINVAL;
1954 }
1955
1956 out->gapless_mdata = tmp_mdata;
1957 out->send_new_metadata = 1;
1958 ALOGV("%s new encoder delay %u and padding %u", __func__,
1959 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1960
1961 return 0;
1962}
1963
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001964static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1965{
1966 return out == adev->primary_output || out == adev->voice_tx_output;
1967}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001968
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001969static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1970{
1971 struct stream_out *out = (struct stream_out *)stream;
1972 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001973 struct audio_usecase *usecase;
1974 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001975 struct str_parms *parms;
1976 char value[32];
1977 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001978 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07001979 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001980
Eric Laurent2e140aa2016-06-30 17:14:46 -07001981 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001982 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001983 parms = str_parms_create_str(kvpairs);
1984 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1985 if (ret >= 0) {
1986 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07001987 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001988 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001989
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001990 /*
1991 * When HDMI cable is unplugged the music playback is paused and
1992 * the policy manager sends routing=0. But the audioflinger
1993 * continues to write data until standby time (3sec).
1994 * As the HDMI core is turned off, the write gets blocked.
1995 * Avoid this by routing audio to speaker until standby.
1996 */
1997 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
1998 val == AUDIO_DEVICE_NONE) {
1999 val = AUDIO_DEVICE_OUT_SPEAKER;
2000 }
2001
2002 /*
2003 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002004 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002005 * the select_devices(). But how do we undo this?
2006 *
2007 * For example, music playback is active on headset (deep-buffer usecase)
2008 * and if we go to ringtones and select a ringtone, low-latency usecase
2009 * will be started on headset+speaker. As we can't enable headset+speaker
2010 * and headset devices at the same time, select_devices() switches the music
2011 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2012 * So when the ringtone playback is completed, how do we undo the same?
2013 *
2014 * We are relying on the out_set_parameters() call on deep-buffer output,
2015 * once the ringtone playback is ended.
2016 * NOTE: We should not check if the current devices are same as new devices.
2017 * Because select_devices() must be called to switch back the music
2018 * playback to headset.
2019 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002020 audio_devices_t new_dev = val;
2021 if (new_dev != AUDIO_DEVICE_NONE) {
2022 bool same_dev = out->devices == new_dev;
2023 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002024
Eric Laurenta7657192014-10-09 21:09:33 -07002025 if (output_drives_call(adev, out)) {
2026 if (!voice_is_in_call(adev)) {
2027 if (adev->mode == AUDIO_MODE_IN_CALL) {
2028 adev->current_call_output = out;
2029 ret = voice_start_call(adev);
2030 }
2031 } else {
2032 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002033 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002034 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002035 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002036
2037 if (!out->standby) {
2038 if (!same_dev) {
2039 ALOGV("update routing change");
2040 out->routing_change = true;
2041 }
2042 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002043 audio_extn_tfa_98xx_update();
vivek mehta0d3637a2016-07-24 09:32:02 -07002044 }
2045
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002046 }
2047
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002048 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002049 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002050
2051 /*handles device and call state changes*/
2052 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002053 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002054
2055 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2056 parse_compress_metadata(out, parms);
2057 }
2058
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002059 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002060 ALOGV("%s: exit: code(%d)", __func__, status);
2061 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002062}
2063
2064static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2065{
2066 struct stream_out *out = (struct stream_out *)stream;
2067 struct str_parms *query = str_parms_create_str(keys);
2068 char *str;
2069 char value[256];
2070 struct str_parms *reply = str_parms_create();
2071 size_t i, j;
2072 int ret;
2073 bool first = true;
Eric Laurent994a6932013-07-17 11:51:42 -07002074 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002075 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2076 if (ret >= 0) {
2077 value[0] = '\0';
2078 i = 0;
2079 while (out->supported_channel_masks[i] != 0) {
2080 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2081 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2082 if (!first) {
2083 strcat(value, "|");
2084 }
2085 strcat(value, out_channels_name_to_enum_table[j].name);
2086 first = false;
2087 break;
2088 }
2089 }
2090 i++;
2091 }
2092 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2093 str = str_parms_to_str(reply);
2094 } else {
2095 str = strdup(keys);
2096 }
2097 str_parms_destroy(query);
2098 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002099 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002100 return str;
2101}
2102
2103static uint32_t out_get_latency(const struct audio_stream_out *stream)
2104{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002105 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002106 struct stream_out *out = (struct stream_out *)stream;
2107
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002108 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2109 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002110 else if ((out->realtime) ||
2111 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002112 // since the buffer won't be filled up faster than realtime,
2113 // return a smaller number
2114 period_ms = (out->af_period_multiplier * out->config.period_size *
2115 1000) / (out->config.rate);
2116 hw_delay = platform_render_latency(out->usecase)/1000;
2117 return period_ms + hw_delay;
2118 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002119
2120 return (out->config.period_count * out->config.period_size * 1000) /
2121 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002122}
2123
2124static int out_set_volume(struct audio_stream_out *stream, float left,
2125 float right)
2126{
Eric Laurenta9024de2013-04-04 09:19:12 -07002127 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002128 int volume[2];
2129
Eric Laurenta9024de2013-04-04 09:19:12 -07002130 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2131 /* only take left channel into account: the API is for stereo anyway */
2132 out->muted = (left == 0.0f);
2133 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002134 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2135 const char *mixer_ctl_name = "Compress Playback Volume";
2136 struct audio_device *adev = out->dev;
2137 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002138 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2139 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002140 /* try with the control based on device id */
2141 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2142 PCM_PLAYBACK);
2143 char ctl_name[128] = {0};
2144 snprintf(ctl_name, sizeof(ctl_name),
2145 "Compress Playback %d Volume", pcm_device_id);
2146 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2147 if (!ctl) {
2148 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2149 return -EINVAL;
2150 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002151 }
2152 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2153 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2154 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2155 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002156 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002157
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002158 return -ENOSYS;
2159}
2160
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002161// note: this call is safe only if the stream_cb is
2162// removed first in close_output_stream (as is done now).
2163static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2164{
2165 if (!stream || !parms)
2166 return;
2167
2168 struct stream_out *out = (struct stream_out *)stream;
2169 struct audio_device *adev = out->dev;
2170
2171 card_status_t status;
2172 int card;
2173 if (parse_snd_card_status(parms, &card, &status) < 0)
2174 return;
2175
2176 pthread_mutex_lock(&adev->lock);
2177 bool valid_cb = (card == adev->snd_card);
2178 pthread_mutex_unlock(&adev->lock);
2179
2180 if (!valid_cb)
2181 return;
2182
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002183 lock_output_stream(out);
2184 if (out->card_status != status)
2185 out->card_status = status;
2186 pthread_mutex_unlock(&out->lock);
2187
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002188 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2189 use_case_table[out->usecase],
2190 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2191
2192 if (status == CARD_STATUS_OFFLINE)
2193 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002194
2195 return;
2196}
2197
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002198#ifdef NO_AUDIO_OUT
2199static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002200 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002201{
2202 struct stream_out *out = (struct stream_out *)stream;
2203
2204 /* No Output device supported other than BT for playback.
2205 * Sleep for the amount of buffer duration
2206 */
Eric Laurenta1478072015-09-21 17:21:52 -07002207 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002208 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2209 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002210 out_get_sample_rate(&out->stream.common));
2211 pthread_mutex_unlock(&out->lock);
2212 return bytes;
2213}
2214#endif
2215
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002216static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2217 size_t bytes)
2218{
2219 struct stream_out *out = (struct stream_out *)stream;
2220 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002221 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002222 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002223
Eric Laurenta1478072015-09-21 17:21:52 -07002224 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002225 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2226 error_code = ERROR_CODE_WRITE;
2227 goto exit;
2228 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002229 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002230 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002231 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002232 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002233 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002234 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002235 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002236 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002237 goto exit;
2238 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002239
2240 if (last_known_cal_step != -1) {
2241 ALOGD("%s: retry previous failed cal level set", __func__);
2242 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2243 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002244 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002245
Andy Hungfc044e12017-03-20 09:24:22 -07002246 // this is always nonzero
2247 const size_t frame_size = audio_stream_out_frame_size(stream);
2248
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002249 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002250 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002251 if (out->send_new_metadata) {
2252 ALOGVV("send new gapless metadata");
2253 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2254 out->send_new_metadata = 0;
2255 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002256 unsigned int avail;
2257 struct timespec tstamp;
2258 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2259 /* Do not limit write size if the available frames count is unknown */
2260 if (ret != 0) {
2261 avail = bytes;
2262 }
2263 if (avail == 0) {
2264 ret = 0;
2265 } else {
2266 if (avail > bytes) {
2267 avail = bytes;
2268 }
2269 ret = compress_write(out->compr, buffer, avail);
2270 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2271 __func__, avail, ret);
2272 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002273
Eric Laurent6e895242013-09-05 16:10:57 -07002274 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002275 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2276 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002277 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002278 compress_start(out->compr);
2279 out->playback_started = 1;
2280 out->offload_state = OFFLOAD_STATE_PLAYING;
2281 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002282 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002283 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07002284 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002285 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002286 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002287 return ret;
2288 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002289 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002290 if (out->pcm) {
2291 if (out->muted)
2292 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002293
Eric Laurent0e46adf2016-12-16 12:49:24 -08002294 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002295
Haynes Mathew George03c40102016-01-29 17:57:48 -08002296 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2297 out->config.rate;
2298 request_out_focus(out, ns);
2299
2300 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2301 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002302 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002303 else
2304 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002305
Haynes Mathew George03c40102016-01-29 17:57:48 -08002306 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002307 } else {
2308 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002309 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002310 }
2311
2312exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002313 // For PCM we always consume the buffer and return #bytes regardless of ret.
2314 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2315 out->written += bytes / (out->config.channels * sizeof(short));
2316 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002317 long long sleeptime_us = 0;
Andy Hungfc044e12017-03-20 09:24:22 -07002318 const int64_t now_ns = audio_utils_get_real_time_ns();
2319
Andy Hung7401c7c2016-09-21 12:41:21 -07002320 if (ret != 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002321 error_log_log(out->error_log, error_code, now_ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002322 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2323 ALOGE_IF(out->pcm != NULL,
2324 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hungfc044e12017-03-20 09:24:22 -07002325 sleeptime_us = bytes * 1000000LL / frame_size /
Andy Hung7401c7c2016-09-21 12:41:21 -07002326 out_get_sample_rate(&out->stream.common);
2327 // usleep not guaranteed for values over 1 second but we don't limit here.
2328 }
2329 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002330
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002331 pthread_mutex_unlock(&out->lock);
2332
2333 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002334 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002335 if (sleeptime_us != 0)
2336 usleep(sleeptime_us);
Andy Hungfc044e12017-03-20 09:24:22 -07002337 } else {
2338 // only log if the data is properly written (out->power_log may be null)
2339 power_log_log(out->power_log, buffer, bytes / frame_size, now_ns);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002340 }
2341 return bytes;
2342}
2343
2344static int out_get_render_position(const struct audio_stream_out *stream,
2345 uint32_t *dsp_frames)
2346{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002347 struct stream_out *out = (struct stream_out *)stream;
2348 *dsp_frames = 0;
2349 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002350 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002351 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002352 unsigned long frames = 0;
2353 // TODO: check return value
2354 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2355 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002356 ALOGVV("%s rendered frames %d sample_rate %d",
2357 __func__, *dsp_frames, out->sample_rate);
2358 }
2359 pthread_mutex_unlock(&out->lock);
2360 return 0;
2361 } else
2362 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002363}
2364
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002365static int out_add_audio_effect(const struct audio_stream *stream __unused,
2366 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002367{
2368 return 0;
2369}
2370
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002371static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2372 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002373{
2374 return 0;
2375}
2376
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002377static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2378 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002379{
2380 return -EINVAL;
2381}
2382
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002383static int out_get_presentation_position(const struct audio_stream_out *stream,
2384 uint64_t *frames, struct timespec *timestamp)
2385{
2386 struct stream_out *out = (struct stream_out *)stream;
Andy Hung7171da22016-03-08 16:58:42 -08002387 int ret = -EINVAL;
Eric Laurent949a0892013-09-20 09:20:13 -07002388 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002389
Eric Laurenta1478072015-09-21 17:21:52 -07002390 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002391
Eric Laurent949a0892013-09-20 09:20:13 -07002392 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2393 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002394 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002395 compress_get_tstamp(out->compr, &dsp_frames,
2396 &out->sample_rate);
2397 ALOGVV("%s rendered frames %ld sample_rate %d",
2398 __func__, dsp_frames, out->sample_rate);
2399 *frames = dsp_frames;
2400 ret = 0;
2401 /* this is the best we can do */
2402 clock_gettime(CLOCK_MONOTONIC, timestamp);
2403 }
2404 } else {
2405 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002406 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002407 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2408 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002409 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002410 // This adjustment accounts for buffering after app processor.
2411 // It is based on estimated DSP latency per use case, rather than exact.
2412 signed_frames -=
2413 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2414
Eric Laurent949a0892013-09-20 09:20:13 -07002415 // It would be unusual for this value to be negative, but check just in case ...
2416 if (signed_frames >= 0) {
2417 *frames = signed_frames;
2418 ret = 0;
2419 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002420 }
2421 }
2422 }
2423
2424 pthread_mutex_unlock(&out->lock);
2425
2426 return ret;
2427}
2428
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002429static int out_set_callback(struct audio_stream_out *stream,
2430 stream_callback_t callback, void *cookie)
2431{
2432 struct stream_out *out = (struct stream_out *)stream;
2433
2434 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002435 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002436 out->offload_callback = callback;
2437 out->offload_cookie = cookie;
2438 pthread_mutex_unlock(&out->lock);
2439 return 0;
2440}
2441
2442static int out_pause(struct audio_stream_out* stream)
2443{
2444 struct stream_out *out = (struct stream_out *)stream;
2445 int status = -ENOSYS;
2446 ALOGV("%s", __func__);
2447 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002448 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002449 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2450 status = compress_pause(out->compr);
2451 out->offload_state = OFFLOAD_STATE_PAUSED;
2452 }
2453 pthread_mutex_unlock(&out->lock);
2454 }
2455 return status;
2456}
2457
2458static int out_resume(struct audio_stream_out* stream)
2459{
2460 struct stream_out *out = (struct stream_out *)stream;
2461 int status = -ENOSYS;
2462 ALOGV("%s", __func__);
2463 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2464 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002465 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002466 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2467 status = compress_resume(out->compr);
2468 out->offload_state = OFFLOAD_STATE_PLAYING;
2469 }
2470 pthread_mutex_unlock(&out->lock);
2471 }
2472 return status;
2473}
2474
2475static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2476{
2477 struct stream_out *out = (struct stream_out *)stream;
2478 int status = -ENOSYS;
2479 ALOGV("%s", __func__);
2480 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002481 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002482 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2483 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2484 else
2485 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2486 pthread_mutex_unlock(&out->lock);
2487 }
2488 return status;
2489}
2490
2491static int out_flush(struct audio_stream_out* stream)
2492{
2493 struct stream_out *out = (struct stream_out *)stream;
2494 ALOGV("%s", __func__);
2495 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002496 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002497 stop_compressed_output_l(out);
2498 pthread_mutex_unlock(&out->lock);
2499 return 0;
2500 }
2501 return -ENOSYS;
2502}
2503
Eric Laurent0e46adf2016-12-16 12:49:24 -08002504static int out_stop(const struct audio_stream_out* stream)
2505{
2506 struct stream_out *out = (struct stream_out *)stream;
2507 struct audio_device *adev = out->dev;
2508 int ret = -ENOSYS;
2509
2510 ALOGV("%s", __func__);
2511 pthread_mutex_lock(&adev->lock);
2512 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2513 out->playback_started && out->pcm != NULL) {
2514 pcm_stop(out->pcm);
2515 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08002516 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002517 }
2518 pthread_mutex_unlock(&adev->lock);
2519 return ret;
2520}
2521
2522static int out_start(const struct audio_stream_out* stream)
2523{
2524 struct stream_out *out = (struct stream_out *)stream;
2525 struct audio_device *adev = out->dev;
2526 int ret = -ENOSYS;
2527
2528 ALOGV("%s", __func__);
2529 pthread_mutex_lock(&adev->lock);
2530 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2531 !out->playback_started && out->pcm != NULL) {
2532 ret = start_output_stream(out);
2533 if (ret == 0) {
2534 out->playback_started = true;
2535 }
2536 }
2537 pthread_mutex_unlock(&adev->lock);
2538 return ret;
2539}
2540
Phil Burkbc991042017-02-24 08:06:44 -08002541/*
2542 * Modify config->period_count based on min_size_frames
2543 */
2544static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
2545{
2546 int periodCountRequested = (min_size_frames + config->period_size - 1)
2547 / config->period_size;
2548 int periodCount = MMAP_PERIOD_COUNT_MIN;
2549
2550 ALOGV("%s original config.period_size = %d config.period_count = %d",
2551 __func__, config->period_size, config->period_count);
2552
2553 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
2554 periodCount *= 2;
2555 }
2556 config->period_count = periodCount;
2557
2558 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
2559}
2560
Eric Laurent0e46adf2016-12-16 12:49:24 -08002561static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2562 int32_t min_size_frames,
2563 struct audio_mmap_buffer_info *info)
2564{
2565 struct stream_out *out = (struct stream_out *)stream;
2566 struct audio_device *adev = out->dev;
2567 int ret = 0;
2568 unsigned int offset1;
2569 unsigned int frames1;
2570 const char *step = "";
2571
2572 ALOGV("%s", __func__);
2573 pthread_mutex_lock(&adev->lock);
2574
2575 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002576 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002577 ret = -EINVAL;
2578 goto exit;
2579 }
2580 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08002581 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002582 ret = -ENOSYS;
2583 goto exit;
2584 }
2585 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
2586 if (out->pcm_device_id < 0) {
2587 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2588 __func__, out->pcm_device_id, out->usecase);
2589 ret = -EINVAL;
2590 goto exit;
2591 }
Phil Burkbc991042017-02-24 08:06:44 -08002592
2593 adjust_mmap_period_count(&out->config, min_size_frames);
2594
Eric Laurent0e46adf2016-12-16 12:49:24 -08002595 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2596 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
2597 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2598 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
2599 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2600 step = "open";
2601 ret = -ENODEV;
2602 goto exit;
2603 }
2604 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
2605 if (ret < 0) {
2606 step = "begin";
2607 goto exit;
2608 }
2609 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
2610 info->burst_size_frames = out->config.period_size;
2611 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
2612
2613 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
2614 info->buffer_size_frames));
2615
2616 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
2617 if (ret < 0) {
2618 step = "commit";
2619 goto exit;
2620 }
Phil Burkbc991042017-02-24 08:06:44 -08002621
2622 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002623 ret = 0;
2624
2625 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
2626 __func__, info->shared_memory_address, info->buffer_size_frames);
2627
2628exit:
2629 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002630 if (out->pcm == NULL) {
2631 ALOGE("%s: %s - %d", __func__, step, ret);
2632 } else {
2633 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08002634 pcm_close(out->pcm);
2635 out->pcm = NULL;
2636 }
2637 }
2638 pthread_mutex_unlock(&adev->lock);
2639 return ret;
2640}
2641
2642static int out_get_mmap_position(const struct audio_stream_out *stream,
2643 struct audio_mmap_position *position)
2644{
2645 struct stream_out *out = (struct stream_out *)stream;
2646 ALOGVV("%s", __func__);
2647 if (position == NULL) {
2648 return -EINVAL;
2649 }
2650 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
2651 return -ENOSYS;
2652 }
2653 if (out->pcm == NULL) {
2654 return -ENOSYS;
2655 }
2656
2657 struct timespec ts = { 0, 0 };
2658 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
2659 if (ret < 0) {
2660 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2661 return ret;
2662 }
Andy Hungfc044e12017-03-20 09:24:22 -07002663 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002664 return 0;
2665}
2666
2667
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002668/** audio_stream_in implementation **/
2669static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2670{
2671 struct stream_in *in = (struct stream_in *)stream;
2672
2673 return in->config.rate;
2674}
2675
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002676static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002677{
2678 return -ENOSYS;
2679}
2680
2681static size_t in_get_buffer_size(const struct audio_stream *stream)
2682{
2683 struct stream_in *in = (struct stream_in *)stream;
2684
Haynes Mathew George03c40102016-01-29 17:57:48 -08002685 return in->config.period_size * in->af_period_multiplier *
2686 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002687}
2688
2689static uint32_t in_get_channels(const struct audio_stream *stream)
2690{
2691 struct stream_in *in = (struct stream_in *)stream;
2692
2693 return in->channel_mask;
2694}
2695
vivek mehta4ed66e62016-04-15 23:33:34 -07002696static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002697{
vivek mehta4ed66e62016-04-15 23:33:34 -07002698 struct stream_in *in = (struct stream_in *)stream;
2699 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002700}
2701
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002702static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002703{
2704 return -ENOSYS;
2705}
2706
2707static int in_standby(struct audio_stream *stream)
2708{
2709 struct stream_in *in = (struct stream_in *)stream;
2710 struct audio_device *adev = in->dev;
2711 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08002712 bool do_stop = true;
2713
Eric Laurent994a6932013-07-17 11:51:42 -07002714 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002715
2716 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002717
2718 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08002719 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002720 audio_extn_sound_trigger_stop_lab(in);
2721 in->standby = true;
2722 }
2723
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002724 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002725 if (adev->adm_deregister_stream)
2726 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2727
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002728 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002729 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002730 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002731 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002732 in->capture_started = false;
2733 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002734 if (in->pcm) {
2735 pcm_close(in->pcm);
2736 in->pcm = NULL;
2737 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002738 adev->enable_voicerx = false;
2739 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08002740 if (do_stop) {
2741 status = stop_input_stream(in);
2742 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002743 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002744 }
2745 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002746 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002747 return status;
2748}
2749
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002750static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002751{
2752 return 0;
2753}
2754
2755static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2756{
2757 struct stream_in *in = (struct stream_in *)stream;
2758 struct audio_device *adev = in->dev;
2759 struct str_parms *parms;
2760 char *str;
2761 char value[32];
2762 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07002763 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002764
Eric Laurent994a6932013-07-17 11:51:42 -07002765 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002766 parms = str_parms_create_str(kvpairs);
2767
2768 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2769
Eric Laurenta1478072015-09-21 17:21:52 -07002770 lock_input_stream(in);
2771
Eric Laurent150dbfe2013-02-27 14:31:02 -08002772 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002773 if (ret >= 0) {
2774 val = atoi(value);
2775 /* no audio source uses val == 0 */
2776 if ((in->source != val) && (val != 0)) {
2777 in->source = val;
2778 }
2779 }
2780
2781 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07002782
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002783 if (ret >= 0) {
2784 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002785 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002786 in->device = val;
2787 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002788 if (!in->standby) {
2789 ALOGV("update input routing change");
2790 in->routing_change = true;
2791 select_devices(adev, in->usecase);
2792 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002793 }
2794 }
2795
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002796 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002797 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002798
2799 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002800 ALOGV("%s: exit: status(%d)", __func__, status);
2801 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002802}
2803
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002804static char* in_get_parameters(const struct audio_stream *stream __unused,
2805 const char *keys __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002806{
2807 return strdup("");
2808}
2809
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002810static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002811{
2812 return 0;
2813}
2814
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002815static void in_snd_mon_cb(void * stream, struct str_parms * parms)
2816{
2817 if (!stream || !parms)
2818 return;
2819
2820 struct stream_in *in = (struct stream_in *)stream;
2821 struct audio_device *adev = in->dev;
2822
2823 card_status_t status;
2824 int card;
2825 if (parse_snd_card_status(parms, &card, &status) < 0)
2826 return;
2827
2828 pthread_mutex_lock(&adev->lock);
2829 bool valid_cb = (card == adev->snd_card);
2830 pthread_mutex_unlock(&adev->lock);
2831
2832 if (!valid_cb)
2833 return;
2834
2835 lock_input_stream(in);
2836 if (in->card_status != status)
2837 in->card_status = status;
2838 pthread_mutex_unlock(&in->lock);
2839
2840 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
2841 use_case_table[in->usecase],
2842 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2843
2844 // a better solution would be to report error back to AF and let
2845 // it put the stream to standby
2846 if (status == CARD_STATUS_OFFLINE)
2847 in_standby(&in->stream.common);
2848
2849 return;
2850}
2851
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002852static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2853 size_t bytes)
2854{
2855 struct stream_in *in = (struct stream_in *)stream;
2856 struct audio_device *adev = in->dev;
2857 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07002858 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002859
Eric Laurenta1478072015-09-21 17:21:52 -07002860 lock_input_stream(in);
2861
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002862 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002863 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002864 /* Read from sound trigger HAL */
2865 audio_extn_sound_trigger_read(in, buffer, bytes);
2866 pthread_mutex_unlock(&in->lock);
2867 return bytes;
2868 }
2869
Eric Laurent0e46adf2016-12-16 12:49:24 -08002870 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
2871 ret = -ENOSYS;
2872 goto exit;
2873 }
2874
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002875 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002876 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002877 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002878 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002879 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002880 goto exit;
2881 }
2882 in->standby = 0;
2883 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002884
Haynes Mathew George03c40102016-01-29 17:57:48 -08002885 //what's the duration requested by the client?
2886 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
2887 in->config.rate;
2888 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002889
Haynes Mathew George03c40102016-01-29 17:57:48 -08002890 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002891 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002892 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002893 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07002894 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002895 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002896 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002897 if (ret < 0) {
2898 ALOGE("Failed to read w/err %s", strerror(errno));
2899 ret = -errno;
2900 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002901 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
2902 if (bytes % 4 == 0) {
2903 /* data from DSP comes in 24_8 format, convert it to 8_24 */
2904 int_buf_stream = buffer;
2905 for (size_t itt=0; itt < bytes/4 ; itt++) {
2906 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07002907 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002908 } else {
2909 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
2910 ret = -EINVAL;
2911 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07002912 }
2913 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002914 }
2915
Haynes Mathew George03c40102016-01-29 17:57:48 -08002916 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002917
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002918 /*
2919 * Instead of writing zeroes here, we could trust the hardware
2920 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002921 * 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 -08002922 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002923 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002924 memset(buffer, 0, bytes);
2925
2926exit:
2927 pthread_mutex_unlock(&in->lock);
2928
2929 if (ret != 0) {
2930 in_standby(&in->stream.common);
2931 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Eric Laurentfdf296a2014-07-03 16:41:51 -07002932 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002933 in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08002934 memset(buffer, 0, bytes); // clear return data
2935 }
2936 if (bytes > 0) {
Andy Hung6ebe5962016-01-15 17:46:57 -08002937 in->frames_read += bytes / audio_stream_in_frame_size(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002938 }
2939 return bytes;
2940}
2941
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002942static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002943{
2944 return 0;
2945}
2946
Andy Hung6ebe5962016-01-15 17:46:57 -08002947static int in_get_capture_position(const struct audio_stream_in *stream,
2948 int64_t *frames, int64_t *time)
2949{
2950 if (stream == NULL || frames == NULL || time == NULL) {
2951 return -EINVAL;
2952 }
2953 struct stream_in *in = (struct stream_in *)stream;
2954 int ret = -ENOSYS;
2955
2956 lock_input_stream(in);
2957 if (in->pcm) {
2958 struct timespec timestamp;
2959 unsigned int avail;
2960 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
2961 *frames = in->frames_read + avail;
2962 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
2963 ret = 0;
2964 }
2965 }
2966 pthread_mutex_unlock(&in->lock);
2967 return ret;
2968}
2969
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002970static int add_remove_audio_effect(const struct audio_stream *stream,
2971 effect_handle_t effect,
2972 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002973{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002974 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002975 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002976 int status = 0;
2977 effect_descriptor_t desc;
2978
2979 status = (*effect)->get_descriptor(effect, &desc);
2980 if (status != 0)
2981 return status;
2982
Eric Laurenta1478072015-09-21 17:21:52 -07002983 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002984 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07002985 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07002986 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07002987 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002988 in->enable_aec != enable &&
2989 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2990 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002991 if (!enable)
2992 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07002993 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2994 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
2995 adev->enable_voicerx = enable;
2996 struct audio_usecase *usecase;
2997 struct listnode *node;
2998 list_for_each(node, &adev->usecase_list) {
2999 usecase = node_to_item(node, struct audio_usecase, list);
3000 if (usecase->type == PCM_PLAYBACK) {
3001 select_devices(adev, usecase->id);
3002 break;
3003 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003004 }
3005 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003006 if (!in->standby)
3007 select_devices(in->dev, in->usecase);
3008 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003009 if (in->enable_ns != enable &&
3010 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3011 in->enable_ns = enable;
3012 if (!in->standby)
3013 select_devices(in->dev, in->usecase);
3014 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003015 pthread_mutex_unlock(&in->dev->lock);
3016 pthread_mutex_unlock(&in->lock);
3017
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003018 return 0;
3019}
3020
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003021static int in_add_audio_effect(const struct audio_stream *stream,
3022 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003023{
Eric Laurent994a6932013-07-17 11:51:42 -07003024 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003025 return add_remove_audio_effect(stream, effect, true);
3026}
3027
3028static int in_remove_audio_effect(const struct audio_stream *stream,
3029 effect_handle_t effect)
3030{
Eric Laurent994a6932013-07-17 11:51:42 -07003031 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003032 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003033}
3034
Eric Laurent0e46adf2016-12-16 12:49:24 -08003035static int in_stop(const struct audio_stream_in* stream)
3036{
3037 struct stream_in *in = (struct stream_in *)stream;
3038 struct audio_device *adev = in->dev;
3039
3040 int ret = -ENOSYS;
3041 ALOGV("%s", __func__);
3042 pthread_mutex_lock(&adev->lock);
3043 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3044 in->capture_started && in->pcm != NULL) {
3045 pcm_stop(in->pcm);
3046 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003047 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003048 }
3049 pthread_mutex_unlock(&adev->lock);
3050 return ret;
3051}
3052
3053static int in_start(const struct audio_stream_in* stream)
3054{
3055 struct stream_in *in = (struct stream_in *)stream;
3056 struct audio_device *adev = in->dev;
3057 int ret = -ENOSYS;
3058
3059 ALOGV("%s in %p", __func__, in);
3060 pthread_mutex_lock(&adev->lock);
3061 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3062 !in->capture_started && in->pcm != NULL) {
3063 if (!in->capture_started) {
3064 ret = start_input_stream(in);
3065 if (ret == 0) {
3066 in->capture_started = true;
3067 }
3068 }
3069 }
3070 pthread_mutex_unlock(&adev->lock);
3071 return ret;
3072}
3073
3074static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3075 int32_t min_size_frames,
3076 struct audio_mmap_buffer_info *info)
3077{
3078 struct stream_in *in = (struct stream_in *)stream;
3079 struct audio_device *adev = in->dev;
3080 int ret = 0;
3081 unsigned int offset1;
3082 unsigned int frames1;
3083 const char *step = "";
3084
3085 pthread_mutex_lock(&adev->lock);
3086 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003087
Eric Laurent0e46adf2016-12-16 12:49:24 -08003088 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003089 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003090 ret = -EINVAL;
3091 goto exit;
3092 }
3093 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003094 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003095 ALOGV("%s in %p", __func__, in);
3096 ret = -ENOSYS;
3097 goto exit;
3098 }
3099 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3100 if (in->pcm_device_id < 0) {
3101 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3102 __func__, in->pcm_device_id, in->usecase);
3103 ret = -EINVAL;
3104 goto exit;
3105 }
Phil Burkbc991042017-02-24 08:06:44 -08003106
3107 adjust_mmap_period_count(&in->config, min_size_frames);
3108
Eric Laurent0e46adf2016-12-16 12:49:24 -08003109 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3110 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3111 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3112 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3113 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3114 step = "open";
3115 ret = -ENODEV;
3116 goto exit;
3117 }
3118
3119 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3120 if (ret < 0) {
3121 step = "begin";
3122 goto exit;
3123 }
3124 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
3125 info->burst_size_frames = in->config.period_size;
3126 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3127
3128 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(in->pcm,
3129 info->buffer_size_frames));
3130
3131 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3132 if (ret < 0) {
3133 step = "commit";
3134 goto exit;
3135 }
3136
Phil Burkbc991042017-02-24 08:06:44 -08003137 in->standby = false;
3138 ret = 0;
3139
Eric Laurent0e46adf2016-12-16 12:49:24 -08003140 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3141 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003142
3143exit:
3144 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003145 if (in->pcm == NULL) {
3146 ALOGE("%s: %s - %d", __func__, step, ret);
3147 } else {
3148 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003149 pcm_close(in->pcm);
3150 in->pcm = NULL;
3151 }
3152 }
3153 pthread_mutex_unlock(&adev->lock);
3154 return ret;
3155}
3156
3157static int in_get_mmap_position(const struct audio_stream_in *stream,
3158 struct audio_mmap_position *position)
3159{
3160 struct stream_in *in = (struct stream_in *)stream;
3161 ALOGVV("%s", __func__);
3162 if (position == NULL) {
3163 return -EINVAL;
3164 }
3165 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
3166 return -ENOSYS;
3167 }
3168 if (in->pcm == NULL) {
3169 return -ENOSYS;
3170 }
3171 struct timespec ts = { 0, 0 };
3172 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
3173 if (ret < 0) {
3174 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3175 return ret;
3176 }
Andy Hungfc044e12017-03-20 09:24:22 -07003177 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003178 return 0;
3179}
3180
3181
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003182static int adev_open_output_stream(struct audio_hw_device *dev,
3183 audio_io_handle_t handle,
3184 audio_devices_t devices,
3185 audio_output_flags_t flags,
3186 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003187 struct audio_stream_out **stream_out,
3188 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003189{
3190 struct audio_device *adev = (struct audio_device *)dev;
3191 struct stream_out *out;
3192 int i, ret;
3193
Eric Laurent994a6932013-07-17 11:51:42 -07003194 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003195 __func__, config->sample_rate, config->channel_mask, devices, flags);
3196 *stream_out = NULL;
3197 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3198
3199 if (devices == AUDIO_DEVICE_NONE)
3200 devices = AUDIO_DEVICE_OUT_SPEAKER;
3201
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003202 out->flags = flags;
3203 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003204 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003205 out->format = config->format;
3206 out->sample_rate = config->sample_rate;
3207 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3208 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003209 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003210
3211 /* Init use case and pcm_config */
3212 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
Eric Laurent7f245042013-09-30 19:22:50 -07003213 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003214 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003215 pthread_mutex_lock(&adev->lock);
3216 ret = read_hdmi_channel_masks(out);
3217 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003218 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003219 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003220
3221 if (config->sample_rate == 0)
3222 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3223 if (config->channel_mask == 0)
3224 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Eric Laurentad1cec22015-12-16 10:12:27 -08003225 if (config->format == AUDIO_FORMAT_DEFAULT)
3226 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003227
3228 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003229 out->sample_rate = config->sample_rate;
Eric Laurentad1cec22015-12-16 10:12:27 -08003230 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003231 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3232 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003233 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003234 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003235 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003236 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003237 pthread_mutex_lock(&adev->lock);
3238 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3239 pthread_mutex_unlock(&adev->lock);
3240
3241 // reject offload during card offline to allow
3242 // fallback to s/w paths
3243 if (offline) {
3244 ret = -ENODEV;
3245 goto error_open;
3246 }
3247
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003248 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3249 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3250 ALOGE("%s: Unsupported Offload information", __func__);
3251 ret = -EINVAL;
3252 goto error_open;
3253 }
3254 if (!is_supported_format(config->offload_info.format)) {
3255 ALOGE("%s: Unsupported audio format", __func__);
3256 ret = -EINVAL;
3257 goto error_open;
3258 }
3259
3260 out->compr_config.codec = (struct snd_codec *)
3261 calloc(1, sizeof(struct snd_codec));
3262
3263 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3264 if (config->offload_info.channel_mask)
3265 out->channel_mask = config->offload_info.channel_mask;
3266 else if (config->channel_mask)
3267 out->channel_mask = config->channel_mask;
3268 out->format = config->offload_info.format;
3269 out->sample_rate = config->offload_info.sample_rate;
3270
3271 out->stream.set_callback = out_set_callback;
3272 out->stream.pause = out_pause;
3273 out->stream.resume = out_resume;
3274 out->stream.drain = out_drain;
3275 out->stream.flush = out_flush;
3276
3277 out->compr_config.codec->id =
3278 get_snd_codec_id(config->offload_info.format);
3279 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3280 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07003281 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003282 out->compr_config.codec->bit_rate =
3283 config->offload_info.bit_rate;
3284 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003285 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003286 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3287
3288 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3289 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003290
3291 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003292 create_offload_callback_thread(out);
3293 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3294 __func__, config->offload_info.version,
3295 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003296 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3297 if (config->sample_rate == 0)
3298 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3299 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3300 config->sample_rate != 8000) {
3301 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3302 ret = -EINVAL;
3303 goto error_open;
3304 }
3305 out->sample_rate = config->sample_rate;
3306 out->config.rate = config->sample_rate;
3307 if (config->format == AUDIO_FORMAT_DEFAULT)
3308 config->format = AUDIO_FORMAT_PCM_16_BIT;
3309 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3310 config->format = AUDIO_FORMAT_PCM_16_BIT;
3311 ret = -EINVAL;
3312 goto error_open;
3313 }
3314 out->format = config->format;
3315 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3316 out->config = pcm_config_afe_proxy_playback;
3317 adev->voice_tx_output = out;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003318 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003319 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3320 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3321 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003322 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
3323 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3324 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003325 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3326 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003327 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003328 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003329 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3330 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3331 out->config = pcm_config_mmap_playback;
3332 out->stream.start = out_start;
3333 out->stream.stop = out_stop;
3334 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3335 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003336 } else {
3337 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3338 out->config = pcm_config_low_latency;
3339 }
3340 if (config->format != audio_format_from_pcm_format(out->config.format)) {
3341 if (k_enable_extended_precision
3342 && pcm_params_format_test(adev->use_case_table[out->usecase],
3343 pcm_format_from_audio_format(config->format))) {
3344 out->config.format = pcm_format_from_audio_format(config->format);
3345 /* out->format already set to config->format */
3346 } else {
3347 /* deny the externally proposed config format
3348 * and use the one specified in audio_hw layer configuration.
3349 * Note: out->format is returned by out->stream.common.get_format()
3350 * and is used to set config->format in the code several lines below.
3351 */
3352 out->format = audio_format_from_pcm_format(out->config.format);
3353 }
3354 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003355 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003356 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07003357 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3358 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003359
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003360 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003361 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003362 adev->primary_output = out;
3363 else {
3364 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003365 ret = -EEXIST;
3366 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003367 }
3368 }
3369
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003370 /* Check if this usecase is already existing */
3371 pthread_mutex_lock(&adev->lock);
3372 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3373 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003374 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003375 ret = -EEXIST;
3376 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003377 }
3378 pthread_mutex_unlock(&adev->lock);
3379
3380 out->stream.common.get_sample_rate = out_get_sample_rate;
3381 out->stream.common.set_sample_rate = out_set_sample_rate;
3382 out->stream.common.get_buffer_size = out_get_buffer_size;
3383 out->stream.common.get_channels = out_get_channels;
3384 out->stream.common.get_format = out_get_format;
3385 out->stream.common.set_format = out_set_format;
3386 out->stream.common.standby = out_standby;
3387 out->stream.common.dump = out_dump;
3388 out->stream.common.set_parameters = out_set_parameters;
3389 out->stream.common.get_parameters = out_get_parameters;
3390 out->stream.common.add_audio_effect = out_add_audio_effect;
3391 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3392 out->stream.get_latency = out_get_latency;
3393 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003394#ifdef NO_AUDIO_OUT
3395 out->stream.write = out_write_for_no_output;
3396#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003397 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003398#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003399 out->stream.get_render_position = out_get_render_position;
3400 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003401 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003402
Eric Laurent0e46adf2016-12-16 12:49:24 -08003403 if (out->realtime)
3404 out->af_period_multiplier = af_period_multiplier;
3405 else
3406 out->af_period_multiplier = 1;
3407
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003408 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003409 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003410 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003411
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003412 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003413 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003414 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3415
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003416 config->format = out->stream.common.get_format(&out->stream.common);
3417 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3418 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3419
Andy Hunga452b0a2017-03-15 14:51:15 -07003420 out->error_log = error_log_create(
3421 ERROR_LOG_ENTRIES,
3422 1000000000 /* aggregate consecutive identical errors within one second in ns */);
3423
Andy Hungfc044e12017-03-20 09:24:22 -07003424 const size_t POWER_LOG_FRAMES_PER_ENTRY =
3425 config->sample_rate * POWER_LOG_SAMPLING_INTERVAL_MS / 1000;
3426 // power_log may be null if the format is not supported
3427 out->power_log = power_log_create(
3428 config->sample_rate,
3429 audio_channel_count_from_out_mask(config->channel_mask),
3430 config->format,
3431 POWER_LOG_ENTRIES,
3432 POWER_LOG_FRAMES_PER_ENTRY);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003433
3434 /*
3435 By locking output stream before registering, we allow the callback
3436 to update stream's state only after stream's initial state is set to
3437 adev state.
3438 */
3439 lock_output_stream(out);
3440 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3441 pthread_mutex_lock(&adev->lock);
3442 out->card_status = adev->card_status;
3443 pthread_mutex_unlock(&adev->lock);
3444 pthread_mutex_unlock(&out->lock);
3445
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003446 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003447
Eric Laurent994a6932013-07-17 11:51:42 -07003448 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003449 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003450
3451error_open:
3452 free(out);
3453 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003454 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003455 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003456}
3457
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003458static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003459 struct audio_stream_out *stream)
3460{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003461 struct stream_out *out = (struct stream_out *)stream;
3462 struct audio_device *adev = out->dev;
3463
Eric Laurent994a6932013-07-17 11:51:42 -07003464 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003465
3466 // must deregister from sndmonitor first to prevent races
3467 // between the callback and close_stream
3468 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003469 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003470 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3471 destroy_offload_callback_thread(out);
3472
3473 if (out->compr_config.codec != NULL)
3474 free(out->compr_config.codec);
3475 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003476
3477 if (adev->voice_tx_output == out)
3478 adev->voice_tx_output = NULL;
3479
Andy Hungfc044e12017-03-20 09:24:22 -07003480 power_log_destroy(out->power_log);
3481 out->power_log = NULL;
3482
Andy Hunga452b0a2017-03-15 14:51:15 -07003483 error_log_destroy(out->error_log);
3484 out->error_log = NULL;
3485
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003486 pthread_cond_destroy(&out->cond);
3487 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003488 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003489 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003490}
3491
3492static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3493{
3494 struct audio_device *adev = (struct audio_device *)dev;
3495 struct str_parms *parms;
3496 char *str;
3497 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003498 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003499 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003500 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003501
Joe Onorato188b6222016-03-01 11:02:27 -08003502 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003503
3504 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003505
3506 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003507 status = voice_set_parameters(adev, parms);
3508 if (status != 0) {
3509 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003510 }
3511
3512 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3513 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003514 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003515 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3516 adev->bluetooth_nrec = true;
3517 else
3518 adev->bluetooth_nrec = false;
3519 }
3520
3521 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3522 if (ret >= 0) {
3523 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3524 adev->screen_off = false;
3525 else
3526 adev->screen_off = true;
3527 }
3528
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003529 ret = str_parms_get_int(parms, "rotation", &val);
3530 if (ret >= 0) {
3531 bool reverse_speakers = false;
3532 switch(val) {
3533 // FIXME: note that the code below assumes that the speakers are in the correct placement
3534 // relative to the user when the device is rotated 90deg from its default rotation. This
3535 // assumption is device-specific, not platform-specific like this code.
3536 case 270:
3537 reverse_speakers = true;
3538 break;
3539 case 0:
3540 case 90:
3541 case 180:
3542 break;
3543 default:
3544 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003545 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003546 }
Eric Laurent03f09432014-03-25 18:09:11 -07003547 if (status == 0) {
Ravi Kumar Alamanda1f60cf82015-04-23 19:45:17 -07003548 platform_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003549 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003550 }
3551
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003552 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3553 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003554 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003555 }
3556
David Linee3fe402017-03-13 10:00:42 -07003557 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3558 if (ret >= 0) {
3559 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
3560 if (device == AUDIO_DEVICE_OUT_USB_DEVICE) {
3561 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3562 if (ret >= 0) {
3563 const int card = atoi(value);
3564 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, card);
3565 }
3566 } else if (device == AUDIO_DEVICE_IN_USB_DEVICE) {
3567 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3568 if (ret >= 0) {
3569 const int card = atoi(value);
3570 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, card);
3571 }
3572 }
3573 }
3574
3575 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3576 if (ret >= 0) {
3577 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
3578 if (device == AUDIO_DEVICE_OUT_USB_DEVICE) {
3579 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3580 if (ret >= 0) {
3581 const int card = atoi(value);
3582
3583 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, card);
3584 }
3585 } else if (device == AUDIO_DEVICE_IN_USB_DEVICE) {
3586 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3587 if (ret >= 0) {
3588 const int card = atoi(value);
3589 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, card);
3590 }
3591 }
3592 }
3593
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08003594 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003595done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003596 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003597 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07003598 ALOGV("%s: exit with code(%d)", __func__, status);
3599 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003600}
3601
3602static char* adev_get_parameters(const struct audio_hw_device *dev,
3603 const char *keys)
3604{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003605 struct audio_device *adev = (struct audio_device *)dev;
3606 struct str_parms *reply = str_parms_create();
3607 struct str_parms *query = str_parms_create_str(keys);
3608 char *str;
3609
3610 pthread_mutex_lock(&adev->lock);
3611
3612 voice_get_parameters(adev, query, reply);
3613 str = str_parms_to_str(reply);
3614 str_parms_destroy(query);
3615 str_parms_destroy(reply);
3616
3617 pthread_mutex_unlock(&adev->lock);
3618 ALOGV("%s: exit: returns - %s", __func__, str);
3619 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003620}
3621
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003622static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003623{
3624 return 0;
3625}
3626
Haynes Mathew George5191a852013-09-11 14:19:36 -07003627static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3628{
3629 int ret;
3630 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003631
Eric Laurent4cc4ce12014-09-10 13:21:01 -05003632 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
3633
Haynes Mathew George5191a852013-09-11 14:19:36 -07003634 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003635 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003636 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003637
Haynes Mathew George5191a852013-09-11 14:19:36 -07003638 return ret;
3639}
3640
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003641static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003642{
3643 return -ENOSYS;
3644}
3645
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003646static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3647 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003648{
3649 return -ENOSYS;
3650}
3651
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003652static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003653{
3654 return -ENOSYS;
3655}
3656
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003657static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003658{
3659 return -ENOSYS;
3660}
3661
3662static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3663{
3664 struct audio_device *adev = (struct audio_device *)dev;
3665
3666 pthread_mutex_lock(&adev->lock);
3667 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07003668 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003669 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07003670 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3671 voice_is_in_call(adev)) {
3672 voice_stop_call(adev);
3673 adev->current_call_output = NULL;
3674 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003675 }
3676 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003677
3678 audio_extn_extspk_set_mode(adev->extspk, mode);
3679
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003680 return 0;
3681}
3682
3683static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3684{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003685 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003686 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003687
Eric Laurent2bafff12016-03-17 12:17:23 -07003688 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003689 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08003690 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
3691 ret = audio_extn_hfp_set_mic_mute(adev, state);
3692 } else {
3693 ret = voice_set_mic_mute(adev, state);
3694 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003695 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00003696 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003697
3698 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003699}
3700
3701static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3702{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003703 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003704 return 0;
3705}
3706
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003707static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003708 const struct audio_config *config)
3709{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003710 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003711
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003712 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3713 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003714}
3715
3716static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003717 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003718 audio_devices_t devices,
3719 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003720 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07003721 audio_input_flags_t flags,
3722 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05003723 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003724{
3725 struct audio_device *adev = (struct audio_device *)dev;
3726 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003727 int ret = 0, buffer_size, frame_size;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003728 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003729 bool is_low_latency = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003730
Eric Laurent994a6932013-07-17 11:51:42 -07003731 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003732 *stream_in = NULL;
3733 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3734 return -EINVAL;
3735
Zheng Zhang6185d572016-12-01 20:35:17 +08003736 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 -08003737 return -EINVAL;
3738
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003739 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
3740
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003741 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003742 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003743
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003744 in->stream.common.get_sample_rate = in_get_sample_rate;
3745 in->stream.common.set_sample_rate = in_set_sample_rate;
3746 in->stream.common.get_buffer_size = in_get_buffer_size;
3747 in->stream.common.get_channels = in_get_channels;
3748 in->stream.common.get_format = in_get_format;
3749 in->stream.common.set_format = in_set_format;
3750 in->stream.common.standby = in_standby;
3751 in->stream.common.dump = in_dump;
3752 in->stream.common.set_parameters = in_set_parameters;
3753 in->stream.common.get_parameters = in_get_parameters;
3754 in->stream.common.add_audio_effect = in_add_audio_effect;
3755 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3756 in->stream.set_gain = in_set_gain;
3757 in->stream.read = in_read;
3758 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08003759 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003760
3761 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003762 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003763 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003764 in->standby = 1;
3765 in->channel_mask = config->channel_mask;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003766 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003767 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003768
vivek mehta57ff9b52016-04-28 14:13:08 -07003769 // restrict 24 bit capture for unprocessed source only
3770 // for other sources if 24 bit requested reject 24 and set 16 bit capture only
3771 if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07003772 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07003773 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
3774 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
3775 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
3776 bool ret_error = false;
3777 /* 24 bit is restricted to UNPROCESSED source only,also format supported
3778 from HAL is 8_24
3779 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
3780 8_24 return error indicating supported format is 8_24
3781 *> In case of any other source requesting 24 bit or float return error
3782 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07003783
vivek mehta57ff9b52016-04-28 14:13:08 -07003784 on error flinger will retry with supported format passed
3785 */
3786 if (source != AUDIO_SOURCE_UNPROCESSED) {
3787 config->format = AUDIO_FORMAT_PCM_16_BIT;
3788 ret_error = true;
3789 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
3790 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
3791 ret_error = true;
3792 }
3793
3794 if (ret_error) {
3795 ret = -EINVAL;
3796 goto err_open;
3797 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003798 }
3799
vivek mehta57ff9b52016-04-28 14:13:08 -07003800 in->format = config->format;
3801
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003802 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003803 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
3804 if (config->sample_rate == 0)
3805 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3806 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3807 config->sample_rate != 8000) {
3808 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3809 ret = -EINVAL;
3810 goto err_open;
3811 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003812
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003813 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3814 config->format = AUDIO_FORMAT_PCM_16_BIT;
3815 ret = -EINVAL;
3816 goto err_open;
3817 }
3818
3819 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3820 in->config = pcm_config_afe_proxy_record;
3821 } else {
3822 in->usecase = USECASE_AUDIO_RECORD;
3823 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08003824 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003825 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07003826#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003827 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07003828#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08003829 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003830 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08003831 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003832 frame_size = audio_stream_in_frame_size(&in->stream);
3833 buffer_size = get_input_buffer_size(config->sample_rate,
3834 config->format,
3835 channel_count,
3836 is_low_latency);
3837 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003838 in->config.rate = config->sample_rate;
3839 in->af_period_multiplier = 1;
3840 } else {
3841 // period size is left untouched for rt mode playback
3842 in->config = pcm_config_audio_capture_rt;
3843 in->af_period_multiplier = af_period_multiplier;
3844 }
3845 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
3846 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
3847 in->usecase = USECASE_AUDIO_RECORD_MMAP;
3848 in->config = pcm_config_mmap_capture;
3849 in->stream.start = in_start;
3850 in->stream.stop = in_stop;
3851 in->stream.create_mmap_buffer = in_create_mmap_buffer;
3852 in->stream.get_mmap_position = in_get_mmap_position;
3853 in->af_period_multiplier = 1;
3854 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
3855 } else {
3856 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003857 frame_size = audio_stream_in_frame_size(&in->stream);
3858 buffer_size = get_input_buffer_size(config->sample_rate,
3859 config->format,
3860 channel_count,
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003861 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003862 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003863 in->config.rate = config->sample_rate;
3864 in->af_period_multiplier = 1;
3865 }
3866 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
3867 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003868 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003869
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003870 in->config.channels = channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003871
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003872 /* This stream could be for sound trigger lab,
3873 get sound trigger pcm if present */
3874 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003875
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003876 lock_input_stream(in);
3877 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
3878 pthread_mutex_lock(&adev->lock);
3879 in->card_status = adev->card_status;
3880 pthread_mutex_unlock(&adev->lock);
3881 pthread_mutex_unlock(&in->lock);
3882
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003883 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003884 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003885 return 0;
3886
3887err_open:
3888 free(in);
3889 *stream_in = NULL;
3890 return ret;
3891}
3892
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003893static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003894 struct audio_stream_in *stream)
3895{
Eric Laurent994a6932013-07-17 11:51:42 -07003896 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003897
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003898 // must deregister from sndmonitor first to prevent races
3899 // between the callback and close_stream
3900 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003901 in_standby(&stream->common);
3902 free(stream);
3903
3904 return;
3905}
3906
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003907static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003908{
3909 return 0;
3910}
3911
Andy Hung31aca912014-03-20 17:14:59 -07003912/* verifies input and output devices and their capabilities.
3913 *
3914 * This verification is required when enabling extended bit-depth or
3915 * sampling rates, as not all qcom products support it.
3916 *
3917 * Suitable for calling only on initialization such as adev_open().
3918 * It fills the audio_device use_case_table[] array.
3919 *
3920 * Has a side-effect that it needs to configure audio routing / devices
3921 * in order to power up the devices and read the device parameters.
3922 * It does not acquire any hw device lock. Should restore the devices
3923 * back to "normal state" upon completion.
3924 */
3925static int adev_verify_devices(struct audio_device *adev)
3926{
3927 /* enumeration is a bit difficult because one really wants to pull
3928 * the use_case, device id, etc from the hidden pcm_device_table[].
3929 * In this case there are the following use cases and device ids.
3930 *
3931 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
3932 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
3933 * [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
3934 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
3935 * [USECASE_AUDIO_RECORD] = {0, 0},
3936 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
3937 * [USECASE_VOICE_CALL] = {2, 2},
3938 *
3939 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_MULTI_CH omitted.
3940 * USECASE_VOICE_CALL omitted, but possible for either input or output.
3941 */
3942
3943 /* should be the usecases enabled in adev_open_input_stream() */
3944 static const int test_in_usecases[] = {
3945 USECASE_AUDIO_RECORD,
3946 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
3947 };
3948 /* should be the usecases enabled in adev_open_output_stream()*/
3949 static const int test_out_usecases[] = {
3950 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
3951 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
3952 };
3953 static const usecase_type_t usecase_type_by_dir[] = {
3954 PCM_PLAYBACK,
3955 PCM_CAPTURE,
3956 };
3957 static const unsigned flags_by_dir[] = {
3958 PCM_OUT,
3959 PCM_IN,
3960 };
3961
3962 size_t i;
3963 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003964 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07003965 char info[512]; /* for possible debug info */
3966
3967 for (dir = 0; dir < 2; ++dir) {
3968 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
3969 const unsigned flags_dir = flags_by_dir[dir];
3970 const size_t testsize =
3971 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
3972 const int *testcases =
3973 dir ? test_in_usecases : test_out_usecases;
3974 const audio_devices_t audio_device =
3975 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
3976
3977 for (i = 0; i < testsize; ++i) {
3978 const audio_usecase_t audio_usecase = testcases[i];
3979 int device_id;
3980 snd_device_t snd_device;
3981 struct pcm_params **pparams;
3982 struct stream_out out;
3983 struct stream_in in;
3984 struct audio_usecase uc_info;
3985 int retval;
3986
3987 pparams = &adev->use_case_table[audio_usecase];
3988 pcm_params_free(*pparams); /* can accept null input */
3989 *pparams = NULL;
3990
3991 /* find the device ID for the use case (signed, for error) */
3992 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
3993 if (device_id < 0)
3994 continue;
3995
3996 /* prepare structures for device probing */
3997 memset(&uc_info, 0, sizeof(uc_info));
3998 uc_info.id = audio_usecase;
3999 uc_info.type = usecase_type;
4000 if (dir) {
4001 adev->active_input = &in;
4002 memset(&in, 0, sizeof(in));
4003 in.device = audio_device;
4004 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4005 uc_info.stream.in = &in;
4006 } else {
4007 adev->active_input = NULL;
4008 }
4009 memset(&out, 0, sizeof(out));
4010 out.devices = audio_device; /* only field needed in select_devices */
4011 uc_info.stream.out = &out;
4012 uc_info.devices = audio_device;
4013 uc_info.in_snd_device = SND_DEVICE_NONE;
4014 uc_info.out_snd_device = SND_DEVICE_NONE;
4015 list_add_tail(&adev->usecase_list, &uc_info.list);
4016
4017 /* select device - similar to start_(in/out)put_stream() */
4018 retval = select_devices(adev, audio_usecase);
4019 if (retval >= 0) {
4020 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4021#if LOG_NDEBUG == 0
4022 if (*pparams) {
4023 ALOGV("%s: (%s) card %d device %d", __func__,
4024 dir ? "input" : "output", card_id, device_id);
4025 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004026 } else {
4027 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4028 }
4029#endif
4030 }
4031
4032 /* deselect device - similar to stop_(in/out)put_stream() */
4033 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004034 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004035 /* 2. Disable the rx device */
4036 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004037 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004038 list_remove(&uc_info.list);
4039 }
4040 }
4041 adev->active_input = NULL; /* restore adev state */
4042 return 0;
4043}
4044
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004045static int adev_close(hw_device_t *device)
4046{
Andy Hung31aca912014-03-20 17:14:59 -07004047 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004048 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004049
4050 if (!adev)
4051 return 0;
4052
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004053 audio_extn_tfa_98xx_deinit();
4054
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004055 audio_extn_snd_mon_unregister_listener(adev);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004056 pthread_mutex_lock(&adev_init_lock);
4057
4058 if ((--audio_device_ref_count) == 0) {
4059 audio_route_free(adev->audio_route);
4060 free(adev->snd_dev_ref_cnt);
4061 platform_deinit(adev->platform);
4062 audio_extn_extspk_deinit(adev->extspk);
4063 audio_extn_sound_trigger_deinit(adev);
4064 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4065 pcm_params_free(adev->use_case_table[i]);
4066 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004067 if (adev->adm_deinit)
4068 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004069 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004070 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004071
4072 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004073
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004074 return 0;
4075}
4076
Glenn Kasten4f993392014-05-14 07:30:48 -07004077/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4078 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4079 * just that it _might_ work.
4080 */
4081static int period_size_is_plausible_for_low_latency(int period_size)
4082{
4083 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004084 case 48:
4085 case 96:
4086 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004087 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004088 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004089 case 240:
4090 case 320:
4091 case 480:
4092 return 1;
4093 default:
4094 return 0;
4095 }
4096}
4097
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004098static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4099{
4100 int card;
4101 card_status_t status;
4102
4103 if (!parms)
4104 return;
4105
4106 if (parse_snd_card_status(parms, &card, &status) < 0)
4107 return;
4108
4109 pthread_mutex_lock(&adev->lock);
4110 bool valid_cb = (card == adev->snd_card);
4111 if (valid_cb) {
4112 if (adev->card_status != status) {
4113 adev->card_status = status;
4114 platform_snd_card_update(adev->platform, status);
4115 }
4116 }
4117 pthread_mutex_unlock(&adev->lock);
4118 return;
4119}
4120
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004121static int adev_open(const hw_module_t *module, const char *name,
4122 hw_device_t **device)
4123{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004124 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004125
Eric Laurent2bafff12016-03-17 12:17:23 -07004126 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004127 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004128 pthread_mutex_lock(&adev_init_lock);
4129 if (audio_device_ref_count != 0) {
4130 *device = &adev->device.common;
4131 audio_device_ref_count++;
4132 ALOGV("%s: returning existing instance of adev", __func__);
4133 ALOGV("%s: exit", __func__);
4134 pthread_mutex_unlock(&adev_init_lock);
4135 return 0;
4136 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004137 adev = calloc(1, sizeof(struct audio_device));
4138
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004139 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4140
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004141 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4142 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4143 adev->device.common.module = (struct hw_module_t *)module;
4144 adev->device.common.close = adev_close;
4145
4146 adev->device.init_check = adev_init_check;
4147 adev->device.set_voice_volume = adev_set_voice_volume;
4148 adev->device.set_master_volume = adev_set_master_volume;
4149 adev->device.get_master_volume = adev_get_master_volume;
4150 adev->device.set_master_mute = adev_set_master_mute;
4151 adev->device.get_master_mute = adev_get_master_mute;
4152 adev->device.set_mode = adev_set_mode;
4153 adev->device.set_mic_mute = adev_set_mic_mute;
4154 adev->device.get_mic_mute = adev_get_mic_mute;
4155 adev->device.set_parameters = adev_set_parameters;
4156 adev->device.get_parameters = adev_get_parameters;
4157 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4158 adev->device.open_output_stream = adev_open_output_stream;
4159 adev->device.close_output_stream = adev_close_output_stream;
4160 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004161
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004162 adev->device.close_input_stream = adev_close_input_stream;
4163 adev->device.dump = adev_dump;
4164
4165 /* Set the default route before the PCM stream is opened */
4166 pthread_mutex_lock(&adev->lock);
4167 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004168 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004169 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004170 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004171 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004172 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004173 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004174 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004175 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004176 pthread_mutex_unlock(&adev->lock);
4177
4178 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004179 adev->platform = platform_init(adev);
4180 if (!adev->platform) {
4181 free(adev->snd_dev_ref_cnt);
4182 free(adev);
4183 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4184 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004185 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004186 return -EINVAL;
4187 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05004188 adev->extspk = audio_extn_extspk_init(adev);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004189 audio_extn_sound_trigger_init(adev);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004190
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004191 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4192 if (adev->visualizer_lib == NULL) {
4193 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4194 } else {
4195 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4196 adev->visualizer_start_output =
4197 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4198 "visualizer_hal_start_output");
4199 adev->visualizer_stop_output =
4200 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4201 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07004202 }
4203
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004204 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4205 if (adev->offload_effects_lib == NULL) {
4206 ALOGW("%s: DLOPEN failed for %s", __func__,
4207 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4208 } else {
4209 ALOGV("%s: DLOPEN successful for %s", __func__,
4210 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4211 adev->offload_effects_start_output =
4212 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4213 "offload_effects_bundle_hal_start_output");
4214 adev->offload_effects_stop_output =
4215 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4216 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07004217 }
4218
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004219 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4220 if (adev->adm_lib == NULL) {
4221 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4222 } else {
4223 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4224 adev->adm_init = (adm_init_t)
4225 dlsym(adev->adm_lib, "adm_init");
4226 adev->adm_deinit = (adm_deinit_t)
4227 dlsym(adev->adm_lib, "adm_deinit");
4228 adev->adm_register_input_stream = (adm_register_input_stream_t)
4229 dlsym(adev->adm_lib, "adm_register_input_stream");
4230 adev->adm_register_output_stream = (adm_register_output_stream_t)
4231 dlsym(adev->adm_lib, "adm_register_output_stream");
4232 adev->adm_deregister_stream = (adm_deregister_stream_t)
4233 dlsym(adev->adm_lib, "adm_deregister_stream");
4234 adev->adm_request_focus = (adm_request_focus_t)
4235 dlsym(adev->adm_lib, "adm_request_focus");
4236 adev->adm_abandon_focus = (adm_abandon_focus_t)
4237 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08004238 adev->adm_set_config = (adm_set_config_t)
4239 dlsym(adev->adm_lib, "adm_set_config");
4240 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4241 dlsym(adev->adm_lib, "adm_request_focus_v2");
4242 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4243 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4244 adev->adm_on_routing_change = (adm_on_routing_change_t)
4245 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004246 }
4247
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004248 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004249 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004250
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004251 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004252
Andy Hung31aca912014-03-20 17:14:59 -07004253 if (k_enable_extended_precision)
4254 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004255
Glenn Kasten4f993392014-05-14 07:30:48 -07004256 char value[PROPERTY_VALUE_MAX];
4257 int trial;
4258 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4259 trial = atoi(value);
4260 if (period_size_is_plausible_for_low_latency(trial)) {
4261 pcm_config_low_latency.period_size = trial;
4262 pcm_config_low_latency.start_threshold = trial / 4;
4263 pcm_config_low_latency.avail_min = trial / 4;
4264 configured_low_latency_capture_period_size = trial;
4265 }
4266 }
4267 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4268 trial = atoi(value);
4269 if (period_size_is_plausible_for_low_latency(trial)) {
4270 configured_low_latency_capture_period_size = trial;
4271 }
4272 }
4273
Yamit Mehtae3b99562016-09-16 22:44:00 +05304274 audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004275 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004276
4277 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4278 af_period_multiplier = atoi(value);
4279 if (af_period_multiplier < 0) {
4280 af_period_multiplier = 2;
4281 } else if (af_period_multiplier > 4) {
4282 af_period_multiplier = 4;
4283 }
4284 ALOGV("new period_multiplier = %d", af_period_multiplier);
4285 }
4286
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004287 audio_extn_tfa_98xx_init(adev);
4288
vivek mehta1a9b7c02015-06-25 11:49:38 -07004289 pthread_mutex_unlock(&adev_init_lock);
4290
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004291 if (adev->adm_init)
4292 adev->adm_data = adev->adm_init();
4293
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004294 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004295 audio_extn_snd_mon_init();
4296 pthread_mutex_lock(&adev->lock);
4297 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
4298 adev->card_status = CARD_STATUS_ONLINE;
4299 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004300
Eric Laurent2bafff12016-03-17 12:17:23 -07004301 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004302 return 0;
4303}
4304
4305static struct hw_module_methods_t hal_module_methods = {
4306 .open = adev_open,
4307};
4308
4309struct audio_module HAL_MODULE_INFO_SYM = {
4310 .common = {
4311 .tag = HARDWARE_MODULE_TAG,
4312 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4313 .hal_api_version = HARDWARE_HAL_API_VERSION,
4314 .id = AUDIO_HARDWARE_MODULE_ID,
4315 .name = "QCOM Audio HAL",
4316 .author = "Code Aurora Forum",
4317 .methods = &hal_module_methods,
4318 },
4319};