blob: 262bbc68ebe8ac3c568dd08fddea9439660df9f9 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
vivek mehtaa51fd402016-02-04 19:49:33 -08002 * Copyright (C) 2013-2016 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "audio_hw_primary"
Haynes Mathew George03c40102016-01-29 17:57:48 -080018#define ATRACE_TAG ATRACE_TAG_AUDIO
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080019/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070020/*#define VERY_VERY_VERBOSE_LOGGING*/
21#ifdef VERY_VERY_VERBOSE_LOGGING
22#define ALOGVV ALOGV
23#else
24#define ALOGVV(a...) do { } while(0)
25#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080026
27#include <errno.h>
28#include <pthread.h>
29#include <stdint.h>
30#include <sys/time.h>
31#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080032#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070033#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070034#include <sys/resource.h>
35#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036
37#include <cutils/log.h>
Haynes Mathew George03c40102016-01-29 17:57:48 -080038#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080039#include <cutils/str_parms.h>
40#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041#include <cutils/atomic.h>
42#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080043
Eric Laurentb23d5282013-05-14 15:27:20 -070044#include <hardware/audio_effect.h>
Andy Hung31aca912014-03-20 17:14:59 -070045#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070046#include <system/thread_defs.h>
Phil Burkbc991042017-02-24 08:06:44 -080047#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070048#include <audio_effects/effect_aec.h>
49#include <audio_effects/effect_ns.h>
Andy Hungfc044e12017-03-20 09:24:22 -070050#include <audio_utils/clock.h>
51#include <audio_utils/power.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052#include "audio_hw.h"
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -080053#include "audio_extn.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070054#include "platform_api.h"
55#include <platform.h>
Vineeta Srivastava4b89e372014-06-19 14:21:42 -070056#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070058#include "sound/compress_params.h"
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -080059#include "audio_extn/tfa_98xx.h"
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070060
Eric Laurent397db572016-05-11 11:31:47 -070061/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
62 * COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
Marco Nelissen32093f52015-04-08 15:14:02 -070063#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070064// 2 buffers causes problems with high bitrate files
65#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066/* ToDo: Check and update a proper value in msec */
67#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
68#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
69
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070070#define PROXY_OPEN_RETRY_COUNT 100
71#define PROXY_OPEN_WAIT_TIME 20
72
vivek mehtadae44712015-07-27 14:13:18 -070073#define MIN_CHANNEL_COUNT 1
74#define DEFAULT_CHANNEL_COUNT 2
75
Jean-Michel Trivic0750692015-10-12 12:12:32 -070076#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
77#define MAX_CHANNEL_COUNT 1
78#else
vivek mehtadae44712015-07-27 14:13:18 -070079#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
80#define XSTR(x) STR(x)
81#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070082#endif
vivek mehtadae44712015-07-27 14:13:18 -070083
Haynes Mathew George03c40102016-01-29 17:57:48 -080084#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
85
Glenn Kasten4f993392014-05-14 07:30:48 -070086static unsigned int configured_low_latency_capture_period_size =
87 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
88
Eric Laurent0e46adf2016-12-16 12:49:24 -080089
90#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Phil Burkbc991042017-02-24 08:06:44 -080091#define MMAP_PERIOD_COUNT_MIN 32
92#define MMAP_PERIOD_COUNT_MAX 512
93#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
Eric Laurent0e46adf2016-12-16 12:49:24 -080094
95
Andy Hung31aca912014-03-20 17:14:59 -070096/* This constant enables extended precision handling.
97 * TODO The flag is off until more testing is done.
98 */
99static const bool k_enable_extended_precision = false;
100
Eric Laurentb23d5282013-05-14 15:27:20 -0700101struct pcm_config pcm_config_deep_buffer = {
vivek mehtadae44712015-07-27 14:13:18 -0700102 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700103 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
104 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
105 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
106 .format = PCM_FORMAT_S16_LE,
107 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
108 .stop_threshold = INT_MAX,
109 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
110};
111
112struct pcm_config pcm_config_low_latency = {
vivek mehtadae44712015-07-27 14:13:18 -0700113 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700114 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
115 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
116 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
117 .format = PCM_FORMAT_S16_LE,
118 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
119 .stop_threshold = INT_MAX,
120 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
121};
122
Haynes Mathew George03c40102016-01-29 17:57:48 -0800123static int af_period_multiplier = 4;
124struct pcm_config pcm_config_rt = {
125 .channels = DEFAULT_CHANNEL_COUNT,
126 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
127 .period_size = ULL_PERIOD_SIZE, //1 ms
128 .period_count = 512, //=> buffer size is 512ms
129 .format = PCM_FORMAT_S16_LE,
130 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
131 .stop_threshold = INT_MAX,
132 .silence_threshold = 0,
133 .silence_size = 0,
134 .avail_min = ULL_PERIOD_SIZE, //1 ms
135};
136
Eric Laurentb23d5282013-05-14 15:27:20 -0700137struct pcm_config pcm_config_hdmi_multi = {
138 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
139 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
140 .period_size = HDMI_MULTI_PERIOD_SIZE,
141 .period_count = HDMI_MULTI_PERIOD_COUNT,
142 .format = PCM_FORMAT_S16_LE,
143 .start_threshold = 0,
144 .stop_threshold = INT_MAX,
145 .avail_min = 0,
146};
147
Eric Laurent0e46adf2016-12-16 12:49:24 -0800148struct pcm_config pcm_config_mmap_playback = {
149 .channels = DEFAULT_CHANNEL_COUNT,
150 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
151 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800152 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800153 .format = PCM_FORMAT_S16_LE,
154 .start_threshold = MMAP_PERIOD_SIZE*8,
155 .stop_threshold = INT32_MAX,
156 .silence_threshold = 0,
157 .silence_size = 0,
158 .avail_min = MMAP_PERIOD_SIZE, //1 ms
159};
160
Eric Laurentb23d5282013-05-14 15:27:20 -0700161struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700162 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700163 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
164 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700165 .stop_threshold = INT_MAX,
166 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700167};
168
Haynes Mathew George03c40102016-01-29 17:57:48 -0800169struct pcm_config pcm_config_audio_capture_rt = {
170 .channels = DEFAULT_CHANNEL_COUNT,
171 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
172 .period_size = ULL_PERIOD_SIZE,
173 .period_count = 512,
174 .format = PCM_FORMAT_S16_LE,
175 .start_threshold = 0,
176 .stop_threshold = INT_MAX,
177 .silence_threshold = 0,
178 .silence_size = 0,
179 .avail_min = ULL_PERIOD_SIZE, //1 ms
180};
181
Eric Laurent0e46adf2016-12-16 12:49:24 -0800182struct pcm_config pcm_config_mmap_capture = {
183 .channels = DEFAULT_CHANNEL_COUNT,
184 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
185 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800186 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800187 .format = PCM_FORMAT_S16_LE,
188 .start_threshold = 0,
189 .stop_threshold = INT_MAX,
190 .silence_threshold = 0,
191 .silence_size = 0,
192 .avail_min = MMAP_PERIOD_SIZE, //1 ms
193};
194
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700195#define AFE_PROXY_CHANNEL_COUNT 2
196#define AFE_PROXY_SAMPLING_RATE 48000
197
198#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
199#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
200
201struct pcm_config pcm_config_afe_proxy_playback = {
202 .channels = AFE_PROXY_CHANNEL_COUNT,
203 .rate = AFE_PROXY_SAMPLING_RATE,
204 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
205 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
206 .format = PCM_FORMAT_S16_LE,
207 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
208 .stop_threshold = INT_MAX,
209 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
210};
211
212#define AFE_PROXY_RECORD_PERIOD_SIZE 768
213#define AFE_PROXY_RECORD_PERIOD_COUNT 4
214
215struct pcm_config pcm_config_afe_proxy_record = {
216 .channels = AFE_PROXY_CHANNEL_COUNT,
217 .rate = AFE_PROXY_SAMPLING_RATE,
218 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
219 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
220 .format = PCM_FORMAT_S16_LE,
221 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
222 .stop_threshold = INT_MAX,
223 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
224};
225
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700226const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700227 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
228 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
229 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700230 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700231 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700232 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800233 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700234
Eric Laurentb23d5282013-05-14 15:27:20 -0700235 [USECASE_AUDIO_RECORD] = "audio-record",
236 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800237 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700238
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800239 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
240 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700241
Eric Laurentb23d5282013-05-14 15:27:20 -0700242 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700243 [USECASE_VOICE2_CALL] = "voice2-call",
244 [USECASE_VOLTE_CALL] = "volte-call",
245 [USECASE_QCHAT_CALL] = "qchat-call",
246 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800247 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
248 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700249
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700250 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
251 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
252
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700253 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
254 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700255};
256
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800257
258#define STRING_TO_ENUM(string) { #string, string }
259
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800260struct string_to_enum {
261 const char *name;
262 uint32_t value;
263};
264
265static const struct string_to_enum out_channels_name_to_enum_table[] = {
266 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
267 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
268 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
269};
270
Haynes Mathew George5191a852013-09-11 14:19:36 -0700271static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700272static struct audio_device *adev = NULL;
273static pthread_mutex_t adev_init_lock;
274static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700275//cache last MBDRC cal step level
276static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700277
Haynes Mathew George03c40102016-01-29 17:57:48 -0800278static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
279 int flags __unused)
280{
281 int dir = 0;
282 switch (uc_id) {
283 case USECASE_AUDIO_RECORD_LOW_LATENCY:
284 dir = 1;
285 case USECASE_AUDIO_PLAYBACK_ULL:
286 break;
287 default:
288 return false;
289 }
290
291 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
292 PCM_PLAYBACK : PCM_CAPTURE);
293 if (adev->adm_is_noirq_avail)
294 return adev->adm_is_noirq_avail(adev->adm_data,
295 adev->snd_card, dev_id, dir);
296 return false;
297}
298
299static void register_out_stream(struct stream_out *out)
300{
301 struct audio_device *adev = out->dev;
302 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
303 return;
304
305 if (!adev->adm_register_output_stream)
306 return;
307
308 adev->adm_register_output_stream(adev->adm_data,
309 out->handle,
310 out->flags);
311
312 if (!adev->adm_set_config)
313 return;
314
315 if (out->realtime) {
316 adev->adm_set_config(adev->adm_data,
317 out->handle,
318 out->pcm, &out->config);
319 }
320}
321
322static void register_in_stream(struct stream_in *in)
323{
324 struct audio_device *adev = in->dev;
325 if (!adev->adm_register_input_stream)
326 return;
327
328 adev->adm_register_input_stream(adev->adm_data,
329 in->capture_handle,
330 in->flags);
331
332 if (!adev->adm_set_config)
333 return;
334
335 if (in->realtime) {
336 adev->adm_set_config(adev->adm_data,
337 in->capture_handle,
338 in->pcm,
339 &in->config);
340 }
341}
342
343static void request_out_focus(struct stream_out *out, long ns)
344{
345 struct audio_device *adev = out->dev;
346
347 if (out->routing_change) {
348 out->routing_change = false;
349 if (adev->adm_on_routing_change)
350 adev->adm_on_routing_change(adev->adm_data, out->handle);
351 }
352
353 if (adev->adm_request_focus_v2) {
354 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
355 } else if (adev->adm_request_focus) {
356 adev->adm_request_focus(adev->adm_data, out->handle);
357 }
358}
359
360static void request_in_focus(struct stream_in *in, long ns)
361{
362 struct audio_device *adev = in->dev;
363
364 if (in->routing_change) {
365 in->routing_change = false;
366 if (adev->adm_on_routing_change)
367 adev->adm_on_routing_change(adev->adm_data, in->capture_handle);
368 }
369
370 if (adev->adm_request_focus_v2) {
371 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
372 } else if (adev->adm_request_focus) {
373 adev->adm_request_focus(adev->adm_data, in->capture_handle);
374 }
375}
376
377static void release_out_focus(struct stream_out *out, long ns __unused)
378{
379 struct audio_device *adev = out->dev;
380
381 if (adev->adm_abandon_focus)
382 adev->adm_abandon_focus(adev->adm_data, out->handle);
383}
384
385static void release_in_focus(struct stream_in *in, long ns __unused)
386{
387 struct audio_device *adev = in->dev;
388 if (adev->adm_abandon_focus)
389 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
390}
391
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700392static int parse_snd_card_status(struct str_parms * parms, int * card,
393 card_status_t * status)
394{
395 char value[32]={0};
396 char state[32]={0};
397
398 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
399
400 if (ret < 0)
401 return -1;
402
403 // sscanf should be okay as value is of max length 32.
404 // same as sizeof state.
405 if (sscanf(value, "%d,%s", card, state) < 2)
406 return -1;
407
408 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
409 CARD_STATUS_OFFLINE;
410 return 0;
411}
412
vivek mehta1a9b7c02015-06-25 11:49:38 -0700413__attribute__ ((visibility ("default")))
414bool audio_hw_send_gain_dep_calibration(int level) {
415 bool ret_val = false;
416 ALOGV("%s: enter ... ", __func__);
417
418 pthread_mutex_lock(&adev_init_lock);
419
420 if (adev != NULL && adev->platform != NULL) {
421 pthread_mutex_lock(&adev->lock);
422 ret_val = platform_send_gain_dep_cal(adev->platform, level);
423 pthread_mutex_unlock(&adev->lock);
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700424
425 // if cal set fails, cache level info
426 // if cal set succeds, reset known last cal set
427 if (!ret_val)
428 last_known_cal_step = level;
429 else if (last_known_cal_step != -1)
430 last_known_cal_step = -1;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700431 } else {
432 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
433 }
434
435 pthread_mutex_unlock(&adev_init_lock);
436
437 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
438 return ret_val;
439}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700440
vivek mehtaa8d7c922016-05-25 14:40:44 -0700441__attribute__ ((visibility ("default")))
442int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
443 int table_size) {
444 int ret_val = 0;
445 ALOGV("%s: enter ... ", __func__);
446
447 pthread_mutex_lock(&adev_init_lock);
448 if (adev == NULL) {
449 ALOGW("%s: adev is NULL .... ", __func__);
450 goto done;
451 }
452
453 pthread_mutex_lock(&adev->lock);
454 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
455 pthread_mutex_unlock(&adev->lock);
456done:
457 pthread_mutex_unlock(&adev_init_lock);
458 ALOGV("%s: exit ... ", __func__);
459 return ret_val;
460}
461
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700462static bool is_supported_format(audio_format_t format)
463{
Eric Laurent8251ac82014-07-23 11:00:25 -0700464 switch (format) {
465 case AUDIO_FORMAT_MP3:
466 case AUDIO_FORMAT_AAC_LC:
467 case AUDIO_FORMAT_AAC_HE_V1:
468 case AUDIO_FORMAT_AAC_HE_V2:
469 return true;
470 default:
471 break;
472 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700473 return false;
474}
475
Haynes Mathew George03c40102016-01-29 17:57:48 -0800476static inline bool is_mmap_usecase(audio_usecase_t uc_id)
477{
478 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
479 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
480}
481
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700482static int get_snd_codec_id(audio_format_t format)
483{
484 int id = 0;
485
Eric Laurent8251ac82014-07-23 11:00:25 -0700486 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700487 case AUDIO_FORMAT_MP3:
488 id = SND_AUDIOCODEC_MP3;
489 break;
490 case AUDIO_FORMAT_AAC:
491 id = SND_AUDIOCODEC_AAC;
492 break;
493 default:
494 ALOGE("%s: Unsupported audio format", __func__);
495 }
496
497 return id;
498}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800499
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800500static int audio_ssr_status(struct audio_device *adev)
501{
502 int ret = 0;
503 struct mixer_ctl *ctl;
504 const char *mixer_ctl_name = "Audio SSR Status";
505
506 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
507 ret = mixer_ctl_get_value(ctl, 0);
508 ALOGD("%s: value: %d", __func__, ret);
509 return ret;
510}
511
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800512int enable_audio_route(struct audio_device *adev,
513 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800514{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700515 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800516 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800517
518 if (usecase == NULL)
519 return -EINVAL;
520
521 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
522
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800523 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700524 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800525 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700526 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800527
Yamit Mehtae3b99562016-09-16 22:44:00 +0530528 audio_extn_utils_send_app_type_cfg(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800529 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500530 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700531 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700532 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800533
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800534 ALOGV("%s: exit", __func__);
535 return 0;
536}
537
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800538int disable_audio_route(struct audio_device *adev,
539 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800540{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700541 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800542 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800543
544 if (usecase == NULL)
545 return -EINVAL;
546
547 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700548 if (usecase->type == PCM_CAPTURE)
549 snd_device = usecase->in_snd_device;
550 else
551 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800552 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500553 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700554 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700555 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800556
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800557 ALOGV("%s: exit", __func__);
558 return 0;
559}
560
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800561int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700562 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800563{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700564 int i, num_devices = 0;
565 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800566 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800567 if (snd_device < SND_DEVICE_MIN ||
568 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800569 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800570 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800571 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700572
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700573 platform_send_audio_calibration(adev->platform, snd_device);
574
vivek mehtade4849c2016-03-03 17:23:38 -0800575 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700576 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700577 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800578 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700579 }
580
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700581 /* due to the possibility of calibration overwrite between listen
582 and audio, notify sound trigger hal before audio calibration is sent */
583 audio_extn_sound_trigger_update_device_status(snd_device,
584 ST_EVENT_SND_DEVICE_BUSY);
585
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700586 if (audio_extn_spkr_prot_is_enabled())
587 audio_extn_spkr_prot_calib_cancel(adev);
588
zhaoyang yin4211fad2015-06-04 21:13:25 +0800589 audio_extn_dsm_feedback_enable(adev, snd_device, true);
590
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700591 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
592 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
593 audio_extn_spkr_prot_is_enabled()) {
594 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800595 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700596 }
597 if (audio_extn_spkr_prot_start_processing(snd_device)) {
598 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800599 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700600 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700601 } else if (platform_can_split_snd_device(snd_device,
602 &num_devices,
603 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700604 for (i = 0; i < num_devices; i++) {
605 enable_snd_device(adev, new_snd_devices[i]);
606 }
vivek mehtab6506412015-08-07 16:55:17 -0700607 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700608 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800609 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
610 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
611 ALOGE(" %s: Invalid sound device returned", __func__);
612 goto on_error;
613 }
Ed Tam70b5c142016-03-21 19:14:29 -0700614
Eric Laurent2e140aa2016-06-30 17:14:46 -0700615 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800616 audio_route_apply_and_update_path(adev->audio_route, device_name);
617 }
618on_success:
619 adev->snd_dev_ref_cnt[snd_device]++;
620 ret_val = 0;
621on_error:
622 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800623}
624
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800625int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700626 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800627{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700628 int i, num_devices = 0;
629 snd_device_t new_snd_devices[2];
630
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800631 if (snd_device < SND_DEVICE_MIN ||
632 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800633 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800634 return -EINVAL;
635 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700636 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
637 ALOGE("%s: device ref cnt is already 0", __func__);
638 return -EINVAL;
639 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800640 audio_extn_tfa_98xx_disable_speaker(snd_device);
641
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700642 adev->snd_dev_ref_cnt[snd_device]--;
643 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800644 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700645 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
646 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
647 audio_extn_spkr_prot_is_enabled()) {
648 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700649 } else if (platform_can_split_snd_device(snd_device,
650 &num_devices,
651 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700652 for (i = 0; i < num_devices; i++) {
653 disable_snd_device(adev, new_snd_devices[i]);
654 }
vivek mehtab6506412015-08-07 16:55:17 -0700655 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700656 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800657 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
658 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
659 ALOGE(" %s: Invalid sound device returned", __func__);
660 return -EINVAL;
661 }
662
Eric Laurent2e140aa2016-06-30 17:14:46 -0700663 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800664 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700665 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700666 audio_extn_sound_trigger_update_device_status(snd_device,
667 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700668 }
vivek mehtab6506412015-08-07 16:55:17 -0700669
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800670 return 0;
671}
672
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700673/*
674 legend:
675 uc - existing usecase
676 new_uc - new usecase
677 d1, d11, d2 - SND_DEVICE enums
678 a1, a2 - corresponding ANDROID device enums
679 B, B1, B2 - backend strings
680
681case 1
682 uc->dev d1 (a1) B1
683 new_uc->dev d1 (a1), d2 (a2) B1, B2
684
685 resolution: disable and enable uc->dev on d1
686
687case 2
688 uc->dev d1 (a1) B1
689 new_uc->dev d11 (a1) B1
690
691 resolution: need to switch uc since d1 and d11 are related
692 (e.g. speaker and voice-speaker)
693 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
694
695case 3
696 uc->dev d1 (a1) B1
697 new_uc->dev d2 (a2) B2
698
699 resolution: no need to switch uc
700
701case 4
702 uc->dev d1 (a1) B
703 new_uc->dev d2 (a2) B
704
705 resolution: disable enable uc-dev on d2 since backends match
706 we cannot enable two streams on two different devices if they
707 share the same backend. e.g. if offload is on speaker device using
708 QUAD_MI2S backend and a low-latency stream is started on voice-handset
709 using the same backend, offload must also be switched to voice-handset.
710
711case 5
712 uc->dev d1 (a1) B
713 new_uc->dev d1 (a1), d2 (a2) B
714
715 resolution: disable enable uc-dev on d2 since backends match
716 we cannot enable two streams on two different devices if they
717 share the same backend.
718
719case 6
720 uc->dev d1 a1 B1
721 new_uc->dev d2 a1 B2
722
723 resolution: no need to switch
724
725case 7
726
727 uc->dev d1 (a1), d2 (a2) B1, B2
728 new_uc->dev d1 B1
729
730 resolution: no need to switch
731
732*/
733static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
734 struct audio_usecase *new_uc,
735 snd_device_t new_snd_device)
736{
737 audio_devices_t a1 = uc->stream.out->devices;
738 audio_devices_t a2 = new_uc->stream.out->devices;
739
740 snd_device_t d1 = uc->out_snd_device;
741 snd_device_t d2 = new_snd_device;
742
743 // Treat as a special case when a1 and a2 are not disjoint
744 if ((a1 != a2) && (a1 & a2)) {
745 snd_device_t d3[2];
746 int num_devices = 0;
747 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
748 &num_devices,
749 d3);
750 if (ret < 0) {
751 if (ret != -ENOSYS) {
752 ALOGW("%s failed to split snd_device %d",
753 __func__,
754 popcount(a1) > 1 ? d1 : d2);
755 }
756 goto end;
757 }
758
759 // NB: case 7 is hypothetical and isn't a practical usecase yet.
760 // But if it does happen, we need to give priority to d2 if
761 // the combo devices active on the existing usecase share a backend.
762 // This is because we cannot have a usecase active on a combo device
763 // and a new usecase requests one device in this combo pair.
764 if (platform_check_backends_match(d3[0], d3[1])) {
765 return d2; // case 5
766 } else {
767 return d1; // case 1
768 }
769 } else {
770 if (platform_check_backends_match(d1, d2)) {
771 return d2; // case 2, 4
772 } else {
773 return d1; // case 6, 3
774 }
775 }
776
777end:
778 return d2; // return whatever was calculated before.
779}
780
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700781static void check_and_route_playback_usecases(struct audio_device *adev,
782 struct audio_usecase *uc_info,
783 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700784{
785 struct listnode *node;
786 struct audio_usecase *usecase;
787 bool switch_device[AUDIO_USECASE_MAX];
788 int i, num_uc_to_switch = 0;
789
David Linee3fe402017-03-13 10:00:42 -0700790 platform_check_and_set_playback_backend_cfg(adev, uc_info, snd_device);
791
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700792 /*
793 * This function is to make sure that all the usecases that are active on
794 * the hardware codec backend are always routed to any one device that is
795 * handled by the hardware codec.
796 * For example, if low-latency and deep-buffer usecases are currently active
797 * on speaker and out_set_parameters(headset) is received on low-latency
798 * output, then we have to make sure deep-buffer is also switched to headset,
799 * because of the limitation that both the devices cannot be enabled
800 * at the same time as they share the same backend.
801 */
802 /* Disable all the usecases on the shared backend other than the
803 specified usecase */
804 for (i = 0; i < AUDIO_USECASE_MAX; i++)
805 switch_device[i] = false;
806
807 list_for_each(node, &adev->usecase_list) {
808 usecase = node_to_item(node, struct audio_usecase, list);
809 if (usecase->type != PCM_CAPTURE &&
810 usecase != uc_info &&
811 usecase->out_snd_device != snd_device &&
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700812 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
813 platform_check_backends_match(snd_device, usecase->out_snd_device)) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700814 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
815 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700816 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700817 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700818 switch_device[usecase->id] = true;
819 num_uc_to_switch++;
820 }
821 }
822
823 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700824 list_for_each(node, &adev->usecase_list) {
825 usecase = node_to_item(node, struct audio_usecase, list);
826 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700827 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900828 }
829 }
830
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700831 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900832 list_for_each(node, &adev->usecase_list) {
833 usecase = node_to_item(node, struct audio_usecase, list);
834 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700835 d_device = derive_playback_snd_device(usecase, uc_info,
836 snd_device);
837 enable_snd_device(adev, d_device);
838 /* Update the out_snd_device before enabling the audio route */
839 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700840 }
841 }
842
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700843 /* Re-route all the usecases on the shared backend other than the
844 specified usecase to new snd devices */
845 list_for_each(node, &adev->usecase_list) {
846 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700847 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700848 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700849 }
850 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700851 }
852}
853
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700854static void check_and_route_capture_usecases(struct audio_device *adev,
855 struct audio_usecase *uc_info,
856 snd_device_t snd_device)
857{
858 struct listnode *node;
859 struct audio_usecase *usecase;
860 bool switch_device[AUDIO_USECASE_MAX];
861 int i, num_uc_to_switch = 0;
862
vivek mehta4ed66e62016-04-15 23:33:34 -0700863 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
864
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700865 /*
866 * This function is to make sure that all the active capture usecases
867 * are always routed to the same input sound device.
868 * For example, if audio-record and voice-call usecases are currently
869 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
870 * is received for voice call then we have to make sure that audio-record
871 * usecase is also switched to earpiece i.e. voice-dmic-ef,
872 * because of the limitation that two devices cannot be enabled
873 * at the same time if they share the same backend.
874 */
875 for (i = 0; i < AUDIO_USECASE_MAX; i++)
876 switch_device[i] = false;
877
878 list_for_each(node, &adev->usecase_list) {
879 usecase = node_to_item(node, struct audio_usecase, list);
880 if (usecase->type != PCM_PLAYBACK &&
881 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700882 usecase->in_snd_device != snd_device &&
883 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700884 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
885 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700886 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700887 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700888 switch_device[usecase->id] = true;
889 num_uc_to_switch++;
890 }
891 }
892
893 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700894 list_for_each(node, &adev->usecase_list) {
895 usecase = node_to_item(node, struct audio_usecase, list);
896 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700897 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700898 }
899 }
900
901 list_for_each(node, &adev->usecase_list) {
902 usecase = node_to_item(node, struct audio_usecase, list);
903 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700904 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700905 }
906 }
907
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700908 /* Re-route all the usecases on the shared backend other than the
909 specified usecase to new snd devices */
910 list_for_each(node, &adev->usecase_list) {
911 usecase = node_to_item(node, struct audio_usecase, list);
912 /* Update the in_snd_device only before enabling the audio route */
913 if (switch_device[usecase->id] ) {
914 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700915 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700916 }
917 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700918 }
919}
920
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800921/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700922static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800923{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700924 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700925 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800926
927 switch (channels) {
928 /*
929 * Do not handle stereo output in Multi-channel cases
930 * Stereo case is handled in normal playback path
931 */
932 case 6:
933 ALOGV("%s: HDMI supports 5.1", __func__);
934 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
935 break;
936 case 8:
937 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
938 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
939 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
940 break;
941 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700942 ALOGE("HDMI does not support multi channel playback");
943 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800944 break;
945 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700946 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800947}
948
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -0700949static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
950{
951 struct audio_usecase *usecase;
952 struct listnode *node;
953
954 list_for_each(node, &adev->usecase_list) {
955 usecase = node_to_item(node, struct audio_usecase, list);
956 if (usecase->type == VOICE_CALL) {
957 ALOGV("%s: usecase id %d", __func__, usecase->id);
958 return usecase->id;
959 }
960 }
961 return USECASE_INVALID;
962}
963
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800964struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
965 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700966{
967 struct audio_usecase *usecase;
968 struct listnode *node;
969
970 list_for_each(node, &adev->usecase_list) {
971 usecase = node_to_item(node, struct audio_usecase, list);
972 if (usecase->id == uc_id)
973 return usecase;
974 }
975 return NULL;
976}
977
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800978int select_devices(struct audio_device *adev,
979 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800980{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800981 snd_device_t out_snd_device = SND_DEVICE_NONE;
982 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700983 struct audio_usecase *usecase = NULL;
984 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800985 struct audio_usecase *hfp_usecase = NULL;
986 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800987 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700988 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800989
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700990 usecase = get_usecase_from_list(adev, uc_id);
991 if (usecase == NULL) {
992 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
993 return -EINVAL;
994 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800995
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800996 if ((usecase->type == VOICE_CALL) ||
997 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700998 out_snd_device = platform_get_output_snd_device(adev->platform,
999 usecase->stream.out->devices);
1000 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001001 usecase->devices = usecase->stream.out->devices;
1002 } else {
1003 /*
1004 * If the voice call is active, use the sound devices of voice call usecase
1005 * so that it would not result any device switch. All the usecases will
1006 * be switched to new device when select_devices() is called for voice call
1007 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001008 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001009 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001010 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001011 vc_usecase = get_usecase_from_list(adev,
1012 get_voice_usecase_id_from_list(adev));
1013 if ((vc_usecase != NULL) &&
1014 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1015 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001016 in_snd_device = vc_usecase->in_snd_device;
1017 out_snd_device = vc_usecase->out_snd_device;
1018 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001019 } else if (audio_extn_hfp_is_active(adev)) {
1020 hfp_ucid = audio_extn_hfp_get_usecase();
1021 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1022 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1023 in_snd_device = hfp_usecase->in_snd_device;
1024 out_snd_device = hfp_usecase->out_snd_device;
1025 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001026 }
1027 if (usecase->type == PCM_PLAYBACK) {
1028 usecase->devices = usecase->stream.out->devices;
1029 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001030 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001031 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001032 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001033 if (usecase->stream.out == adev->primary_output &&
1034 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001035 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1036 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001037 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001038 select_devices(adev, adev->active_input->usecase);
1039 }
1040 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001041 } else if (usecase->type == PCM_CAPTURE) {
1042 usecase->devices = usecase->stream.in->device;
1043 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001044 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001045 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001046 if (adev->active_input &&
1047 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1048 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001049 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001050 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1051 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
1052 } else if (adev->primary_output) {
1053 out_device = adev->primary_output->devices;
1054 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001055 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001056 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001057 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001058 }
1059 }
1060
1061 if (out_snd_device == usecase->out_snd_device &&
1062 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001063 return 0;
1064 }
1065
Eric Laurent2bafff12016-03-17 12:17:23 -07001066 if (out_snd_device != SND_DEVICE_NONE &&
1067 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1068 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1069 __func__,
1070 use_case_table[uc_id],
1071 adev->last_logged_snd_device[uc_id][0],
1072 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1073 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1074 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1075 -1,
1076 out_snd_device,
1077 platform_get_snd_device_name(out_snd_device),
1078 platform_get_snd_device_acdb_id(out_snd_device));
1079 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1080 }
1081 if (in_snd_device != SND_DEVICE_NONE &&
1082 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1083 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1084 __func__,
1085 use_case_table[uc_id],
1086 adev->last_logged_snd_device[uc_id][1],
1087 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1088 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1089 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1090 -1,
1091 in_snd_device,
1092 platform_get_snd_device_name(in_snd_device),
1093 platform_get_snd_device_acdb_id(in_snd_device));
1094 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1095 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001096
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001097 /*
1098 * Limitation: While in call, to do a device switch we need to disable
1099 * and enable both RX and TX devices though one of them is same as current
1100 * device.
1101 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001102 if ((usecase->type == VOICE_CALL) &&
1103 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1104 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001105 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001106 /* Disable sidetone only if voice call already exists */
1107 if (voice_is_call_state_active(adev))
1108 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001109 }
1110
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001111 /* Disable current sound devices */
1112 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001113 disable_audio_route(adev, usecase);
1114 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001115 }
1116
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001117 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001118 disable_audio_route(adev, usecase);
1119 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001120 }
1121
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001122 /* Applicable only on the targets that has external modem.
1123 * New device information should be sent to modem before enabling
1124 * the devices to reduce in-call device switch time.
1125 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001126 if ((usecase->type == VOICE_CALL) &&
1127 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1128 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001129 status = platform_switch_voice_call_enable_device_config(adev->platform,
1130 out_snd_device,
1131 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001132 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001133
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001134 /* Enable new sound devices */
1135 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001136 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1137 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001138 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001139 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001140 }
1141
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001142 if (in_snd_device != SND_DEVICE_NONE) {
1143 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001144 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001145 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001146
Eric Laurentb23d5282013-05-14 15:27:20 -07001147 if (usecase->type == VOICE_CALL)
1148 status = platform_switch_voice_call_device_post(adev->platform,
1149 out_snd_device,
1150 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001151
sangwoo170731f2013-06-08 15:36:36 +09001152 usecase->in_snd_device = in_snd_device;
1153 usecase->out_snd_device = out_snd_device;
1154
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001155 audio_extn_tfa_98xx_set_mode();
1156
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001157 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001158
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001159 /* Applicable only on the targets that has external modem.
1160 * Enable device command should be sent to modem only after
1161 * enabling voice call mixer controls
1162 */
vivek mehta765eb642015-08-07 19:46:06 -07001163 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001164 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1165 out_snd_device,
1166 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001167 /* Enable sidetone only if voice call already exists */
1168 if (voice_is_call_state_active(adev))
1169 voice_set_sidetone(adev, out_snd_device, true);
1170 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001171
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001172 return status;
1173}
1174
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001175static int stop_input_stream(struct stream_in *in)
1176{
1177 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001178 struct audio_usecase *uc_info;
1179 struct audio_device *adev = in->dev;
1180
Eric Laurentc8400632013-02-14 19:04:54 -08001181 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001182
Eric Laurent994a6932013-07-17 11:51:42 -07001183 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001184 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001185 uc_info = get_usecase_from_list(adev, in->usecase);
1186 if (uc_info == NULL) {
1187 ALOGE("%s: Could not find the usecase (%d) in the list",
1188 __func__, in->usecase);
1189 return -EINVAL;
1190 }
1191
Eric Laurent150dbfe2013-02-27 14:31:02 -08001192 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001193 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001194
1195 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001196 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001197
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001198 list_remove(&uc_info->list);
1199 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001200
Eric Laurent994a6932013-07-17 11:51:42 -07001201 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001202 return ret;
1203}
1204
1205int start_input_stream(struct stream_in *in)
1206{
1207 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001208 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001209 struct audio_usecase *uc_info;
1210 struct audio_device *adev = in->dev;
1211
Eric Laurent994a6932013-07-17 11:51:42 -07001212 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001213
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001214 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1215 return -EIO;
1216
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001217 if (in->card_status == CARD_STATUS_OFFLINE ||
1218 adev->card_status == CARD_STATUS_OFFLINE) {
1219 ALOGW("in->card_status or adev->card_status offline, try again");
1220 ret = -EAGAIN;
1221 goto error_config;
1222 }
1223
Eric Laurentb23d5282013-05-14 15:27:20 -07001224 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001225 if (in->pcm_device_id < 0) {
1226 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1227 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001228 ret = -EINVAL;
1229 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001230 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001231
1232 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001233 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1234 uc_info->id = in->usecase;
1235 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001236 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001237 uc_info->devices = in->device;
1238 uc_info->in_snd_device = SND_DEVICE_NONE;
1239 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001240
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001241 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001242
1243 audio_extn_perf_lock_acquire();
1244
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001245 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001246
Eric Laurent0e46adf2016-12-16 12:49:24 -08001247 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001248 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001249 ALOGE("%s: pcm stream not ready", __func__);
1250 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001251 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001252 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001253 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001254 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1255 goto error_open;
1256 }
1257 } else {
1258 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1259 unsigned int pcm_open_retry_count = 0;
1260
1261 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1262 flags |= PCM_MMAP | PCM_NOIRQ;
1263 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1264 } else if (in->realtime) {
1265 flags |= PCM_MMAP | PCM_NOIRQ;
1266 }
1267
1268 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1269 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1270
1271 while (1) {
1272 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1273 flags, &in->config);
1274 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1275 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1276 if (in->pcm != NULL) {
1277 pcm_close(in->pcm);
1278 in->pcm = NULL;
1279 }
1280 if (pcm_open_retry_count-- == 0) {
1281 ret = -EIO;
1282 goto error_open;
1283 }
1284 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1285 continue;
1286 }
1287 break;
1288 }
1289
1290 ALOGV("%s: pcm_prepare", __func__);
1291 ret = pcm_prepare(in->pcm);
1292 if (ret < 0) {
1293 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001294 pcm_close(in->pcm);
1295 in->pcm = NULL;
1296 goto error_open;
1297 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001298 if (in->realtime) {
1299 ret = pcm_start(in->pcm);
1300 if (ret < 0) {
1301 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1302 pcm_close(in->pcm);
1303 in->pcm = NULL;
1304 goto error_open;
1305 }
1306 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001307 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001308 register_in_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001309 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001310 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001311
Eric Laurent0e46adf2016-12-16 12:49:24 -08001312 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001313
1314error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001315 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001316 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001317
1318error_config:
1319 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001320 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001321
1322 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001323}
1324
Eric Laurenta1478072015-09-21 17:21:52 -07001325void lock_input_stream(struct stream_in *in)
1326{
1327 pthread_mutex_lock(&in->pre_lock);
1328 pthread_mutex_lock(&in->lock);
1329 pthread_mutex_unlock(&in->pre_lock);
1330}
1331
1332void lock_output_stream(struct stream_out *out)
1333{
1334 pthread_mutex_lock(&out->pre_lock);
1335 pthread_mutex_lock(&out->lock);
1336 pthread_mutex_unlock(&out->pre_lock);
1337}
1338
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001339/* must be called with out->lock locked */
1340static int send_offload_cmd_l(struct stream_out* out, int command)
1341{
1342 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1343
1344 ALOGVV("%s %d", __func__, command);
1345
1346 cmd->cmd = command;
1347 list_add_tail(&out->offload_cmd_list, &cmd->node);
1348 pthread_cond_signal(&out->offload_cond);
1349 return 0;
1350}
1351
1352/* must be called iwth out->lock locked */
1353static void stop_compressed_output_l(struct stream_out *out)
1354{
1355 out->offload_state = OFFLOAD_STATE_IDLE;
1356 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001357 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001358 if (out->compr != NULL) {
1359 compress_stop(out->compr);
1360 while (out->offload_thread_blocked) {
1361 pthread_cond_wait(&out->cond, &out->lock);
1362 }
1363 }
1364}
1365
1366static void *offload_thread_loop(void *context)
1367{
1368 struct stream_out *out = (struct stream_out *) context;
1369 struct listnode *item;
1370
1371 out->offload_state = OFFLOAD_STATE_IDLE;
1372 out->playback_started = 0;
1373
1374 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1375 set_sched_policy(0, SP_FOREGROUND);
1376 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1377
1378 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001379 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001380 for (;;) {
1381 struct offload_cmd *cmd = NULL;
1382 stream_callback_event_t event;
1383 bool send_callback = false;
1384
1385 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1386 __func__, list_empty(&out->offload_cmd_list),
1387 out->offload_state);
1388 if (list_empty(&out->offload_cmd_list)) {
1389 ALOGV("%s SLEEPING", __func__);
1390 pthread_cond_wait(&out->offload_cond, &out->lock);
1391 ALOGV("%s RUNNING", __func__);
1392 continue;
1393 }
1394
1395 item = list_head(&out->offload_cmd_list);
1396 cmd = node_to_item(item, struct offload_cmd, node);
1397 list_remove(item);
1398
1399 ALOGVV("%s STATE %d CMD %d out->compr %p",
1400 __func__, out->offload_state, cmd->cmd, out->compr);
1401
1402 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1403 free(cmd);
1404 break;
1405 }
1406
1407 if (out->compr == NULL) {
1408 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001409 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001410 pthread_cond_signal(&out->cond);
1411 continue;
1412 }
1413 out->offload_thread_blocked = true;
1414 pthread_mutex_unlock(&out->lock);
1415 send_callback = false;
1416 switch(cmd->cmd) {
1417 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1418 compress_wait(out->compr, -1);
1419 send_callback = true;
1420 event = STREAM_CBK_EVENT_WRITE_READY;
1421 break;
1422 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001423 compress_next_track(out->compr);
1424 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001425 send_callback = true;
1426 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001427 /* Resend the metadata for next iteration */
1428 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001429 break;
1430 case OFFLOAD_CMD_DRAIN:
1431 compress_drain(out->compr);
1432 send_callback = true;
1433 event = STREAM_CBK_EVENT_DRAIN_READY;
1434 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001435 case OFFLOAD_CMD_ERROR:
1436 send_callback = true;
1437 event = STREAM_CBK_EVENT_ERROR;
1438 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001439 default:
1440 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1441 break;
1442 }
Eric Laurenta1478072015-09-21 17:21:52 -07001443 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001444 out->offload_thread_blocked = false;
1445 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001446 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001447 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001448 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001449 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001450 free(cmd);
1451 }
1452
1453 pthread_cond_signal(&out->cond);
1454 while (!list_empty(&out->offload_cmd_list)) {
1455 item = list_head(&out->offload_cmd_list);
1456 list_remove(item);
1457 free(node_to_item(item, struct offload_cmd, node));
1458 }
1459 pthread_mutex_unlock(&out->lock);
1460
1461 return NULL;
1462}
1463
1464static int create_offload_callback_thread(struct stream_out *out)
1465{
1466 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1467 list_init(&out->offload_cmd_list);
1468 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1469 offload_thread_loop, out);
1470 return 0;
1471}
1472
1473static int destroy_offload_callback_thread(struct stream_out *out)
1474{
Eric Laurenta1478072015-09-21 17:21:52 -07001475 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001476 stop_compressed_output_l(out);
1477 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1478
1479 pthread_mutex_unlock(&out->lock);
1480 pthread_join(out->offload_thread, (void **) NULL);
1481 pthread_cond_destroy(&out->offload_cond);
1482
1483 return 0;
1484}
1485
Eric Laurent07eeafd2013-10-06 12:52:49 -07001486static bool allow_hdmi_channel_config(struct audio_device *adev)
1487{
1488 struct listnode *node;
1489 struct audio_usecase *usecase;
1490 bool ret = true;
1491
1492 list_for_each(node, &adev->usecase_list) {
1493 usecase = node_to_item(node, struct audio_usecase, list);
1494 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1495 /*
1496 * If voice call is already existing, do not proceed further to avoid
1497 * disabling/enabling both RX and TX devices, CSD calls, etc.
1498 * Once the voice call done, the HDMI channels can be configured to
1499 * max channels of remaining use cases.
1500 */
1501 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001502 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001503 __func__);
1504 ret = false;
1505 break;
1506 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
Joe Onorato188b6222016-03-01 11:02:27 -08001507 ALOGV("%s: multi channel playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001508 "no change in HDMI channels", __func__);
1509 ret = false;
1510 break;
1511 }
1512 }
1513 }
1514 return ret;
1515}
1516
1517static int check_and_set_hdmi_channels(struct audio_device *adev,
1518 unsigned int channels)
1519{
1520 struct listnode *node;
1521 struct audio_usecase *usecase;
1522
1523 /* Check if change in HDMI channel config is allowed */
1524 if (!allow_hdmi_channel_config(adev))
1525 return 0;
1526
1527 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001528 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001529 return 0;
1530 }
1531
1532 platform_set_hdmi_channels(adev->platform, channels);
1533 adev->cur_hdmi_channels = channels;
1534
1535 /*
1536 * Deroute all the playback streams routed to HDMI so that
1537 * the back end is deactivated. Note that backend will not
1538 * be deactivated if any one stream is connected to it.
1539 */
1540 list_for_each(node, &adev->usecase_list) {
1541 usecase = node_to_item(node, struct audio_usecase, list);
1542 if (usecase->type == PCM_PLAYBACK &&
1543 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001544 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001545 }
1546 }
1547
1548 /*
1549 * Enable all the streams disabled above. Now the HDMI backend
1550 * will be activated with new channel configuration
1551 */
1552 list_for_each(node, &adev->usecase_list) {
1553 usecase = node_to_item(node, struct audio_usecase, list);
1554 if (usecase->type == PCM_PLAYBACK &&
1555 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001556 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001557 }
1558 }
1559
1560 return 0;
1561}
1562
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001563static int stop_output_stream(struct stream_out *out)
1564{
1565 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001566 struct audio_usecase *uc_info;
1567 struct audio_device *adev = out->dev;
1568
Eric Laurent994a6932013-07-17 11:51:42 -07001569 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001570 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001571 uc_info = get_usecase_from_list(adev, out->usecase);
1572 if (uc_info == NULL) {
1573 ALOGE("%s: Could not find the usecase (%d) in the list",
1574 __func__, out->usecase);
1575 return -EINVAL;
1576 }
1577
Haynes Mathew George41f86652014-06-17 14:22:15 -07001578 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1579 if (adev->visualizer_stop_output != NULL)
1580 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1581 if (adev->offload_effects_stop_output != NULL)
1582 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1583 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001584
Eric Laurent150dbfe2013-02-27 14:31:02 -08001585 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001586 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001587
1588 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001589 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001590
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001591 list_remove(&uc_info->list);
1592 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001593
Eric Laurent0499d4f2014-08-25 22:39:29 -05001594 audio_extn_extspk_update(adev->extspk);
1595
Eric Laurent07eeafd2013-10-06 12:52:49 -07001596 /* Must be called after removing the usecase from list */
1597 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1598 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1599
Eric Laurent994a6932013-07-17 11:51:42 -07001600 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001601 return ret;
1602}
1603
1604int start_output_stream(struct stream_out *out)
1605{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001606 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001607 struct audio_usecase *uc_info;
1608 struct audio_device *adev = out->dev;
1609
Eric Laurent994a6932013-07-17 11:51:42 -07001610 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001611 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001612
1613 if (out->card_status == CARD_STATUS_OFFLINE ||
1614 adev->card_status == CARD_STATUS_OFFLINE) {
1615 ALOGW("out->card_status or adev->card_status offline, try again");
1616 ret = -EAGAIN;
1617 goto error_config;
1618 }
1619
Eric Laurentb23d5282013-05-14 15:27:20 -07001620 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001621 if (out->pcm_device_id < 0) {
1622 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1623 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001624 ret = -EINVAL;
1625 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001626 }
1627
1628 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1629 uc_info->id = out->usecase;
1630 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001631 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001632 uc_info->devices = out->devices;
1633 uc_info->in_snd_device = SND_DEVICE_NONE;
1634 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001635
Eric Laurent07eeafd2013-10-06 12:52:49 -07001636 /* This must be called before adding this usecase to the list */
1637 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1638 check_and_set_hdmi_channels(adev, out->config.channels);
1639
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001640 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001641
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001642 audio_extn_perf_lock_acquire();
1643
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001644 select_devices(adev, out->usecase);
1645
Eric Laurent0499d4f2014-08-25 22:39:29 -05001646 audio_extn_extspk_update(adev->extspk);
1647
Andy Hung31aca912014-03-20 17:14:59 -07001648 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001649 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001650 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1651 out->pcm = NULL;
1652 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1653 COMPRESS_IN, &out->compr_config);
1654 if (out->compr && !is_compress_ready(out->compr)) {
1655 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1656 compress_close(out->compr);
1657 out->compr = NULL;
1658 ret = -EIO;
1659 goto error_open;
1660 }
1661 if (out->offload_callback)
1662 compress_nonblock(out->compr, out->non_blocking);
1663
1664 if (adev->visualizer_start_output != NULL)
1665 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1666 if (adev->offload_effects_start_output != NULL)
1667 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
1668 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001669 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001670 ALOGE("%s: pcm stream not ready", __func__);
1671 goto error_open;
1672 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001673 ret = pcm_start(out->pcm);
1674 if (ret < 0) {
1675 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1676 goto error_open;
1677 }
1678 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001679 unsigned int flags = PCM_OUT;
1680 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001681
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001682 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1683 flags |= PCM_MMAP | PCM_NOIRQ;
1684 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001685 } else if (out->realtime) {
1686 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001687 } else
1688 flags |= PCM_MONOTONIC;
1689
1690 while (1) {
1691 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1692 flags, &out->config);
1693 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1694 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1695 if (out->pcm != NULL) {
1696 pcm_close(out->pcm);
1697 out->pcm = NULL;
1698 }
1699 if (pcm_open_retry_count-- == 0) {
1700 ret = -EIO;
1701 goto error_open;
1702 }
1703 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1704 continue;
1705 }
1706 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001707 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001708 ALOGV("%s: pcm_prepare", __func__);
1709 if (pcm_is_ready(out->pcm)) {
1710 ret = pcm_prepare(out->pcm);
1711 if (ret < 0) {
1712 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1713 pcm_close(out->pcm);
1714 out->pcm = NULL;
1715 goto error_open;
1716 }
1717 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001718 if (out->realtime) {
1719 ret = pcm_start(out->pcm);
1720 if (ret < 0) {
1721 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1722 pcm_close(out->pcm);
1723 out->pcm = NULL;
1724 goto error_open;
1725 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001726 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001727 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001728 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001729 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001730 audio_extn_tfa_98xx_enable_speaker();
1731
Eric Laurent994a6932013-07-17 11:51:42 -07001732 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001733 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001734error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001735 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001736 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001737error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001738 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001739}
1740
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001741static int check_input_parameters(uint32_t sample_rate,
1742 audio_format_t format,
1743 int channel_count)
1744{
vivek mehta4ed66e62016-04-15 23:33:34 -07001745 if ((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT)) {
vivek mehtadae44712015-07-27 14:13:18 -07001746 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1747 return -EINVAL;
1748 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001749
vivek mehtadae44712015-07-27 14:13:18 -07001750 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > MAX_CHANNEL_COUNT)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001751 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
vivek mehtadae44712015-07-27 14:13:18 -07001752 channel_count, MIN_CHANNEL_COUNT, MAX_CHANNEL_COUNT);
1753 return -EINVAL;
1754 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001755
1756 switch (sample_rate) {
1757 case 8000:
1758 case 11025:
1759 case 12000:
1760 case 16000:
1761 case 22050:
1762 case 24000:
1763 case 32000:
1764 case 44100:
1765 case 48000:
1766 break;
1767 default:
vivek mehtadae44712015-07-27 14:13:18 -07001768 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001769 return -EINVAL;
1770 }
1771
1772 return 0;
1773}
1774
1775static size_t get_input_buffer_size(uint32_t sample_rate,
1776 audio_format_t format,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001777 int channel_count,
1778 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001779{
1780 size_t size = 0;
1781
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001782 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1783 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001784
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001785 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001786 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001787 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07001788
1789 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001790
Glenn Kasten4f993392014-05-14 07:30:48 -07001791 /* make sure the size is multiple of 32 bytes
1792 * At 48 kHz mono 16-bit PCM:
1793 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1794 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1795 */
1796 size += 0x1f;
1797 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001798
1799 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001800}
1801
1802static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1803{
1804 struct stream_out *out = (struct stream_out *)stream;
1805
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001806 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001807}
1808
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001809static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001810{
1811 return -ENOSYS;
1812}
1813
1814static size_t out_get_buffer_size(const struct audio_stream *stream)
1815{
1816 struct stream_out *out = (struct stream_out *)stream;
1817
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001818 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1819 return out->compr_config.fragment_size;
1820 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001821 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07001822 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001823}
1824
1825static uint32_t out_get_channels(const struct audio_stream *stream)
1826{
1827 struct stream_out *out = (struct stream_out *)stream;
1828
1829 return out->channel_mask;
1830}
1831
1832static audio_format_t out_get_format(const struct audio_stream *stream)
1833{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001834 struct stream_out *out = (struct stream_out *)stream;
1835
1836 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001837}
1838
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001839static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001840{
1841 return -ENOSYS;
1842}
1843
1844static int out_standby(struct audio_stream *stream)
1845{
1846 struct stream_out *out = (struct stream_out *)stream;
1847 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08001848 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001849
Eric Laurent994a6932013-07-17 11:51:42 -07001850 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001851 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001852
Eric Laurenta1478072015-09-21 17:21:52 -07001853 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001854 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001855 if (adev->adm_deregister_stream)
1856 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001857 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001858 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001859 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1860 if (out->pcm) {
1861 pcm_close(out->pcm);
1862 out->pcm = NULL;
1863 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001864 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001865 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08001866 out->playback_started = false;
1867 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001868 } else {
1869 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001870 out->gapless_mdata.encoder_delay = 0;
1871 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001872 if (out->compr != NULL) {
1873 compress_close(out->compr);
1874 out->compr = NULL;
1875 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001876 }
Phil Burkbc991042017-02-24 08:06:44 -08001877 if (do_stop) {
1878 stop_output_stream(out);
1879 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001880 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001881 }
1882 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001883 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001884 return 0;
1885}
1886
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001887static int out_on_error(struct audio_stream *stream)
1888{
1889 struct stream_out *out = (struct stream_out *)stream;
1890 struct audio_device *adev = out->dev;
1891 bool do_standby = false;
1892
1893 lock_output_stream(out);
1894 if (!out->standby) {
1895 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1896 stop_compressed_output_l(out);
1897 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
1898 } else
1899 do_standby = true;
1900 }
1901 pthread_mutex_unlock(&out->lock);
1902
1903 if (do_standby)
1904 return out_standby(&out->stream.common);
1905
1906 return 0;
1907}
1908
Andy Hung7401c7c2016-09-21 12:41:21 -07001909static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001910{
Andy Hung7401c7c2016-09-21 12:41:21 -07001911 struct stream_out *out = (struct stream_out *)stream;
1912
1913 // We try to get the lock for consistency,
1914 // but it isn't necessary for these variables.
1915 // If we're not in standby, we may be blocked on a write.
1916 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
1917 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
1918 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
1919
1920 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07001921 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07001922 }
Andy Hunga452b0a2017-03-15 14:51:15 -07001923
1924 // dump error info
1925 (void)error_log_dump(
1926 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hungfc044e12017-03-20 09:24:22 -07001927 // dump power info (out->power_log may be null)
Andy Hung627acb62017-03-22 16:43:42 -07001928 (void)power_log_dump(
1929 out->power_log, fd, " " /* prefix */, POWER_LOG_LINES, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001930 return 0;
1931}
1932
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001933static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1934{
1935 int ret = 0;
1936 char value[32];
1937 struct compr_gapless_mdata tmp_mdata;
1938
1939 if (!out || !parms) {
1940 return -EINVAL;
1941 }
1942
1943 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1944 if (ret >= 0) {
1945 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
1946 } else {
1947 return -EINVAL;
1948 }
1949
1950 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1951 if (ret >= 0) {
1952 tmp_mdata.encoder_padding = atoi(value);
1953 } else {
1954 return -EINVAL;
1955 }
1956
1957 out->gapless_mdata = tmp_mdata;
1958 out->send_new_metadata = 1;
1959 ALOGV("%s new encoder delay %u and padding %u", __func__,
1960 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1961
1962 return 0;
1963}
1964
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001965static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1966{
1967 return out == adev->primary_output || out == adev->voice_tx_output;
1968}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001969
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001970static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1971{
1972 struct stream_out *out = (struct stream_out *)stream;
1973 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001974 struct audio_usecase *usecase;
1975 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001976 struct str_parms *parms;
1977 char value[32];
1978 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001979 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07001980 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001981
Eric Laurent2e140aa2016-06-30 17:14:46 -07001982 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001983 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001984 parms = str_parms_create_str(kvpairs);
1985 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1986 if (ret >= 0) {
1987 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07001988 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001989 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001990
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001991 /*
1992 * When HDMI cable is unplugged the music playback is paused and
1993 * the policy manager sends routing=0. But the audioflinger
1994 * continues to write data until standby time (3sec).
1995 * As the HDMI core is turned off, the write gets blocked.
1996 * Avoid this by routing audio to speaker until standby.
1997 */
1998 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
1999 val == AUDIO_DEVICE_NONE) {
2000 val = AUDIO_DEVICE_OUT_SPEAKER;
2001 }
2002
2003 /*
2004 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002005 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002006 * the select_devices(). But how do we undo this?
2007 *
2008 * For example, music playback is active on headset (deep-buffer usecase)
2009 * and if we go to ringtones and select a ringtone, low-latency usecase
2010 * will be started on headset+speaker. As we can't enable headset+speaker
2011 * and headset devices at the same time, select_devices() switches the music
2012 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2013 * So when the ringtone playback is completed, how do we undo the same?
2014 *
2015 * We are relying on the out_set_parameters() call on deep-buffer output,
2016 * once the ringtone playback is ended.
2017 * NOTE: We should not check if the current devices are same as new devices.
2018 * Because select_devices() must be called to switch back the music
2019 * playback to headset.
2020 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002021 audio_devices_t new_dev = val;
2022 if (new_dev != AUDIO_DEVICE_NONE) {
2023 bool same_dev = out->devices == new_dev;
2024 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002025
Eric Laurenta7657192014-10-09 21:09:33 -07002026 if (output_drives_call(adev, out)) {
2027 if (!voice_is_in_call(adev)) {
2028 if (adev->mode == AUDIO_MODE_IN_CALL) {
2029 adev->current_call_output = out;
2030 ret = voice_start_call(adev);
2031 }
2032 } else {
2033 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002034 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002035 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002036 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002037
2038 if (!out->standby) {
2039 if (!same_dev) {
2040 ALOGV("update routing change");
2041 out->routing_change = true;
2042 }
2043 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002044 audio_extn_tfa_98xx_update();
vivek mehta0d3637a2016-07-24 09:32:02 -07002045 }
2046
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002047 }
2048
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002049 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002050 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002051
2052 /*handles device and call state changes*/
2053 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002054 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002055
2056 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2057 parse_compress_metadata(out, parms);
2058 }
2059
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002060 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002061 ALOGV("%s: exit: code(%d)", __func__, status);
2062 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002063}
2064
2065static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2066{
2067 struct stream_out *out = (struct stream_out *)stream;
2068 struct str_parms *query = str_parms_create_str(keys);
2069 char *str;
2070 char value[256];
2071 struct str_parms *reply = str_parms_create();
2072 size_t i, j;
2073 int ret;
2074 bool first = true;
Eric Laurent994a6932013-07-17 11:51:42 -07002075 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002076 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2077 if (ret >= 0) {
2078 value[0] = '\0';
2079 i = 0;
2080 while (out->supported_channel_masks[i] != 0) {
2081 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2082 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2083 if (!first) {
2084 strcat(value, "|");
2085 }
2086 strcat(value, out_channels_name_to_enum_table[j].name);
2087 first = false;
2088 break;
2089 }
2090 }
2091 i++;
2092 }
2093 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2094 str = str_parms_to_str(reply);
2095 } else {
2096 str = strdup(keys);
2097 }
2098 str_parms_destroy(query);
2099 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002100 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002101 return str;
2102}
2103
2104static uint32_t out_get_latency(const struct audio_stream_out *stream)
2105{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002106 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002107 struct stream_out *out = (struct stream_out *)stream;
2108
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002109 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2110 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002111 else if ((out->realtime) ||
2112 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002113 // since the buffer won't be filled up faster than realtime,
2114 // return a smaller number
2115 period_ms = (out->af_period_multiplier * out->config.period_size *
2116 1000) / (out->config.rate);
2117 hw_delay = platform_render_latency(out->usecase)/1000;
2118 return period_ms + hw_delay;
2119 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002120
2121 return (out->config.period_count * out->config.period_size * 1000) /
2122 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002123}
2124
2125static int out_set_volume(struct audio_stream_out *stream, float left,
2126 float right)
2127{
Eric Laurenta9024de2013-04-04 09:19:12 -07002128 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002129 int volume[2];
2130
Eric Laurenta9024de2013-04-04 09:19:12 -07002131 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2132 /* only take left channel into account: the API is for stereo anyway */
2133 out->muted = (left == 0.0f);
2134 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002135 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2136 const char *mixer_ctl_name = "Compress Playback Volume";
2137 struct audio_device *adev = out->dev;
2138 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002139 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2140 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002141 /* try with the control based on device id */
2142 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2143 PCM_PLAYBACK);
2144 char ctl_name[128] = {0};
2145 snprintf(ctl_name, sizeof(ctl_name),
2146 "Compress Playback %d Volume", pcm_device_id);
2147 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2148 if (!ctl) {
2149 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2150 return -EINVAL;
2151 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002152 }
2153 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2154 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2155 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2156 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002157 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002158
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002159 return -ENOSYS;
2160}
2161
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002162// note: this call is safe only if the stream_cb is
2163// removed first in close_output_stream (as is done now).
2164static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2165{
2166 if (!stream || !parms)
2167 return;
2168
2169 struct stream_out *out = (struct stream_out *)stream;
2170 struct audio_device *adev = out->dev;
2171
2172 card_status_t status;
2173 int card;
2174 if (parse_snd_card_status(parms, &card, &status) < 0)
2175 return;
2176
2177 pthread_mutex_lock(&adev->lock);
2178 bool valid_cb = (card == adev->snd_card);
2179 pthread_mutex_unlock(&adev->lock);
2180
2181 if (!valid_cb)
2182 return;
2183
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002184 lock_output_stream(out);
2185 if (out->card_status != status)
2186 out->card_status = status;
2187 pthread_mutex_unlock(&out->lock);
2188
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002189 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2190 use_case_table[out->usecase],
2191 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2192
2193 if (status == CARD_STATUS_OFFLINE)
2194 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002195
2196 return;
2197}
2198
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002199#ifdef NO_AUDIO_OUT
2200static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002201 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002202{
2203 struct stream_out *out = (struct stream_out *)stream;
2204
2205 /* No Output device supported other than BT for playback.
2206 * Sleep for the amount of buffer duration
2207 */
Eric Laurenta1478072015-09-21 17:21:52 -07002208 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002209 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2210 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002211 out_get_sample_rate(&out->stream.common));
2212 pthread_mutex_unlock(&out->lock);
2213 return bytes;
2214}
2215#endif
2216
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002217static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2218 size_t bytes)
2219{
2220 struct stream_out *out = (struct stream_out *)stream;
2221 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002222 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002223 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002224
Eric Laurenta1478072015-09-21 17:21:52 -07002225 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002226 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2227 error_code = ERROR_CODE_WRITE;
2228 goto exit;
2229 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002230 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002231 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002232 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002233 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002234 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002235 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002236 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002237 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002238 goto exit;
2239 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002240
2241 if (last_known_cal_step != -1) {
2242 ALOGD("%s: retry previous failed cal level set", __func__);
2243 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2244 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002245 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002246
Andy Hungfc044e12017-03-20 09:24:22 -07002247 // this is always nonzero
2248 const size_t frame_size = audio_stream_out_frame_size(stream);
2249
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002250 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002251 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002252 if (out->send_new_metadata) {
2253 ALOGVV("send new gapless metadata");
2254 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2255 out->send_new_metadata = 0;
2256 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002257 unsigned int avail;
2258 struct timespec tstamp;
2259 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2260 /* Do not limit write size if the available frames count is unknown */
2261 if (ret != 0) {
2262 avail = bytes;
2263 }
2264 if (avail == 0) {
2265 ret = 0;
2266 } else {
2267 if (avail > bytes) {
2268 avail = bytes;
2269 }
2270 ret = compress_write(out->compr, buffer, avail);
2271 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2272 __func__, avail, ret);
2273 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002274
Eric Laurent6e895242013-09-05 16:10:57 -07002275 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002276 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2277 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002278 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002279 compress_start(out->compr);
2280 out->playback_started = 1;
2281 out->offload_state = OFFLOAD_STATE_PLAYING;
2282 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002283 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002284 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07002285 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002286 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002287 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002288 return ret;
2289 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002290 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002291 if (out->pcm) {
2292 if (out->muted)
2293 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002294
Eric Laurent0e46adf2016-12-16 12:49:24 -08002295 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002296
Haynes Mathew George03c40102016-01-29 17:57:48 -08002297 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2298 out->config.rate;
2299 request_out_focus(out, ns);
2300
2301 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2302 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002303 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002304 else
2305 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002306
Haynes Mathew George03c40102016-01-29 17:57:48 -08002307 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002308 } else {
2309 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002310 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002311 }
2312
2313exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002314 // For PCM we always consume the buffer and return #bytes regardless of ret.
2315 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2316 out->written += bytes / (out->config.channels * sizeof(short));
2317 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002318 long long sleeptime_us = 0;
Andy Hungfc044e12017-03-20 09:24:22 -07002319 const int64_t now_ns = audio_utils_get_real_time_ns();
2320
Andy Hung7401c7c2016-09-21 12:41:21 -07002321 if (ret != 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002322 error_log_log(out->error_log, error_code, now_ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002323 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2324 ALOGE_IF(out->pcm != NULL,
2325 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hungfc044e12017-03-20 09:24:22 -07002326 sleeptime_us = bytes * 1000000LL / frame_size /
Andy Hung7401c7c2016-09-21 12:41:21 -07002327 out_get_sample_rate(&out->stream.common);
2328 // usleep not guaranteed for values over 1 second but we don't limit here.
2329 }
2330 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002331
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002332 pthread_mutex_unlock(&out->lock);
2333
2334 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002335 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002336 if (sleeptime_us != 0)
2337 usleep(sleeptime_us);
Andy Hungfc044e12017-03-20 09:24:22 -07002338 } else {
2339 // only log if the data is properly written (out->power_log may be null)
2340 power_log_log(out->power_log, buffer, bytes / frame_size, now_ns);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002341 }
2342 return bytes;
2343}
2344
2345static int out_get_render_position(const struct audio_stream_out *stream,
2346 uint32_t *dsp_frames)
2347{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002348 struct stream_out *out = (struct stream_out *)stream;
2349 *dsp_frames = 0;
2350 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002351 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002352 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002353 unsigned long frames = 0;
2354 // TODO: check return value
2355 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2356 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002357 ALOGVV("%s rendered frames %d sample_rate %d",
2358 __func__, *dsp_frames, out->sample_rate);
2359 }
2360 pthread_mutex_unlock(&out->lock);
2361 return 0;
2362 } else
2363 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002364}
2365
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002366static int out_add_audio_effect(const struct audio_stream *stream __unused,
2367 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002368{
2369 return 0;
2370}
2371
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002372static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2373 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002374{
2375 return 0;
2376}
2377
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002378static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2379 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002380{
2381 return -EINVAL;
2382}
2383
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002384static int out_get_presentation_position(const struct audio_stream_out *stream,
2385 uint64_t *frames, struct timespec *timestamp)
2386{
2387 struct stream_out *out = (struct stream_out *)stream;
Andy Hung7171da22016-03-08 16:58:42 -08002388 int ret = -EINVAL;
Eric Laurent949a0892013-09-20 09:20:13 -07002389 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002390
Eric Laurenta1478072015-09-21 17:21:52 -07002391 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002392
Eric Laurent949a0892013-09-20 09:20:13 -07002393 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2394 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002395 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002396 compress_get_tstamp(out->compr, &dsp_frames,
2397 &out->sample_rate);
2398 ALOGVV("%s rendered frames %ld sample_rate %d",
2399 __func__, dsp_frames, out->sample_rate);
2400 *frames = dsp_frames;
2401 ret = 0;
2402 /* this is the best we can do */
2403 clock_gettime(CLOCK_MONOTONIC, timestamp);
2404 }
2405 } else {
2406 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002407 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002408 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2409 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002410 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002411 // This adjustment accounts for buffering after app processor.
2412 // It is based on estimated DSP latency per use case, rather than exact.
2413 signed_frames -=
2414 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2415
Eric Laurent949a0892013-09-20 09:20:13 -07002416 // It would be unusual for this value to be negative, but check just in case ...
2417 if (signed_frames >= 0) {
2418 *frames = signed_frames;
2419 ret = 0;
2420 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002421 }
2422 }
2423 }
2424
2425 pthread_mutex_unlock(&out->lock);
2426
2427 return ret;
2428}
2429
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002430static int out_set_callback(struct audio_stream_out *stream,
2431 stream_callback_t callback, void *cookie)
2432{
2433 struct stream_out *out = (struct stream_out *)stream;
2434
2435 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002436 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002437 out->offload_callback = callback;
2438 out->offload_cookie = cookie;
2439 pthread_mutex_unlock(&out->lock);
2440 return 0;
2441}
2442
2443static int out_pause(struct audio_stream_out* stream)
2444{
2445 struct stream_out *out = (struct stream_out *)stream;
2446 int status = -ENOSYS;
2447 ALOGV("%s", __func__);
2448 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002449 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002450 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2451 status = compress_pause(out->compr);
2452 out->offload_state = OFFLOAD_STATE_PAUSED;
2453 }
2454 pthread_mutex_unlock(&out->lock);
2455 }
2456 return status;
2457}
2458
2459static int out_resume(struct audio_stream_out* stream)
2460{
2461 struct stream_out *out = (struct stream_out *)stream;
2462 int status = -ENOSYS;
2463 ALOGV("%s", __func__);
2464 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2465 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002466 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002467 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2468 status = compress_resume(out->compr);
2469 out->offload_state = OFFLOAD_STATE_PLAYING;
2470 }
2471 pthread_mutex_unlock(&out->lock);
2472 }
2473 return status;
2474}
2475
2476static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2477{
2478 struct stream_out *out = (struct stream_out *)stream;
2479 int status = -ENOSYS;
2480 ALOGV("%s", __func__);
2481 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002482 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002483 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2484 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2485 else
2486 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2487 pthread_mutex_unlock(&out->lock);
2488 }
2489 return status;
2490}
2491
2492static int out_flush(struct audio_stream_out* stream)
2493{
2494 struct stream_out *out = (struct stream_out *)stream;
2495 ALOGV("%s", __func__);
2496 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002497 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002498 stop_compressed_output_l(out);
2499 pthread_mutex_unlock(&out->lock);
2500 return 0;
2501 }
2502 return -ENOSYS;
2503}
2504
Eric Laurent0e46adf2016-12-16 12:49:24 -08002505static int out_stop(const struct audio_stream_out* stream)
2506{
2507 struct stream_out *out = (struct stream_out *)stream;
2508 struct audio_device *adev = out->dev;
2509 int ret = -ENOSYS;
2510
2511 ALOGV("%s", __func__);
2512 pthread_mutex_lock(&adev->lock);
2513 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2514 out->playback_started && out->pcm != NULL) {
2515 pcm_stop(out->pcm);
2516 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08002517 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002518 }
2519 pthread_mutex_unlock(&adev->lock);
2520 return ret;
2521}
2522
2523static int out_start(const struct audio_stream_out* stream)
2524{
2525 struct stream_out *out = (struct stream_out *)stream;
2526 struct audio_device *adev = out->dev;
2527 int ret = -ENOSYS;
2528
2529 ALOGV("%s", __func__);
2530 pthread_mutex_lock(&adev->lock);
2531 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2532 !out->playback_started && out->pcm != NULL) {
2533 ret = start_output_stream(out);
2534 if (ret == 0) {
2535 out->playback_started = true;
2536 }
2537 }
2538 pthread_mutex_unlock(&adev->lock);
2539 return ret;
2540}
2541
Phil Burkbc991042017-02-24 08:06:44 -08002542/*
2543 * Modify config->period_count based on min_size_frames
2544 */
2545static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
2546{
2547 int periodCountRequested = (min_size_frames + config->period_size - 1)
2548 / config->period_size;
2549 int periodCount = MMAP_PERIOD_COUNT_MIN;
2550
2551 ALOGV("%s original config.period_size = %d config.period_count = %d",
2552 __func__, config->period_size, config->period_count);
2553
2554 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
2555 periodCount *= 2;
2556 }
2557 config->period_count = periodCount;
2558
2559 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
2560}
2561
Eric Laurent0e46adf2016-12-16 12:49:24 -08002562static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2563 int32_t min_size_frames,
2564 struct audio_mmap_buffer_info *info)
2565{
2566 struct stream_out *out = (struct stream_out *)stream;
2567 struct audio_device *adev = out->dev;
2568 int ret = 0;
2569 unsigned int offset1;
2570 unsigned int frames1;
2571 const char *step = "";
2572
2573 ALOGV("%s", __func__);
2574 pthread_mutex_lock(&adev->lock);
2575
2576 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002577 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002578 ret = -EINVAL;
2579 goto exit;
2580 }
2581 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08002582 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002583 ret = -ENOSYS;
2584 goto exit;
2585 }
2586 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
2587 if (out->pcm_device_id < 0) {
2588 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2589 __func__, out->pcm_device_id, out->usecase);
2590 ret = -EINVAL;
2591 goto exit;
2592 }
Phil Burkbc991042017-02-24 08:06:44 -08002593
2594 adjust_mmap_period_count(&out->config, min_size_frames);
2595
Eric Laurent0e46adf2016-12-16 12:49:24 -08002596 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2597 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
2598 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2599 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
2600 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2601 step = "open";
2602 ret = -ENODEV;
2603 goto exit;
2604 }
2605 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
2606 if (ret < 0) {
2607 step = "begin";
2608 goto exit;
2609 }
2610 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
2611 info->burst_size_frames = out->config.period_size;
2612 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
2613
2614 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
2615 info->buffer_size_frames));
2616
2617 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
2618 if (ret < 0) {
2619 step = "commit";
2620 goto exit;
2621 }
Phil Burkbc991042017-02-24 08:06:44 -08002622
2623 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002624 ret = 0;
2625
2626 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
2627 __func__, info->shared_memory_address, info->buffer_size_frames);
2628
2629exit:
2630 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002631 if (out->pcm == NULL) {
2632 ALOGE("%s: %s - %d", __func__, step, ret);
2633 } else {
2634 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08002635 pcm_close(out->pcm);
2636 out->pcm = NULL;
2637 }
2638 }
2639 pthread_mutex_unlock(&adev->lock);
2640 return ret;
2641}
2642
2643static int out_get_mmap_position(const struct audio_stream_out *stream,
2644 struct audio_mmap_position *position)
2645{
2646 struct stream_out *out = (struct stream_out *)stream;
2647 ALOGVV("%s", __func__);
2648 if (position == NULL) {
2649 return -EINVAL;
2650 }
2651 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
2652 return -ENOSYS;
2653 }
2654 if (out->pcm == NULL) {
2655 return -ENOSYS;
2656 }
2657
2658 struct timespec ts = { 0, 0 };
2659 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
2660 if (ret < 0) {
2661 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2662 return ret;
2663 }
Andy Hungfc044e12017-03-20 09:24:22 -07002664 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002665 return 0;
2666}
2667
2668
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002669/** audio_stream_in implementation **/
2670static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2671{
2672 struct stream_in *in = (struct stream_in *)stream;
2673
2674 return in->config.rate;
2675}
2676
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002677static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002678{
2679 return -ENOSYS;
2680}
2681
2682static size_t in_get_buffer_size(const struct audio_stream *stream)
2683{
2684 struct stream_in *in = (struct stream_in *)stream;
2685
Haynes Mathew George03c40102016-01-29 17:57:48 -08002686 return in->config.period_size * in->af_period_multiplier *
2687 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002688}
2689
2690static uint32_t in_get_channels(const struct audio_stream *stream)
2691{
2692 struct stream_in *in = (struct stream_in *)stream;
2693
2694 return in->channel_mask;
2695}
2696
vivek mehta4ed66e62016-04-15 23:33:34 -07002697static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002698{
vivek mehta4ed66e62016-04-15 23:33:34 -07002699 struct stream_in *in = (struct stream_in *)stream;
2700 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002701}
2702
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002703static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002704{
2705 return -ENOSYS;
2706}
2707
2708static int in_standby(struct audio_stream *stream)
2709{
2710 struct stream_in *in = (struct stream_in *)stream;
2711 struct audio_device *adev = in->dev;
2712 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08002713 bool do_stop = true;
2714
Eric Laurent994a6932013-07-17 11:51:42 -07002715 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002716
2717 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002718
2719 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08002720 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002721 audio_extn_sound_trigger_stop_lab(in);
2722 in->standby = true;
2723 }
2724
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002725 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002726 if (adev->adm_deregister_stream)
2727 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2728
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002729 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002730 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002731 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002732 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002733 in->capture_started = false;
2734 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002735 if (in->pcm) {
2736 pcm_close(in->pcm);
2737 in->pcm = NULL;
2738 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002739 adev->enable_voicerx = false;
2740 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08002741 if (do_stop) {
2742 status = stop_input_stream(in);
2743 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002744 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002745 }
2746 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002747 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002748 return status;
2749}
2750
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002751static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002752{
2753 return 0;
2754}
2755
2756static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2757{
2758 struct stream_in *in = (struct stream_in *)stream;
2759 struct audio_device *adev = in->dev;
2760 struct str_parms *parms;
2761 char *str;
2762 char value[32];
2763 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07002764 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002765
Eric Laurent994a6932013-07-17 11:51:42 -07002766 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002767 parms = str_parms_create_str(kvpairs);
2768
2769 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2770
Eric Laurenta1478072015-09-21 17:21:52 -07002771 lock_input_stream(in);
2772
Eric Laurent150dbfe2013-02-27 14:31:02 -08002773 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002774 if (ret >= 0) {
2775 val = atoi(value);
2776 /* no audio source uses val == 0 */
2777 if ((in->source != val) && (val != 0)) {
2778 in->source = val;
2779 }
2780 }
2781
2782 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07002783
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002784 if (ret >= 0) {
2785 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002786 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002787 in->device = val;
2788 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002789 if (!in->standby) {
2790 ALOGV("update input routing change");
2791 in->routing_change = true;
2792 select_devices(adev, in->usecase);
2793 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002794 }
2795 }
2796
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002797 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002798 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002799
2800 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002801 ALOGV("%s: exit: status(%d)", __func__, status);
2802 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002803}
2804
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002805static char* in_get_parameters(const struct audio_stream *stream __unused,
2806 const char *keys __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002807{
2808 return strdup("");
2809}
2810
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002811static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002812{
2813 return 0;
2814}
2815
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002816static void in_snd_mon_cb(void * stream, struct str_parms * parms)
2817{
2818 if (!stream || !parms)
2819 return;
2820
2821 struct stream_in *in = (struct stream_in *)stream;
2822 struct audio_device *adev = in->dev;
2823
2824 card_status_t status;
2825 int card;
2826 if (parse_snd_card_status(parms, &card, &status) < 0)
2827 return;
2828
2829 pthread_mutex_lock(&adev->lock);
2830 bool valid_cb = (card == adev->snd_card);
2831 pthread_mutex_unlock(&adev->lock);
2832
2833 if (!valid_cb)
2834 return;
2835
2836 lock_input_stream(in);
2837 if (in->card_status != status)
2838 in->card_status = status;
2839 pthread_mutex_unlock(&in->lock);
2840
2841 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
2842 use_case_table[in->usecase],
2843 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2844
2845 // a better solution would be to report error back to AF and let
2846 // it put the stream to standby
2847 if (status == CARD_STATUS_OFFLINE)
2848 in_standby(&in->stream.common);
2849
2850 return;
2851}
2852
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002853static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2854 size_t bytes)
2855{
2856 struct stream_in *in = (struct stream_in *)stream;
2857 struct audio_device *adev = in->dev;
2858 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07002859 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002860
Eric Laurenta1478072015-09-21 17:21:52 -07002861 lock_input_stream(in);
2862
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002863 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002864 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002865 /* Read from sound trigger HAL */
2866 audio_extn_sound_trigger_read(in, buffer, bytes);
2867 pthread_mutex_unlock(&in->lock);
2868 return bytes;
2869 }
2870
Eric Laurent0e46adf2016-12-16 12:49:24 -08002871 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
2872 ret = -ENOSYS;
2873 goto exit;
2874 }
2875
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002876 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002877 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002878 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002879 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002880 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002881 goto exit;
2882 }
2883 in->standby = 0;
2884 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002885
Haynes Mathew George03c40102016-01-29 17:57:48 -08002886 //what's the duration requested by the client?
2887 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
2888 in->config.rate;
2889 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002890
Haynes Mathew George03c40102016-01-29 17:57:48 -08002891 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002892 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002893 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002894 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07002895 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002896 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002897 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002898 if (ret < 0) {
2899 ALOGE("Failed to read w/err %s", strerror(errno));
2900 ret = -errno;
2901 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002902 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
2903 if (bytes % 4 == 0) {
2904 /* data from DSP comes in 24_8 format, convert it to 8_24 */
2905 int_buf_stream = buffer;
2906 for (size_t itt=0; itt < bytes/4 ; itt++) {
2907 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07002908 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002909 } else {
2910 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
2911 ret = -EINVAL;
2912 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07002913 }
2914 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002915 }
2916
Haynes Mathew George03c40102016-01-29 17:57:48 -08002917 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002918
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002919 /*
2920 * Instead of writing zeroes here, we could trust the hardware
2921 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002922 * 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 -08002923 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002924 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002925 memset(buffer, 0, bytes);
2926
2927exit:
2928 pthread_mutex_unlock(&in->lock);
2929
2930 if (ret != 0) {
2931 in_standby(&in->stream.common);
2932 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Eric Laurentfdf296a2014-07-03 16:41:51 -07002933 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002934 in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08002935 memset(buffer, 0, bytes); // clear return data
2936 }
2937 if (bytes > 0) {
Andy Hung6ebe5962016-01-15 17:46:57 -08002938 in->frames_read += bytes / audio_stream_in_frame_size(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002939 }
2940 return bytes;
2941}
2942
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002943static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002944{
2945 return 0;
2946}
2947
Andy Hung6ebe5962016-01-15 17:46:57 -08002948static int in_get_capture_position(const struct audio_stream_in *stream,
2949 int64_t *frames, int64_t *time)
2950{
2951 if (stream == NULL || frames == NULL || time == NULL) {
2952 return -EINVAL;
2953 }
2954 struct stream_in *in = (struct stream_in *)stream;
2955 int ret = -ENOSYS;
2956
2957 lock_input_stream(in);
2958 if (in->pcm) {
2959 struct timespec timestamp;
2960 unsigned int avail;
2961 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
2962 *frames = in->frames_read + avail;
2963 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
2964 ret = 0;
2965 }
2966 }
2967 pthread_mutex_unlock(&in->lock);
2968 return ret;
2969}
2970
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002971static int add_remove_audio_effect(const struct audio_stream *stream,
2972 effect_handle_t effect,
2973 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002974{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002975 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002976 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002977 int status = 0;
2978 effect_descriptor_t desc;
2979
2980 status = (*effect)->get_descriptor(effect, &desc);
2981 if (status != 0)
2982 return status;
2983
Eric Laurenta1478072015-09-21 17:21:52 -07002984 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002985 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07002986 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07002987 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07002988 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002989 in->enable_aec != enable &&
2990 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2991 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002992 if (!enable)
2993 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07002994 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2995 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
2996 adev->enable_voicerx = enable;
2997 struct audio_usecase *usecase;
2998 struct listnode *node;
2999 list_for_each(node, &adev->usecase_list) {
3000 usecase = node_to_item(node, struct audio_usecase, list);
3001 if (usecase->type == PCM_PLAYBACK) {
3002 select_devices(adev, usecase->id);
3003 break;
3004 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003005 }
3006 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003007 if (!in->standby)
3008 select_devices(in->dev, in->usecase);
3009 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003010 if (in->enable_ns != enable &&
3011 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3012 in->enable_ns = enable;
3013 if (!in->standby)
3014 select_devices(in->dev, in->usecase);
3015 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003016 pthread_mutex_unlock(&in->dev->lock);
3017 pthread_mutex_unlock(&in->lock);
3018
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003019 return 0;
3020}
3021
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003022static int in_add_audio_effect(const struct audio_stream *stream,
3023 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003024{
Eric Laurent994a6932013-07-17 11:51:42 -07003025 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003026 return add_remove_audio_effect(stream, effect, true);
3027}
3028
3029static int in_remove_audio_effect(const struct audio_stream *stream,
3030 effect_handle_t effect)
3031{
Eric Laurent994a6932013-07-17 11:51:42 -07003032 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003033 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003034}
3035
Eric Laurent0e46adf2016-12-16 12:49:24 -08003036static int in_stop(const struct audio_stream_in* stream)
3037{
3038 struct stream_in *in = (struct stream_in *)stream;
3039 struct audio_device *adev = in->dev;
3040
3041 int ret = -ENOSYS;
3042 ALOGV("%s", __func__);
3043 pthread_mutex_lock(&adev->lock);
3044 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3045 in->capture_started && in->pcm != NULL) {
3046 pcm_stop(in->pcm);
3047 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003048 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003049 }
3050 pthread_mutex_unlock(&adev->lock);
3051 return ret;
3052}
3053
3054static int in_start(const struct audio_stream_in* stream)
3055{
3056 struct stream_in *in = (struct stream_in *)stream;
3057 struct audio_device *adev = in->dev;
3058 int ret = -ENOSYS;
3059
3060 ALOGV("%s in %p", __func__, in);
3061 pthread_mutex_lock(&adev->lock);
3062 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3063 !in->capture_started && in->pcm != NULL) {
3064 if (!in->capture_started) {
3065 ret = start_input_stream(in);
3066 if (ret == 0) {
3067 in->capture_started = true;
3068 }
3069 }
3070 }
3071 pthread_mutex_unlock(&adev->lock);
3072 return ret;
3073}
3074
3075static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3076 int32_t min_size_frames,
3077 struct audio_mmap_buffer_info *info)
3078{
3079 struct stream_in *in = (struct stream_in *)stream;
3080 struct audio_device *adev = in->dev;
3081 int ret = 0;
3082 unsigned int offset1;
3083 unsigned int frames1;
3084 const char *step = "";
3085
3086 pthread_mutex_lock(&adev->lock);
3087 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003088
Eric Laurent0e46adf2016-12-16 12:49:24 -08003089 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003090 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003091 ret = -EINVAL;
3092 goto exit;
3093 }
3094 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003095 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003096 ALOGV("%s in %p", __func__, in);
3097 ret = -ENOSYS;
3098 goto exit;
3099 }
3100 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3101 if (in->pcm_device_id < 0) {
3102 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3103 __func__, in->pcm_device_id, in->usecase);
3104 ret = -EINVAL;
3105 goto exit;
3106 }
Phil Burkbc991042017-02-24 08:06:44 -08003107
3108 adjust_mmap_period_count(&in->config, min_size_frames);
3109
Eric Laurent0e46adf2016-12-16 12:49:24 -08003110 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3111 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3112 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3113 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3114 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3115 step = "open";
3116 ret = -ENODEV;
3117 goto exit;
3118 }
3119
3120 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3121 if (ret < 0) {
3122 step = "begin";
3123 goto exit;
3124 }
3125 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
3126 info->burst_size_frames = in->config.period_size;
3127 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3128
3129 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(in->pcm,
3130 info->buffer_size_frames));
3131
3132 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3133 if (ret < 0) {
3134 step = "commit";
3135 goto exit;
3136 }
3137
Phil Burkbc991042017-02-24 08:06:44 -08003138 in->standby = false;
3139 ret = 0;
3140
Eric Laurent0e46adf2016-12-16 12:49:24 -08003141 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3142 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003143
3144exit:
3145 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003146 if (in->pcm == NULL) {
3147 ALOGE("%s: %s - %d", __func__, step, ret);
3148 } else {
3149 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003150 pcm_close(in->pcm);
3151 in->pcm = NULL;
3152 }
3153 }
3154 pthread_mutex_unlock(&adev->lock);
3155 return ret;
3156}
3157
3158static int in_get_mmap_position(const struct audio_stream_in *stream,
3159 struct audio_mmap_position *position)
3160{
3161 struct stream_in *in = (struct stream_in *)stream;
3162 ALOGVV("%s", __func__);
3163 if (position == NULL) {
3164 return -EINVAL;
3165 }
3166 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
3167 return -ENOSYS;
3168 }
3169 if (in->pcm == NULL) {
3170 return -ENOSYS;
3171 }
3172 struct timespec ts = { 0, 0 };
3173 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
3174 if (ret < 0) {
3175 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3176 return ret;
3177 }
Andy Hungfc044e12017-03-20 09:24:22 -07003178 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003179 return 0;
3180}
3181
3182
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003183static int adev_open_output_stream(struct audio_hw_device *dev,
3184 audio_io_handle_t handle,
3185 audio_devices_t devices,
3186 audio_output_flags_t flags,
3187 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003188 struct audio_stream_out **stream_out,
3189 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003190{
3191 struct audio_device *adev = (struct audio_device *)dev;
3192 struct stream_out *out;
3193 int i, ret;
3194
Eric Laurent994a6932013-07-17 11:51:42 -07003195 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003196 __func__, config->sample_rate, config->channel_mask, devices, flags);
3197 *stream_out = NULL;
3198 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3199
3200 if (devices == AUDIO_DEVICE_NONE)
3201 devices = AUDIO_DEVICE_OUT_SPEAKER;
3202
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003203 out->flags = flags;
3204 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003205 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003206 out->format = config->format;
3207 out->sample_rate = config->sample_rate;
3208 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3209 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003210 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003211
3212 /* Init use case and pcm_config */
3213 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
Eric Laurent7f245042013-09-30 19:22:50 -07003214 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003215 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003216 pthread_mutex_lock(&adev->lock);
3217 ret = read_hdmi_channel_masks(out);
3218 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003219 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003220 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003221
3222 if (config->sample_rate == 0)
3223 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3224 if (config->channel_mask == 0)
3225 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Eric Laurentad1cec22015-12-16 10:12:27 -08003226 if (config->format == AUDIO_FORMAT_DEFAULT)
3227 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003228
3229 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003230 out->sample_rate = config->sample_rate;
Eric Laurentad1cec22015-12-16 10:12:27 -08003231 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003232 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3233 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003234 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003235 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003236 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003237 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003238 pthread_mutex_lock(&adev->lock);
3239 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3240 pthread_mutex_unlock(&adev->lock);
3241
3242 // reject offload during card offline to allow
3243 // fallback to s/w paths
3244 if (offline) {
3245 ret = -ENODEV;
3246 goto error_open;
3247 }
3248
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003249 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3250 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3251 ALOGE("%s: Unsupported Offload information", __func__);
3252 ret = -EINVAL;
3253 goto error_open;
3254 }
3255 if (!is_supported_format(config->offload_info.format)) {
3256 ALOGE("%s: Unsupported audio format", __func__);
3257 ret = -EINVAL;
3258 goto error_open;
3259 }
3260
3261 out->compr_config.codec = (struct snd_codec *)
3262 calloc(1, sizeof(struct snd_codec));
3263
3264 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3265 if (config->offload_info.channel_mask)
3266 out->channel_mask = config->offload_info.channel_mask;
3267 else if (config->channel_mask)
3268 out->channel_mask = config->channel_mask;
3269 out->format = config->offload_info.format;
3270 out->sample_rate = config->offload_info.sample_rate;
3271
3272 out->stream.set_callback = out_set_callback;
3273 out->stream.pause = out_pause;
3274 out->stream.resume = out_resume;
3275 out->stream.drain = out_drain;
3276 out->stream.flush = out_flush;
3277
3278 out->compr_config.codec->id =
3279 get_snd_codec_id(config->offload_info.format);
3280 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3281 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07003282 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003283 out->compr_config.codec->bit_rate =
3284 config->offload_info.bit_rate;
3285 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003286 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003287 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3288
3289 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3290 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003291
3292 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003293 create_offload_callback_thread(out);
3294 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3295 __func__, config->offload_info.version,
3296 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003297 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3298 if (config->sample_rate == 0)
3299 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3300 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3301 config->sample_rate != 8000) {
3302 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3303 ret = -EINVAL;
3304 goto error_open;
3305 }
3306 out->sample_rate = config->sample_rate;
3307 out->config.rate = config->sample_rate;
3308 if (config->format == AUDIO_FORMAT_DEFAULT)
3309 config->format = AUDIO_FORMAT_PCM_16_BIT;
3310 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3311 config->format = AUDIO_FORMAT_PCM_16_BIT;
3312 ret = -EINVAL;
3313 goto error_open;
3314 }
3315 out->format = config->format;
3316 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3317 out->config = pcm_config_afe_proxy_playback;
3318 adev->voice_tx_output = out;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003319 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003320 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3321 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3322 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003323 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
3324 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3325 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003326 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3327 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003328 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003329 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003330 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3331 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3332 out->config = pcm_config_mmap_playback;
3333 out->stream.start = out_start;
3334 out->stream.stop = out_stop;
3335 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3336 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003337 } else {
3338 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3339 out->config = pcm_config_low_latency;
3340 }
3341 if (config->format != audio_format_from_pcm_format(out->config.format)) {
3342 if (k_enable_extended_precision
3343 && pcm_params_format_test(adev->use_case_table[out->usecase],
3344 pcm_format_from_audio_format(config->format))) {
3345 out->config.format = pcm_format_from_audio_format(config->format);
3346 /* out->format already set to config->format */
3347 } else {
3348 /* deny the externally proposed config format
3349 * and use the one specified in audio_hw layer configuration.
3350 * Note: out->format is returned by out->stream.common.get_format()
3351 * and is used to set config->format in the code several lines below.
3352 */
3353 out->format = audio_format_from_pcm_format(out->config.format);
3354 }
3355 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003356 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003357 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07003358 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3359 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003360
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003361 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003362 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003363 adev->primary_output = out;
3364 else {
3365 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003366 ret = -EEXIST;
3367 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003368 }
3369 }
3370
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003371 /* Check if this usecase is already existing */
3372 pthread_mutex_lock(&adev->lock);
3373 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3374 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003375 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003376 ret = -EEXIST;
3377 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003378 }
3379 pthread_mutex_unlock(&adev->lock);
3380
3381 out->stream.common.get_sample_rate = out_get_sample_rate;
3382 out->stream.common.set_sample_rate = out_set_sample_rate;
3383 out->stream.common.get_buffer_size = out_get_buffer_size;
3384 out->stream.common.get_channels = out_get_channels;
3385 out->stream.common.get_format = out_get_format;
3386 out->stream.common.set_format = out_set_format;
3387 out->stream.common.standby = out_standby;
3388 out->stream.common.dump = out_dump;
3389 out->stream.common.set_parameters = out_set_parameters;
3390 out->stream.common.get_parameters = out_get_parameters;
3391 out->stream.common.add_audio_effect = out_add_audio_effect;
3392 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3393 out->stream.get_latency = out_get_latency;
3394 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003395#ifdef NO_AUDIO_OUT
3396 out->stream.write = out_write_for_no_output;
3397#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003398 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003399#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003400 out->stream.get_render_position = out_get_render_position;
3401 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003402 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003403
Eric Laurent0e46adf2016-12-16 12:49:24 -08003404 if (out->realtime)
3405 out->af_period_multiplier = af_period_multiplier;
3406 else
3407 out->af_period_multiplier = 1;
3408
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003409 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003410 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003411 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003412
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003413 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003414 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003415 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3416
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003417 config->format = out->stream.common.get_format(&out->stream.common);
3418 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3419 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3420
Andy Hunga452b0a2017-03-15 14:51:15 -07003421 out->error_log = error_log_create(
3422 ERROR_LOG_ENTRIES,
3423 1000000000 /* aggregate consecutive identical errors within one second in ns */);
3424
Andy Hungfc044e12017-03-20 09:24:22 -07003425 const size_t POWER_LOG_FRAMES_PER_ENTRY =
3426 config->sample_rate * POWER_LOG_SAMPLING_INTERVAL_MS / 1000;
3427 // power_log may be null if the format is not supported
3428 out->power_log = power_log_create(
3429 config->sample_rate,
3430 audio_channel_count_from_out_mask(config->channel_mask),
3431 config->format,
3432 POWER_LOG_ENTRIES,
3433 POWER_LOG_FRAMES_PER_ENTRY);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003434
3435 /*
3436 By locking output stream before registering, we allow the callback
3437 to update stream's state only after stream's initial state is set to
3438 adev state.
3439 */
3440 lock_output_stream(out);
3441 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3442 pthread_mutex_lock(&adev->lock);
3443 out->card_status = adev->card_status;
3444 pthread_mutex_unlock(&adev->lock);
3445 pthread_mutex_unlock(&out->lock);
3446
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003447 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003448
Eric Laurent994a6932013-07-17 11:51:42 -07003449 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003450 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003451
3452error_open:
3453 free(out);
3454 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003455 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003456 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003457}
3458
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003459static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003460 struct audio_stream_out *stream)
3461{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003462 struct stream_out *out = (struct stream_out *)stream;
3463 struct audio_device *adev = out->dev;
3464
Eric Laurent994a6932013-07-17 11:51:42 -07003465 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003466
3467 // must deregister from sndmonitor first to prevent races
3468 // between the callback and close_stream
3469 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003470 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003471 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3472 destroy_offload_callback_thread(out);
3473
3474 if (out->compr_config.codec != NULL)
3475 free(out->compr_config.codec);
3476 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003477
3478 if (adev->voice_tx_output == out)
3479 adev->voice_tx_output = NULL;
3480
Andy Hungfc044e12017-03-20 09:24:22 -07003481 power_log_destroy(out->power_log);
3482 out->power_log = NULL;
3483
Andy Hunga452b0a2017-03-15 14:51:15 -07003484 error_log_destroy(out->error_log);
3485 out->error_log = NULL;
3486
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003487 pthread_cond_destroy(&out->cond);
3488 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003489 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003490 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003491}
3492
3493static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3494{
3495 struct audio_device *adev = (struct audio_device *)dev;
3496 struct str_parms *parms;
3497 char *str;
3498 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003499 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003500 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003501 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003502
Joe Onorato188b6222016-03-01 11:02:27 -08003503 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003504
3505 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003506
3507 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003508 status = voice_set_parameters(adev, parms);
3509 if (status != 0) {
3510 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003511 }
3512
3513 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3514 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003515 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003516 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3517 adev->bluetooth_nrec = true;
3518 else
3519 adev->bluetooth_nrec = false;
3520 }
3521
3522 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3523 if (ret >= 0) {
3524 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3525 adev->screen_off = false;
3526 else
3527 adev->screen_off = true;
3528 }
3529
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003530 ret = str_parms_get_int(parms, "rotation", &val);
3531 if (ret >= 0) {
3532 bool reverse_speakers = false;
3533 switch(val) {
3534 // FIXME: note that the code below assumes that the speakers are in the correct placement
3535 // relative to the user when the device is rotated 90deg from its default rotation. This
3536 // assumption is device-specific, not platform-specific like this code.
3537 case 270:
3538 reverse_speakers = true;
3539 break;
3540 case 0:
3541 case 90:
3542 case 180:
3543 break;
3544 default:
3545 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003546 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003547 }
Eric Laurent03f09432014-03-25 18:09:11 -07003548 if (status == 0) {
Ravi Kumar Alamanda1f60cf82015-04-23 19:45:17 -07003549 platform_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003550 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003551 }
3552
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003553 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3554 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003555 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003556 }
3557
David Linee3fe402017-03-13 10:00:42 -07003558 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3559 if (ret >= 0) {
3560 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
3561 if (device == AUDIO_DEVICE_OUT_USB_DEVICE) {
3562 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3563 if (ret >= 0) {
3564 const int card = atoi(value);
3565 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, card);
3566 }
3567 } else if (device == AUDIO_DEVICE_IN_USB_DEVICE) {
3568 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3569 if (ret >= 0) {
3570 const int card = atoi(value);
3571 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, card);
3572 }
3573 }
3574 }
3575
3576 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3577 if (ret >= 0) {
3578 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
3579 if (device == AUDIO_DEVICE_OUT_USB_DEVICE) {
3580 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3581 if (ret >= 0) {
3582 const int card = atoi(value);
3583
3584 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, card);
3585 }
3586 } else if (device == AUDIO_DEVICE_IN_USB_DEVICE) {
3587 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3588 if (ret >= 0) {
3589 const int card = atoi(value);
3590 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, card);
3591 }
3592 }
3593 }
3594
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08003595 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003596done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003597 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003598 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07003599 ALOGV("%s: exit with code(%d)", __func__, status);
3600 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003601}
3602
3603static char* adev_get_parameters(const struct audio_hw_device *dev,
3604 const char *keys)
3605{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003606 struct audio_device *adev = (struct audio_device *)dev;
3607 struct str_parms *reply = str_parms_create();
3608 struct str_parms *query = str_parms_create_str(keys);
3609 char *str;
3610
3611 pthread_mutex_lock(&adev->lock);
3612
3613 voice_get_parameters(adev, query, reply);
3614 str = str_parms_to_str(reply);
3615 str_parms_destroy(query);
3616 str_parms_destroy(reply);
3617
3618 pthread_mutex_unlock(&adev->lock);
3619 ALOGV("%s: exit: returns - %s", __func__, str);
3620 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003621}
3622
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003623static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003624{
3625 return 0;
3626}
3627
Haynes Mathew George5191a852013-09-11 14:19:36 -07003628static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3629{
3630 int ret;
3631 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003632
Eric Laurent4cc4ce12014-09-10 13:21:01 -05003633 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
3634
Haynes Mathew George5191a852013-09-11 14:19:36 -07003635 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003636 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003637 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003638
Haynes Mathew George5191a852013-09-11 14:19:36 -07003639 return ret;
3640}
3641
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003642static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003643{
3644 return -ENOSYS;
3645}
3646
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003647static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3648 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003649{
3650 return -ENOSYS;
3651}
3652
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003653static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003654{
3655 return -ENOSYS;
3656}
3657
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003658static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003659{
3660 return -ENOSYS;
3661}
3662
3663static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3664{
3665 struct audio_device *adev = (struct audio_device *)dev;
3666
3667 pthread_mutex_lock(&adev->lock);
3668 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07003669 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003670 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07003671 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3672 voice_is_in_call(adev)) {
3673 voice_stop_call(adev);
3674 adev->current_call_output = NULL;
3675 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003676 }
3677 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003678
3679 audio_extn_extspk_set_mode(adev->extspk, mode);
3680
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003681 return 0;
3682}
3683
3684static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3685{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003686 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003687 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003688
Eric Laurent2bafff12016-03-17 12:17:23 -07003689 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003690 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08003691 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
3692 ret = audio_extn_hfp_set_mic_mute(adev, state);
3693 } else {
3694 ret = voice_set_mic_mute(adev, state);
3695 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003696 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00003697 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003698
3699 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003700}
3701
3702static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3703{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003704 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003705 return 0;
3706}
3707
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003708static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003709 const struct audio_config *config)
3710{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003711 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003712
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003713 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3714 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003715}
3716
3717static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003718 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003719 audio_devices_t devices,
3720 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003721 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07003722 audio_input_flags_t flags,
3723 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05003724 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003725{
3726 struct audio_device *adev = (struct audio_device *)dev;
3727 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003728 int ret = 0, buffer_size, frame_size;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003729 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003730 bool is_low_latency = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003731
Eric Laurent994a6932013-07-17 11:51:42 -07003732 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003733 *stream_in = NULL;
3734 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3735 return -EINVAL;
3736
Zheng Zhang6185d572016-12-01 20:35:17 +08003737 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 -08003738 return -EINVAL;
3739
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003740 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
3741
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003742 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003743 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003744
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003745 in->stream.common.get_sample_rate = in_get_sample_rate;
3746 in->stream.common.set_sample_rate = in_set_sample_rate;
3747 in->stream.common.get_buffer_size = in_get_buffer_size;
3748 in->stream.common.get_channels = in_get_channels;
3749 in->stream.common.get_format = in_get_format;
3750 in->stream.common.set_format = in_set_format;
3751 in->stream.common.standby = in_standby;
3752 in->stream.common.dump = in_dump;
3753 in->stream.common.set_parameters = in_set_parameters;
3754 in->stream.common.get_parameters = in_get_parameters;
3755 in->stream.common.add_audio_effect = in_add_audio_effect;
3756 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3757 in->stream.set_gain = in_set_gain;
3758 in->stream.read = in_read;
3759 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08003760 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003761
3762 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003763 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003764 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003765 in->standby = 1;
3766 in->channel_mask = config->channel_mask;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003767 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003768 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003769
vivek mehta57ff9b52016-04-28 14:13:08 -07003770 // restrict 24 bit capture for unprocessed source only
3771 // for other sources if 24 bit requested reject 24 and set 16 bit capture only
3772 if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07003773 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07003774 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
3775 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
3776 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
3777 bool ret_error = false;
3778 /* 24 bit is restricted to UNPROCESSED source only,also format supported
3779 from HAL is 8_24
3780 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
3781 8_24 return error indicating supported format is 8_24
3782 *> In case of any other source requesting 24 bit or float return error
3783 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07003784
vivek mehta57ff9b52016-04-28 14:13:08 -07003785 on error flinger will retry with supported format passed
3786 */
3787 if (source != AUDIO_SOURCE_UNPROCESSED) {
3788 config->format = AUDIO_FORMAT_PCM_16_BIT;
3789 ret_error = true;
3790 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
3791 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
3792 ret_error = true;
3793 }
3794
3795 if (ret_error) {
3796 ret = -EINVAL;
3797 goto err_open;
3798 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003799 }
3800
vivek mehta57ff9b52016-04-28 14:13:08 -07003801 in->format = config->format;
3802
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003803 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003804 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
3805 if (config->sample_rate == 0)
3806 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3807 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3808 config->sample_rate != 8000) {
3809 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3810 ret = -EINVAL;
3811 goto err_open;
3812 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003813
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003814 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3815 config->format = AUDIO_FORMAT_PCM_16_BIT;
3816 ret = -EINVAL;
3817 goto err_open;
3818 }
3819
3820 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3821 in->config = pcm_config_afe_proxy_record;
3822 } else {
3823 in->usecase = USECASE_AUDIO_RECORD;
3824 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08003825 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003826 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07003827#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003828 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07003829#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08003830 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003831 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08003832 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003833 frame_size = audio_stream_in_frame_size(&in->stream);
3834 buffer_size = get_input_buffer_size(config->sample_rate,
3835 config->format,
3836 channel_count,
3837 is_low_latency);
3838 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003839 in->config.rate = config->sample_rate;
3840 in->af_period_multiplier = 1;
3841 } else {
3842 // period size is left untouched for rt mode playback
3843 in->config = pcm_config_audio_capture_rt;
3844 in->af_period_multiplier = af_period_multiplier;
3845 }
3846 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
3847 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
3848 in->usecase = USECASE_AUDIO_RECORD_MMAP;
3849 in->config = pcm_config_mmap_capture;
3850 in->stream.start = in_start;
3851 in->stream.stop = in_stop;
3852 in->stream.create_mmap_buffer = in_create_mmap_buffer;
3853 in->stream.get_mmap_position = in_get_mmap_position;
3854 in->af_period_multiplier = 1;
3855 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
3856 } else {
3857 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003858 frame_size = audio_stream_in_frame_size(&in->stream);
3859 buffer_size = get_input_buffer_size(config->sample_rate,
3860 config->format,
3861 channel_count,
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003862 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003863 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003864 in->config.rate = config->sample_rate;
3865 in->af_period_multiplier = 1;
3866 }
3867 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
3868 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003869 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003870
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003871 in->config.channels = channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003872
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003873 /* This stream could be for sound trigger lab,
3874 get sound trigger pcm if present */
3875 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003876
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003877 lock_input_stream(in);
3878 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
3879 pthread_mutex_lock(&adev->lock);
3880 in->card_status = adev->card_status;
3881 pthread_mutex_unlock(&adev->lock);
3882 pthread_mutex_unlock(&in->lock);
3883
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003884 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003885 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003886 return 0;
3887
3888err_open:
3889 free(in);
3890 *stream_in = NULL;
3891 return ret;
3892}
3893
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003894static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003895 struct audio_stream_in *stream)
3896{
Eric Laurent994a6932013-07-17 11:51:42 -07003897 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003898
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003899 // must deregister from sndmonitor first to prevent races
3900 // between the callback and close_stream
3901 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003902 in_standby(&stream->common);
3903 free(stream);
3904
3905 return;
3906}
3907
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003908static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003909{
3910 return 0;
3911}
3912
Andy Hung31aca912014-03-20 17:14:59 -07003913/* verifies input and output devices and their capabilities.
3914 *
3915 * This verification is required when enabling extended bit-depth or
3916 * sampling rates, as not all qcom products support it.
3917 *
3918 * Suitable for calling only on initialization such as adev_open().
3919 * It fills the audio_device use_case_table[] array.
3920 *
3921 * Has a side-effect that it needs to configure audio routing / devices
3922 * in order to power up the devices and read the device parameters.
3923 * It does not acquire any hw device lock. Should restore the devices
3924 * back to "normal state" upon completion.
3925 */
3926static int adev_verify_devices(struct audio_device *adev)
3927{
3928 /* enumeration is a bit difficult because one really wants to pull
3929 * the use_case, device id, etc from the hidden pcm_device_table[].
3930 * In this case there are the following use cases and device ids.
3931 *
3932 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
3933 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
3934 * [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
3935 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
3936 * [USECASE_AUDIO_RECORD] = {0, 0},
3937 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
3938 * [USECASE_VOICE_CALL] = {2, 2},
3939 *
3940 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_MULTI_CH omitted.
3941 * USECASE_VOICE_CALL omitted, but possible for either input or output.
3942 */
3943
3944 /* should be the usecases enabled in adev_open_input_stream() */
3945 static const int test_in_usecases[] = {
3946 USECASE_AUDIO_RECORD,
3947 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
3948 };
3949 /* should be the usecases enabled in adev_open_output_stream()*/
3950 static const int test_out_usecases[] = {
3951 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
3952 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
3953 };
3954 static const usecase_type_t usecase_type_by_dir[] = {
3955 PCM_PLAYBACK,
3956 PCM_CAPTURE,
3957 };
3958 static const unsigned flags_by_dir[] = {
3959 PCM_OUT,
3960 PCM_IN,
3961 };
3962
3963 size_t i;
3964 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003965 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07003966 char info[512]; /* for possible debug info */
3967
3968 for (dir = 0; dir < 2; ++dir) {
3969 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
3970 const unsigned flags_dir = flags_by_dir[dir];
3971 const size_t testsize =
3972 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
3973 const int *testcases =
3974 dir ? test_in_usecases : test_out_usecases;
3975 const audio_devices_t audio_device =
3976 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
3977
3978 for (i = 0; i < testsize; ++i) {
3979 const audio_usecase_t audio_usecase = testcases[i];
3980 int device_id;
3981 snd_device_t snd_device;
3982 struct pcm_params **pparams;
3983 struct stream_out out;
3984 struct stream_in in;
3985 struct audio_usecase uc_info;
3986 int retval;
3987
3988 pparams = &adev->use_case_table[audio_usecase];
3989 pcm_params_free(*pparams); /* can accept null input */
3990 *pparams = NULL;
3991
3992 /* find the device ID for the use case (signed, for error) */
3993 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
3994 if (device_id < 0)
3995 continue;
3996
3997 /* prepare structures for device probing */
3998 memset(&uc_info, 0, sizeof(uc_info));
3999 uc_info.id = audio_usecase;
4000 uc_info.type = usecase_type;
4001 if (dir) {
4002 adev->active_input = &in;
4003 memset(&in, 0, sizeof(in));
4004 in.device = audio_device;
4005 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4006 uc_info.stream.in = &in;
4007 } else {
4008 adev->active_input = NULL;
4009 }
4010 memset(&out, 0, sizeof(out));
4011 out.devices = audio_device; /* only field needed in select_devices */
4012 uc_info.stream.out = &out;
4013 uc_info.devices = audio_device;
4014 uc_info.in_snd_device = SND_DEVICE_NONE;
4015 uc_info.out_snd_device = SND_DEVICE_NONE;
4016 list_add_tail(&adev->usecase_list, &uc_info.list);
4017
4018 /* select device - similar to start_(in/out)put_stream() */
4019 retval = select_devices(adev, audio_usecase);
4020 if (retval >= 0) {
4021 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4022#if LOG_NDEBUG == 0
4023 if (*pparams) {
4024 ALOGV("%s: (%s) card %d device %d", __func__,
4025 dir ? "input" : "output", card_id, device_id);
4026 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004027 } else {
4028 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4029 }
4030#endif
4031 }
4032
4033 /* deselect device - similar to stop_(in/out)put_stream() */
4034 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004035 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004036 /* 2. Disable the rx device */
4037 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004038 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004039 list_remove(&uc_info.list);
4040 }
4041 }
4042 adev->active_input = NULL; /* restore adev state */
4043 return 0;
4044}
4045
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004046static int adev_close(hw_device_t *device)
4047{
Andy Hung31aca912014-03-20 17:14:59 -07004048 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004049 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004050
4051 if (!adev)
4052 return 0;
4053
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004054 audio_extn_tfa_98xx_deinit();
4055
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004056 audio_extn_snd_mon_unregister_listener(adev);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004057 pthread_mutex_lock(&adev_init_lock);
4058
4059 if ((--audio_device_ref_count) == 0) {
4060 audio_route_free(adev->audio_route);
4061 free(adev->snd_dev_ref_cnt);
4062 platform_deinit(adev->platform);
4063 audio_extn_extspk_deinit(adev->extspk);
4064 audio_extn_sound_trigger_deinit(adev);
4065 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4066 pcm_params_free(adev->use_case_table[i]);
4067 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004068 if (adev->adm_deinit)
4069 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004070 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004071 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004072
4073 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004074
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004075 return 0;
4076}
4077
Glenn Kasten4f993392014-05-14 07:30:48 -07004078/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4079 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4080 * just that it _might_ work.
4081 */
4082static int period_size_is_plausible_for_low_latency(int period_size)
4083{
4084 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004085 case 48:
4086 case 96:
4087 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004088 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004089 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004090 case 240:
4091 case 320:
4092 case 480:
4093 return 1;
4094 default:
4095 return 0;
4096 }
4097}
4098
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004099static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4100{
4101 int card;
4102 card_status_t status;
4103
4104 if (!parms)
4105 return;
4106
4107 if (parse_snd_card_status(parms, &card, &status) < 0)
4108 return;
4109
4110 pthread_mutex_lock(&adev->lock);
4111 bool valid_cb = (card == adev->snd_card);
4112 if (valid_cb) {
4113 if (adev->card_status != status) {
4114 adev->card_status = status;
4115 platform_snd_card_update(adev->platform, status);
4116 }
4117 }
4118 pthread_mutex_unlock(&adev->lock);
4119 return;
4120}
4121
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004122static int adev_open(const hw_module_t *module, const char *name,
4123 hw_device_t **device)
4124{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004125 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004126
Eric Laurent2bafff12016-03-17 12:17:23 -07004127 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004128 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004129 pthread_mutex_lock(&adev_init_lock);
4130 if (audio_device_ref_count != 0) {
4131 *device = &adev->device.common;
4132 audio_device_ref_count++;
4133 ALOGV("%s: returning existing instance of adev", __func__);
4134 ALOGV("%s: exit", __func__);
4135 pthread_mutex_unlock(&adev_init_lock);
4136 return 0;
4137 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004138 adev = calloc(1, sizeof(struct audio_device));
4139
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004140 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4141
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004142 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4143 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4144 adev->device.common.module = (struct hw_module_t *)module;
4145 adev->device.common.close = adev_close;
4146
4147 adev->device.init_check = adev_init_check;
4148 adev->device.set_voice_volume = adev_set_voice_volume;
4149 adev->device.set_master_volume = adev_set_master_volume;
4150 adev->device.get_master_volume = adev_get_master_volume;
4151 adev->device.set_master_mute = adev_set_master_mute;
4152 adev->device.get_master_mute = adev_get_master_mute;
4153 adev->device.set_mode = adev_set_mode;
4154 adev->device.set_mic_mute = adev_set_mic_mute;
4155 adev->device.get_mic_mute = adev_get_mic_mute;
4156 adev->device.set_parameters = adev_set_parameters;
4157 adev->device.get_parameters = adev_get_parameters;
4158 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4159 adev->device.open_output_stream = adev_open_output_stream;
4160 adev->device.close_output_stream = adev_close_output_stream;
4161 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004162
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004163 adev->device.close_input_stream = adev_close_input_stream;
4164 adev->device.dump = adev_dump;
4165
4166 /* Set the default route before the PCM stream is opened */
4167 pthread_mutex_lock(&adev->lock);
4168 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004169 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004170 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004171 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004172 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004173 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004174 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004175 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004176 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004177 pthread_mutex_unlock(&adev->lock);
4178
4179 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004180 adev->platform = platform_init(adev);
4181 if (!adev->platform) {
4182 free(adev->snd_dev_ref_cnt);
4183 free(adev);
4184 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4185 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004186 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004187 return -EINVAL;
4188 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05004189 adev->extspk = audio_extn_extspk_init(adev);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004190 audio_extn_sound_trigger_init(adev);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004191
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004192 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4193 if (adev->visualizer_lib == NULL) {
4194 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4195 } else {
4196 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4197 adev->visualizer_start_output =
4198 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4199 "visualizer_hal_start_output");
4200 adev->visualizer_stop_output =
4201 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4202 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07004203 }
4204
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004205 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4206 if (adev->offload_effects_lib == NULL) {
4207 ALOGW("%s: DLOPEN failed for %s", __func__,
4208 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4209 } else {
4210 ALOGV("%s: DLOPEN successful for %s", __func__,
4211 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4212 adev->offload_effects_start_output =
4213 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4214 "offload_effects_bundle_hal_start_output");
4215 adev->offload_effects_stop_output =
4216 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4217 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07004218 }
4219
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004220 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4221 if (adev->adm_lib == NULL) {
4222 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4223 } else {
4224 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4225 adev->adm_init = (adm_init_t)
4226 dlsym(adev->adm_lib, "adm_init");
4227 adev->adm_deinit = (adm_deinit_t)
4228 dlsym(adev->adm_lib, "adm_deinit");
4229 adev->adm_register_input_stream = (adm_register_input_stream_t)
4230 dlsym(adev->adm_lib, "adm_register_input_stream");
4231 adev->adm_register_output_stream = (adm_register_output_stream_t)
4232 dlsym(adev->adm_lib, "adm_register_output_stream");
4233 adev->adm_deregister_stream = (adm_deregister_stream_t)
4234 dlsym(adev->adm_lib, "adm_deregister_stream");
4235 adev->adm_request_focus = (adm_request_focus_t)
4236 dlsym(adev->adm_lib, "adm_request_focus");
4237 adev->adm_abandon_focus = (adm_abandon_focus_t)
4238 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08004239 adev->adm_set_config = (adm_set_config_t)
4240 dlsym(adev->adm_lib, "adm_set_config");
4241 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4242 dlsym(adev->adm_lib, "adm_request_focus_v2");
4243 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4244 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4245 adev->adm_on_routing_change = (adm_on_routing_change_t)
4246 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004247 }
4248
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004249 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004250 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004251
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004252 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004253
Andy Hung31aca912014-03-20 17:14:59 -07004254 if (k_enable_extended_precision)
4255 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004256
Glenn Kasten4f993392014-05-14 07:30:48 -07004257 char value[PROPERTY_VALUE_MAX];
4258 int trial;
4259 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4260 trial = atoi(value);
4261 if (period_size_is_plausible_for_low_latency(trial)) {
4262 pcm_config_low_latency.period_size = trial;
4263 pcm_config_low_latency.start_threshold = trial / 4;
4264 pcm_config_low_latency.avail_min = trial / 4;
4265 configured_low_latency_capture_period_size = trial;
4266 }
4267 }
4268 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4269 trial = atoi(value);
4270 if (period_size_is_plausible_for_low_latency(trial)) {
4271 configured_low_latency_capture_period_size = trial;
4272 }
4273 }
4274
Yamit Mehtae3b99562016-09-16 22:44:00 +05304275 audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004276 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004277
4278 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4279 af_period_multiplier = atoi(value);
4280 if (af_period_multiplier < 0) {
4281 af_period_multiplier = 2;
4282 } else if (af_period_multiplier > 4) {
4283 af_period_multiplier = 4;
4284 }
4285 ALOGV("new period_multiplier = %d", af_period_multiplier);
4286 }
4287
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004288 audio_extn_tfa_98xx_init(adev);
4289
vivek mehta1a9b7c02015-06-25 11:49:38 -07004290 pthread_mutex_unlock(&adev_init_lock);
4291
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004292 if (adev->adm_init)
4293 adev->adm_data = adev->adm_init();
4294
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004295 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004296 audio_extn_snd_mon_init();
4297 pthread_mutex_lock(&adev->lock);
4298 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
4299 adev->card_status = CARD_STATUS_ONLINE;
4300 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004301
Eric Laurent2bafff12016-03-17 12:17:23 -07004302 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004303 return 0;
4304}
4305
4306static struct hw_module_methods_t hal_module_methods = {
4307 .open = adev_open,
4308};
4309
4310struct audio_module HAL_MODULE_INFO_SYM = {
4311 .common = {
4312 .tag = HARDWARE_MODULE_TAG,
4313 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4314 .hal_api_version = HARDWARE_HAL_API_VERSION,
4315 .id = AUDIO_HARDWARE_MODULE_ID,
4316 .name = "QCOM Audio HAL",
4317 .author = "Code Aurora Forum",
4318 .methods = &hal_module_methods,
4319 },
4320};