blob: 203992442016f066e8fa58b6b9ba219968e9d95a [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
vivek mehtaa51fd402016-02-04 19:49:33 -08002 * Copyright (C) 2013-2016 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "audio_hw_primary"
Haynes Mathew George03c40102016-01-29 17:57:48 -080018#define ATRACE_TAG ATRACE_TAG_AUDIO
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080019/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070020/*#define VERY_VERY_VERBOSE_LOGGING*/
21#ifdef VERY_VERY_VERBOSE_LOGGING
22#define ALOGVV ALOGV
23#else
24#define ALOGVV(a...) do { } while(0)
25#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080026
27#include <errno.h>
28#include <pthread.h>
29#include <stdint.h>
30#include <sys/time.h>
31#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080032#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070033#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070034#include <sys/resource.h>
35#include <sys/prctl.h>
Kevin Rocardb5c28192017-05-02 15:30:20 -070036#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080037
38#include <cutils/log.h>
Haynes Mathew George03c40102016-01-29 17:57:48 -080039#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040#include <cutils/str_parms.h>
41#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070042#include <cutils/atomic.h>
43#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080044
Eric Laurentb23d5282013-05-14 15:27:20 -070045#include <hardware/audio_effect.h>
Andy Hung31aca912014-03-20 17:14:59 -070046#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070047#include <system/thread_defs.h>
Phil Burkbc991042017-02-24 08:06:44 -080048#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070049#include <audio_effects/effect_aec.h>
50#include <audio_effects/effect_ns.h>
Andy Hungfc044e12017-03-20 09:24:22 -070051#include <audio_utils/clock.h>
52#include <audio_utils/power.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include "audio_hw.h"
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -080054#include "audio_extn.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070055#include "platform_api.h"
56#include <platform.h>
Vineeta Srivastava4b89e372014-06-19 14:21:42 -070057#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080058
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070059#include "sound/compress_params.h"
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -080060#include "audio_extn/tfa_98xx.h"
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070061
Eric Laurent397db572016-05-11 11:31:47 -070062/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
63 * COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
Marco Nelissen32093f52015-04-08 15:14:02 -070064#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070065// 2 buffers causes problems with high bitrate files
66#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070067/* ToDo: Check and update a proper value in msec */
68#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
69#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
70
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070071#define PROXY_OPEN_RETRY_COUNT 100
72#define PROXY_OPEN_WAIT_TIME 20
73
vivek mehtadae44712015-07-27 14:13:18 -070074#define MIN_CHANNEL_COUNT 1
75#define DEFAULT_CHANNEL_COUNT 2
76
Jean-Michel Trivic0750692015-10-12 12:12:32 -070077#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
78#define MAX_CHANNEL_COUNT 1
79#else
vivek mehtadae44712015-07-27 14:13:18 -070080#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
81#define XSTR(x) STR(x)
82#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070083#endif
vivek mehtadae44712015-07-27 14:13:18 -070084
Haynes Mathew George03c40102016-01-29 17:57:48 -080085#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
86
Glenn Kasten4f993392014-05-14 07:30:48 -070087static unsigned int configured_low_latency_capture_period_size =
88 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
89
Eric Laurent0e46adf2016-12-16 12:49:24 -080090
91#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Phil Burkbc991042017-02-24 08:06:44 -080092#define MMAP_PERIOD_COUNT_MIN 32
93#define MMAP_PERIOD_COUNT_MAX 512
94#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
Eric Laurent0e46adf2016-12-16 12:49:24 -080095
96
Andy Hung31aca912014-03-20 17:14:59 -070097/* This constant enables extended precision handling.
98 * TODO The flag is off until more testing is done.
99 */
100static const bool k_enable_extended_precision = false;
101
Eric Laurentb23d5282013-05-14 15:27:20 -0700102struct pcm_config pcm_config_deep_buffer = {
vivek mehtadae44712015-07-27 14:13:18 -0700103 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700104 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
105 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
106 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
107 .format = PCM_FORMAT_S16_LE,
108 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
109 .stop_threshold = INT_MAX,
110 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
111};
112
113struct pcm_config pcm_config_low_latency = {
vivek mehtadae44712015-07-27 14:13:18 -0700114 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700115 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
116 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
117 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
118 .format = PCM_FORMAT_S16_LE,
119 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
120 .stop_threshold = INT_MAX,
121 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
122};
123
Haynes Mathew George03c40102016-01-29 17:57:48 -0800124static int af_period_multiplier = 4;
125struct pcm_config pcm_config_rt = {
126 .channels = DEFAULT_CHANNEL_COUNT,
127 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
128 .period_size = ULL_PERIOD_SIZE, //1 ms
129 .period_count = 512, //=> buffer size is 512ms
130 .format = PCM_FORMAT_S16_LE,
131 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
132 .stop_threshold = INT_MAX,
133 .silence_threshold = 0,
134 .silence_size = 0,
135 .avail_min = ULL_PERIOD_SIZE, //1 ms
136};
137
Eric Laurentb23d5282013-05-14 15:27:20 -0700138struct pcm_config pcm_config_hdmi_multi = {
139 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
140 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
141 .period_size = HDMI_MULTI_PERIOD_SIZE,
142 .period_count = HDMI_MULTI_PERIOD_COUNT,
143 .format = PCM_FORMAT_S16_LE,
144 .start_threshold = 0,
145 .stop_threshold = INT_MAX,
146 .avail_min = 0,
147};
148
Eric Laurent0e46adf2016-12-16 12:49:24 -0800149struct pcm_config pcm_config_mmap_playback = {
150 .channels = DEFAULT_CHANNEL_COUNT,
151 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
152 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800153 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800154 .format = PCM_FORMAT_S16_LE,
155 .start_threshold = MMAP_PERIOD_SIZE*8,
156 .stop_threshold = INT32_MAX,
157 .silence_threshold = 0,
158 .silence_size = 0,
159 .avail_min = MMAP_PERIOD_SIZE, //1 ms
160};
161
Eric Laurentb23d5282013-05-14 15:27:20 -0700162struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700163 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700164 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
165 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700166 .stop_threshold = INT_MAX,
167 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700168};
169
Haynes Mathew George03c40102016-01-29 17:57:48 -0800170struct pcm_config pcm_config_audio_capture_rt = {
171 .channels = DEFAULT_CHANNEL_COUNT,
172 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
173 .period_size = ULL_PERIOD_SIZE,
174 .period_count = 512,
175 .format = PCM_FORMAT_S16_LE,
176 .start_threshold = 0,
177 .stop_threshold = INT_MAX,
178 .silence_threshold = 0,
179 .silence_size = 0,
180 .avail_min = ULL_PERIOD_SIZE, //1 ms
181};
182
Eric Laurent0e46adf2016-12-16 12:49:24 -0800183struct pcm_config pcm_config_mmap_capture = {
184 .channels = DEFAULT_CHANNEL_COUNT,
185 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
186 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800187 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800188 .format = PCM_FORMAT_S16_LE,
189 .start_threshold = 0,
190 .stop_threshold = INT_MAX,
191 .silence_threshold = 0,
192 .silence_size = 0,
193 .avail_min = MMAP_PERIOD_SIZE, //1 ms
194};
195
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700196#define AFE_PROXY_CHANNEL_COUNT 2
197#define AFE_PROXY_SAMPLING_RATE 48000
198
199#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
200#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
201
202struct pcm_config pcm_config_afe_proxy_playback = {
203 .channels = AFE_PROXY_CHANNEL_COUNT,
204 .rate = AFE_PROXY_SAMPLING_RATE,
205 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
206 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
207 .format = PCM_FORMAT_S16_LE,
208 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
209 .stop_threshold = INT_MAX,
210 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
211};
212
213#define AFE_PROXY_RECORD_PERIOD_SIZE 768
214#define AFE_PROXY_RECORD_PERIOD_COUNT 4
215
216struct pcm_config pcm_config_afe_proxy_record = {
217 .channels = AFE_PROXY_CHANNEL_COUNT,
218 .rate = AFE_PROXY_SAMPLING_RATE,
219 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
220 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
221 .format = PCM_FORMAT_S16_LE,
222 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
223 .stop_threshold = INT_MAX,
224 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
225};
226
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700227const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700228 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
229 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
230 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700231 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700232 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700233 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800234 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700235
Eric Laurentb23d5282013-05-14 15:27:20 -0700236 [USECASE_AUDIO_RECORD] = "audio-record",
237 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800238 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700239
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800240 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
241 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700242
Eric Laurentb23d5282013-05-14 15:27:20 -0700243 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700244 [USECASE_VOICE2_CALL] = "voice2-call",
245 [USECASE_VOLTE_CALL] = "volte-call",
246 [USECASE_QCHAT_CALL] = "qchat-call",
247 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800248 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
249 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700250
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700251 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
252 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
253
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700254 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
255 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700256};
257
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800258
259#define STRING_TO_ENUM(string) { #string, string }
260
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800261struct string_to_enum {
262 const char *name;
263 uint32_t value;
264};
265
266static const struct string_to_enum out_channels_name_to_enum_table[] = {
267 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
268 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
269 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
270};
271
Haynes Mathew George5191a852013-09-11 14:19:36 -0700272static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700273static struct audio_device *adev = NULL;
274static pthread_mutex_t adev_init_lock;
275static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700276//cache last MBDRC cal step level
277static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700278
Haynes Mathew George03c40102016-01-29 17:57:48 -0800279static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
280 int flags __unused)
281{
282 int dir = 0;
283 switch (uc_id) {
284 case USECASE_AUDIO_RECORD_LOW_LATENCY:
285 dir = 1;
286 case USECASE_AUDIO_PLAYBACK_ULL:
287 break;
288 default:
289 return false;
290 }
291
292 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
293 PCM_PLAYBACK : PCM_CAPTURE);
294 if (adev->adm_is_noirq_avail)
295 return adev->adm_is_noirq_avail(adev->adm_data,
296 adev->snd_card, dev_id, dir);
297 return false;
298}
299
300static void register_out_stream(struct stream_out *out)
301{
302 struct audio_device *adev = out->dev;
303 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
304 return;
305
306 if (!adev->adm_register_output_stream)
307 return;
308
309 adev->adm_register_output_stream(adev->adm_data,
310 out->handle,
311 out->flags);
312
313 if (!adev->adm_set_config)
314 return;
315
316 if (out->realtime) {
317 adev->adm_set_config(adev->adm_data,
318 out->handle,
319 out->pcm, &out->config);
320 }
321}
322
323static void register_in_stream(struct stream_in *in)
324{
325 struct audio_device *adev = in->dev;
326 if (!adev->adm_register_input_stream)
327 return;
328
329 adev->adm_register_input_stream(adev->adm_data,
330 in->capture_handle,
331 in->flags);
332
333 if (!adev->adm_set_config)
334 return;
335
336 if (in->realtime) {
337 adev->adm_set_config(adev->adm_data,
338 in->capture_handle,
339 in->pcm,
340 &in->config);
341 }
342}
343
344static void request_out_focus(struct stream_out *out, long ns)
345{
346 struct audio_device *adev = out->dev;
347
Haynes Mathew George03c40102016-01-29 17:57:48 -0800348 if (adev->adm_request_focus_v2) {
349 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
350 } else if (adev->adm_request_focus) {
351 adev->adm_request_focus(adev->adm_data, out->handle);
352 }
353}
354
355static void request_in_focus(struct stream_in *in, long ns)
356{
357 struct audio_device *adev = in->dev;
358
Haynes Mathew George03c40102016-01-29 17:57:48 -0800359 if (adev->adm_request_focus_v2) {
360 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
361 } else if (adev->adm_request_focus) {
362 adev->adm_request_focus(adev->adm_data, in->capture_handle);
363 }
364}
365
366static void release_out_focus(struct stream_out *out, long ns __unused)
367{
368 struct audio_device *adev = out->dev;
369
370 if (adev->adm_abandon_focus)
371 adev->adm_abandon_focus(adev->adm_data, out->handle);
372}
373
374static void release_in_focus(struct stream_in *in, long ns __unused)
375{
376 struct audio_device *adev = in->dev;
377 if (adev->adm_abandon_focus)
378 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
379}
380
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700381static int parse_snd_card_status(struct str_parms * parms, int * card,
382 card_status_t * status)
383{
384 char value[32]={0};
385 char state[32]={0};
386
387 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
388
389 if (ret < 0)
390 return -1;
391
392 // sscanf should be okay as value is of max length 32.
393 // same as sizeof state.
394 if (sscanf(value, "%d,%s", card, state) < 2)
395 return -1;
396
397 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
398 CARD_STATUS_OFFLINE;
399 return 0;
400}
401
vivek mehta1a9b7c02015-06-25 11:49:38 -0700402__attribute__ ((visibility ("default")))
403bool audio_hw_send_gain_dep_calibration(int level) {
404 bool ret_val = false;
405 ALOGV("%s: enter ... ", __func__);
406
407 pthread_mutex_lock(&adev_init_lock);
408
409 if (adev != NULL && adev->platform != NULL) {
410 pthread_mutex_lock(&adev->lock);
411 ret_val = platform_send_gain_dep_cal(adev->platform, level);
412 pthread_mutex_unlock(&adev->lock);
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700413
414 // if cal set fails, cache level info
415 // if cal set succeds, reset known last cal set
416 if (!ret_val)
417 last_known_cal_step = level;
418 else if (last_known_cal_step != -1)
419 last_known_cal_step = -1;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700420 } else {
421 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
422 }
423
424 pthread_mutex_unlock(&adev_init_lock);
425
426 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
427 return ret_val;
428}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700429
vivek mehtaa8d7c922016-05-25 14:40:44 -0700430__attribute__ ((visibility ("default")))
431int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
432 int table_size) {
433 int ret_val = 0;
434 ALOGV("%s: enter ... ", __func__);
435
436 pthread_mutex_lock(&adev_init_lock);
437 if (adev == NULL) {
438 ALOGW("%s: adev is NULL .... ", __func__);
439 goto done;
440 }
441
442 pthread_mutex_lock(&adev->lock);
443 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
444 pthread_mutex_unlock(&adev->lock);
445done:
446 pthread_mutex_unlock(&adev_init_lock);
447 ALOGV("%s: exit ... ", __func__);
448 return ret_val;
449}
450
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700451static bool is_supported_format(audio_format_t format)
452{
Eric Laurent8251ac82014-07-23 11:00:25 -0700453 switch (format) {
454 case AUDIO_FORMAT_MP3:
455 case AUDIO_FORMAT_AAC_LC:
456 case AUDIO_FORMAT_AAC_HE_V1:
457 case AUDIO_FORMAT_AAC_HE_V2:
458 return true;
459 default:
460 break;
461 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700462 return false;
463}
464
Haynes Mathew George03c40102016-01-29 17:57:48 -0800465static inline bool is_mmap_usecase(audio_usecase_t uc_id)
466{
467 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
468 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
469}
470
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700471static int get_snd_codec_id(audio_format_t format)
472{
473 int id = 0;
474
Eric Laurent8251ac82014-07-23 11:00:25 -0700475 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700476 case AUDIO_FORMAT_MP3:
477 id = SND_AUDIOCODEC_MP3;
478 break;
479 case AUDIO_FORMAT_AAC:
480 id = SND_AUDIOCODEC_AAC;
481 break;
482 default:
483 ALOGE("%s: Unsupported audio format", __func__);
484 }
485
486 return id;
487}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800488
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800489static int audio_ssr_status(struct audio_device *adev)
490{
491 int ret = 0;
492 struct mixer_ctl *ctl;
493 const char *mixer_ctl_name = "Audio SSR Status";
494
495 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
496 ret = mixer_ctl_get_value(ctl, 0);
497 ALOGD("%s: value: %d", __func__, ret);
498 return ret;
499}
500
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800501int enable_audio_route(struct audio_device *adev,
502 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800503{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700504 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800505 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800506
507 if (usecase == NULL)
508 return -EINVAL;
509
510 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
511
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800512 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700513 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800514 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700515 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800516
Yamit Mehtae3b99562016-09-16 22:44:00 +0530517 audio_extn_utils_send_app_type_cfg(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800518 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500519 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700520 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700521 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800522
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800523 ALOGV("%s: exit", __func__);
524 return 0;
525}
526
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800527int disable_audio_route(struct audio_device *adev,
528 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800529{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700530 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800531 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800532
533 if (usecase == NULL)
534 return -EINVAL;
535
536 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700537 if (usecase->type == PCM_CAPTURE)
538 snd_device = usecase->in_snd_device;
539 else
540 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800541 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500542 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700543 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700544 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800545
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800546 ALOGV("%s: exit", __func__);
547 return 0;
548}
549
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800550int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700551 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800552{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700553 int i, num_devices = 0;
554 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800555 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800556 if (snd_device < SND_DEVICE_MIN ||
557 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800558 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800559 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800560 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700561
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700562 platform_send_audio_calibration(adev->platform, snd_device);
563
vivek mehtade4849c2016-03-03 17:23:38 -0800564 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700565 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700566 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800567 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700568 }
569
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700570 /* due to the possibility of calibration overwrite between listen
571 and audio, notify sound trigger hal before audio calibration is sent */
572 audio_extn_sound_trigger_update_device_status(snd_device,
573 ST_EVENT_SND_DEVICE_BUSY);
574
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700575 if (audio_extn_spkr_prot_is_enabled())
576 audio_extn_spkr_prot_calib_cancel(adev);
577
zhaoyang yin4211fad2015-06-04 21:13:25 +0800578 audio_extn_dsm_feedback_enable(adev, snd_device, true);
579
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700580 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
581 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
582 audio_extn_spkr_prot_is_enabled()) {
583 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800584 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700585 }
586 if (audio_extn_spkr_prot_start_processing(snd_device)) {
587 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800588 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700589 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700590 } else if (platform_can_split_snd_device(snd_device,
591 &num_devices,
592 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700593 for (i = 0; i < num_devices; i++) {
594 enable_snd_device(adev, new_snd_devices[i]);
595 }
vivek mehtab6506412015-08-07 16:55:17 -0700596 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700597 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800598 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
599 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
600 ALOGE(" %s: Invalid sound device returned", __func__);
601 goto on_error;
602 }
Ed Tam70b5c142016-03-21 19:14:29 -0700603
Eric Laurent2e140aa2016-06-30 17:14:46 -0700604 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800605 audio_route_apply_and_update_path(adev->audio_route, device_name);
606 }
607on_success:
608 adev->snd_dev_ref_cnt[snd_device]++;
609 ret_val = 0;
610on_error:
611 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800612}
613
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800614int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700615 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800616{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700617 int i, num_devices = 0;
618 snd_device_t new_snd_devices[2];
619
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800620 if (snd_device < SND_DEVICE_MIN ||
621 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800622 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800623 return -EINVAL;
624 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700625 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
626 ALOGE("%s: device ref cnt is already 0", __func__);
627 return -EINVAL;
628 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800629 audio_extn_tfa_98xx_disable_speaker(snd_device);
630
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700631 adev->snd_dev_ref_cnt[snd_device]--;
632 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800633 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700634 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
635 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
636 audio_extn_spkr_prot_is_enabled()) {
637 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700638 } else if (platform_can_split_snd_device(snd_device,
639 &num_devices,
640 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700641 for (i = 0; i < num_devices; i++) {
642 disable_snd_device(adev, new_snd_devices[i]);
643 }
vivek mehtab6506412015-08-07 16:55:17 -0700644 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700645 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800646 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
647 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
648 ALOGE(" %s: Invalid sound device returned", __func__);
649 return -EINVAL;
650 }
651
Eric Laurent2e140aa2016-06-30 17:14:46 -0700652 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800653 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700654 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700655 audio_extn_sound_trigger_update_device_status(snd_device,
656 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700657 }
vivek mehtab6506412015-08-07 16:55:17 -0700658
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800659 return 0;
660}
661
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700662/*
663 legend:
664 uc - existing usecase
665 new_uc - new usecase
666 d1, d11, d2 - SND_DEVICE enums
667 a1, a2 - corresponding ANDROID device enums
668 B, B1, B2 - backend strings
669
670case 1
671 uc->dev d1 (a1) B1
672 new_uc->dev d1 (a1), d2 (a2) B1, B2
673
674 resolution: disable and enable uc->dev on d1
675
676case 2
677 uc->dev d1 (a1) B1
678 new_uc->dev d11 (a1) B1
679
680 resolution: need to switch uc since d1 and d11 are related
681 (e.g. speaker and voice-speaker)
682 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
683
684case 3
685 uc->dev d1 (a1) B1
686 new_uc->dev d2 (a2) B2
687
688 resolution: no need to switch uc
689
690case 4
691 uc->dev d1 (a1) B
692 new_uc->dev d2 (a2) B
693
694 resolution: disable enable uc-dev on d2 since backends match
695 we cannot enable two streams on two different devices if they
696 share the same backend. e.g. if offload is on speaker device using
697 QUAD_MI2S backend and a low-latency stream is started on voice-handset
698 using the same backend, offload must also be switched to voice-handset.
699
700case 5
701 uc->dev d1 (a1) B
702 new_uc->dev d1 (a1), d2 (a2) B
703
704 resolution: disable enable uc-dev on d2 since backends match
705 we cannot enable two streams on two different devices if they
706 share the same backend.
707
708case 6
709 uc->dev d1 a1 B1
710 new_uc->dev d2 a1 B2
711
712 resolution: no need to switch
713
714case 7
715
716 uc->dev d1 (a1), d2 (a2) B1, B2
717 new_uc->dev d1 B1
718
719 resolution: no need to switch
720
721*/
722static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
723 struct audio_usecase *new_uc,
724 snd_device_t new_snd_device)
725{
726 audio_devices_t a1 = uc->stream.out->devices;
727 audio_devices_t a2 = new_uc->stream.out->devices;
728
729 snd_device_t d1 = uc->out_snd_device;
730 snd_device_t d2 = new_snd_device;
731
732 // Treat as a special case when a1 and a2 are not disjoint
733 if ((a1 != a2) && (a1 & a2)) {
734 snd_device_t d3[2];
735 int num_devices = 0;
736 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
737 &num_devices,
738 d3);
739 if (ret < 0) {
740 if (ret != -ENOSYS) {
741 ALOGW("%s failed to split snd_device %d",
742 __func__,
743 popcount(a1) > 1 ? d1 : d2);
744 }
745 goto end;
746 }
747
748 // NB: case 7 is hypothetical and isn't a practical usecase yet.
749 // But if it does happen, we need to give priority to d2 if
750 // the combo devices active on the existing usecase share a backend.
751 // This is because we cannot have a usecase active on a combo device
752 // and a new usecase requests one device in this combo pair.
753 if (platform_check_backends_match(d3[0], d3[1])) {
754 return d2; // case 5
755 } else {
756 return d1; // case 1
757 }
758 } else {
759 if (platform_check_backends_match(d1, d2)) {
760 return d2; // case 2, 4
761 } else {
762 return d1; // case 6, 3
763 }
764 }
765
766end:
767 return d2; // return whatever was calculated before.
768}
769
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700770static void check_and_route_playback_usecases(struct audio_device *adev,
771 struct audio_usecase *uc_info,
772 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700773{
774 struct listnode *node;
775 struct audio_usecase *usecase;
776 bool switch_device[AUDIO_USECASE_MAX];
777 int i, num_uc_to_switch = 0;
778
David Linee3fe402017-03-13 10:00:42 -0700779 platform_check_and_set_playback_backend_cfg(adev, uc_info, snd_device);
780
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700781 /*
782 * This function is to make sure that all the usecases that are active on
783 * the hardware codec backend are always routed to any one device that is
784 * handled by the hardware codec.
785 * For example, if low-latency and deep-buffer usecases are currently active
786 * on speaker and out_set_parameters(headset) is received on low-latency
787 * output, then we have to make sure deep-buffer is also switched to headset,
788 * because of the limitation that both the devices cannot be enabled
789 * at the same time as they share the same backend.
790 */
791 /* Disable all the usecases on the shared backend other than the
792 specified usecase */
793 for (i = 0; i < AUDIO_USECASE_MAX; i++)
794 switch_device[i] = false;
795
796 list_for_each(node, &adev->usecase_list) {
797 usecase = node_to_item(node, struct audio_usecase, list);
798 if (usecase->type != PCM_CAPTURE &&
799 usecase != uc_info &&
800 usecase->out_snd_device != snd_device &&
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700801 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
802 platform_check_backends_match(snd_device, usecase->out_snd_device)) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700803 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
804 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700805 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700806 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700807 switch_device[usecase->id] = true;
808 num_uc_to_switch++;
809 }
810 }
811
812 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700813 list_for_each(node, &adev->usecase_list) {
814 usecase = node_to_item(node, struct audio_usecase, list);
815 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700816 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900817 }
818 }
819
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700820 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900821 list_for_each(node, &adev->usecase_list) {
822 usecase = node_to_item(node, struct audio_usecase, list);
823 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700824 d_device = derive_playback_snd_device(usecase, uc_info,
825 snd_device);
826 enable_snd_device(adev, d_device);
827 /* Update the out_snd_device before enabling the audio route */
828 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700829 }
830 }
831
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700832 /* Re-route all the usecases on the shared backend other than the
833 specified usecase to new snd devices */
834 list_for_each(node, &adev->usecase_list) {
835 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700836 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700837 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700838 }
839 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700840 }
841}
842
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700843static void check_and_route_capture_usecases(struct audio_device *adev,
844 struct audio_usecase *uc_info,
845 snd_device_t snd_device)
846{
847 struct listnode *node;
848 struct audio_usecase *usecase;
849 bool switch_device[AUDIO_USECASE_MAX];
850 int i, num_uc_to_switch = 0;
851
vivek mehta4ed66e62016-04-15 23:33:34 -0700852 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
853
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700854 /*
855 * This function is to make sure that all the active capture usecases
856 * are always routed to the same input sound device.
857 * For example, if audio-record and voice-call usecases are currently
858 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
859 * is received for voice call then we have to make sure that audio-record
860 * usecase is also switched to earpiece i.e. voice-dmic-ef,
861 * because of the limitation that two devices cannot be enabled
862 * at the same time if they share the same backend.
863 */
864 for (i = 0; i < AUDIO_USECASE_MAX; i++)
865 switch_device[i] = false;
866
867 list_for_each(node, &adev->usecase_list) {
868 usecase = node_to_item(node, struct audio_usecase, list);
869 if (usecase->type != PCM_PLAYBACK &&
870 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700871 usecase->in_snd_device != snd_device &&
872 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700873 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
874 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700875 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700876 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700877 switch_device[usecase->id] = true;
878 num_uc_to_switch++;
879 }
880 }
881
882 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700883 list_for_each(node, &adev->usecase_list) {
884 usecase = node_to_item(node, struct audio_usecase, list);
885 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700886 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700887 }
888 }
889
890 list_for_each(node, &adev->usecase_list) {
891 usecase = node_to_item(node, struct audio_usecase, list);
892 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700893 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700894 }
895 }
896
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700897 /* Re-route all the usecases on the shared backend other than the
898 specified usecase to new snd devices */
899 list_for_each(node, &adev->usecase_list) {
900 usecase = node_to_item(node, struct audio_usecase, list);
901 /* Update the in_snd_device only before enabling the audio route */
902 if (switch_device[usecase->id] ) {
903 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700904 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700905 }
906 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700907 }
908}
909
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800910/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700911static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800912{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700913 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700914 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800915
916 switch (channels) {
917 /*
918 * Do not handle stereo output in Multi-channel cases
919 * Stereo case is handled in normal playback path
920 */
921 case 6:
922 ALOGV("%s: HDMI supports 5.1", __func__);
923 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
924 break;
925 case 8:
926 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
927 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
928 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
929 break;
930 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700931 ALOGE("HDMI does not support multi channel playback");
932 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800933 break;
934 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700935 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800936}
937
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -0700938static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
939{
940 struct audio_usecase *usecase;
941 struct listnode *node;
942
943 list_for_each(node, &adev->usecase_list) {
944 usecase = node_to_item(node, struct audio_usecase, list);
945 if (usecase->type == VOICE_CALL) {
946 ALOGV("%s: usecase id %d", __func__, usecase->id);
947 return usecase->id;
948 }
949 }
950 return USECASE_INVALID;
951}
952
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800953struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
954 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700955{
956 struct audio_usecase *usecase;
957 struct listnode *node;
958
959 list_for_each(node, &adev->usecase_list) {
960 usecase = node_to_item(node, struct audio_usecase, list);
961 if (usecase->id == uc_id)
962 return usecase;
963 }
964 return NULL;
965}
966
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800967int select_devices(struct audio_device *adev,
968 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800969{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800970 snd_device_t out_snd_device = SND_DEVICE_NONE;
971 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700972 struct audio_usecase *usecase = NULL;
973 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800974 struct audio_usecase *hfp_usecase = NULL;
975 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800976 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700977 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800978
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700979 usecase = get_usecase_from_list(adev, uc_id);
980 if (usecase == NULL) {
981 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
982 return -EINVAL;
983 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800984
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800985 if ((usecase->type == VOICE_CALL) ||
986 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700987 out_snd_device = platform_get_output_snd_device(adev->platform,
988 usecase->stream.out->devices);
989 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700990 usecase->devices = usecase->stream.out->devices;
991 } else {
992 /*
993 * If the voice call is active, use the sound devices of voice call usecase
994 * so that it would not result any device switch. All the usecases will
995 * be switched to new device when select_devices() is called for voice call
996 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700997 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700998 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700999 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001000 vc_usecase = get_usecase_from_list(adev,
1001 get_voice_usecase_id_from_list(adev));
1002 if ((vc_usecase != NULL) &&
1003 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1004 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001005 in_snd_device = vc_usecase->in_snd_device;
1006 out_snd_device = vc_usecase->out_snd_device;
1007 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001008 } else if (audio_extn_hfp_is_active(adev)) {
1009 hfp_ucid = audio_extn_hfp_get_usecase();
1010 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1011 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1012 in_snd_device = hfp_usecase->in_snd_device;
1013 out_snd_device = hfp_usecase->out_snd_device;
1014 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001015 }
1016 if (usecase->type == PCM_PLAYBACK) {
1017 usecase->devices = usecase->stream.out->devices;
1018 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001019 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001020 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001021 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001022 if (usecase->stream.out == adev->primary_output &&
1023 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001024 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1025 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001026 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001027 select_devices(adev, adev->active_input->usecase);
1028 }
1029 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001030 } else if (usecase->type == PCM_CAPTURE) {
1031 usecase->devices = usecase->stream.in->device;
1032 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001033 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001034 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001035 if (adev->active_input &&
1036 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1037 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001038 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001039 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1040 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
1041 } else if (adev->primary_output) {
1042 out_device = adev->primary_output->devices;
1043 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001044 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001045 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001046 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001047 }
1048 }
1049
1050 if (out_snd_device == usecase->out_snd_device &&
1051 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001052 return 0;
1053 }
1054
Eric Laurent2bafff12016-03-17 12:17:23 -07001055 if (out_snd_device != SND_DEVICE_NONE &&
1056 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1057 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1058 __func__,
1059 use_case_table[uc_id],
1060 adev->last_logged_snd_device[uc_id][0],
1061 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1062 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1063 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1064 -1,
1065 out_snd_device,
1066 platform_get_snd_device_name(out_snd_device),
1067 platform_get_snd_device_acdb_id(out_snd_device));
1068 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1069 }
1070 if (in_snd_device != SND_DEVICE_NONE &&
1071 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1072 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1073 __func__,
1074 use_case_table[uc_id],
1075 adev->last_logged_snd_device[uc_id][1],
1076 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1077 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1078 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1079 -1,
1080 in_snd_device,
1081 platform_get_snd_device_name(in_snd_device),
1082 platform_get_snd_device_acdb_id(in_snd_device));
1083 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1084 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001085
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001086 /*
1087 * Limitation: While in call, to do a device switch we need to disable
1088 * and enable both RX and TX devices though one of them is same as current
1089 * device.
1090 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001091 if ((usecase->type == VOICE_CALL) &&
1092 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1093 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001094 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001095 /* Disable sidetone only if voice call already exists */
1096 if (voice_is_call_state_active(adev))
1097 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001098 }
1099
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001100 /* Disable current sound devices */
1101 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001102 disable_audio_route(adev, usecase);
1103 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001104 }
1105
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001106 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001107 disable_audio_route(adev, usecase);
1108 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001109 }
1110
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001111 /* Applicable only on the targets that has external modem.
1112 * New device information should be sent to modem before enabling
1113 * the devices to reduce in-call device switch time.
1114 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001115 if ((usecase->type == VOICE_CALL) &&
1116 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1117 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001118 status = platform_switch_voice_call_enable_device_config(adev->platform,
1119 out_snd_device,
1120 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001121 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001122
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001123 /* Enable new sound devices */
1124 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001125 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1126 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001127 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001128 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001129 }
1130
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001131 if (in_snd_device != SND_DEVICE_NONE) {
1132 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001133 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001134 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001135
Eric Laurentb23d5282013-05-14 15:27:20 -07001136 if (usecase->type == VOICE_CALL)
1137 status = platform_switch_voice_call_device_post(adev->platform,
1138 out_snd_device,
1139 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001140
sangwoo170731f2013-06-08 15:36:36 +09001141 usecase->in_snd_device = in_snd_device;
1142 usecase->out_snd_device = out_snd_device;
1143
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001144 audio_extn_tfa_98xx_set_mode();
1145
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001146 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001147
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001148 /* Applicable only on the targets that has external modem.
1149 * Enable device command should be sent to modem only after
1150 * enabling voice call mixer controls
1151 */
vivek mehta765eb642015-08-07 19:46:06 -07001152 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001153 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1154 out_snd_device,
1155 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001156 /* Enable sidetone only if voice call already exists */
1157 if (voice_is_call_state_active(adev))
1158 voice_set_sidetone(adev, out_snd_device, true);
1159 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001160
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001161 return status;
1162}
1163
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001164static int stop_input_stream(struct stream_in *in)
1165{
1166 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001167 struct audio_usecase *uc_info;
1168 struct audio_device *adev = in->dev;
1169
Eric Laurentc8400632013-02-14 19:04:54 -08001170 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001171
Eric Laurent994a6932013-07-17 11:51:42 -07001172 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001173 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001174 uc_info = get_usecase_from_list(adev, in->usecase);
1175 if (uc_info == NULL) {
1176 ALOGE("%s: Could not find the usecase (%d) in the list",
1177 __func__, in->usecase);
1178 return -EINVAL;
1179 }
1180
Eric Laurent150dbfe2013-02-27 14:31:02 -08001181 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001182 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001183
1184 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001185 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001186
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001187 list_remove(&uc_info->list);
1188 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001189
Eric Laurent994a6932013-07-17 11:51:42 -07001190 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001191 return ret;
1192}
1193
1194int start_input_stream(struct stream_in *in)
1195{
1196 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001197 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001198 struct audio_usecase *uc_info;
1199 struct audio_device *adev = in->dev;
1200
Eric Laurent994a6932013-07-17 11:51:42 -07001201 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001202
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001203 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1204 return -EIO;
1205
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001206 if (in->card_status == CARD_STATUS_OFFLINE ||
1207 adev->card_status == CARD_STATUS_OFFLINE) {
1208 ALOGW("in->card_status or adev->card_status offline, try again");
1209 ret = -EAGAIN;
1210 goto error_config;
1211 }
1212
Eric Laurentb23d5282013-05-14 15:27:20 -07001213 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001214 if (in->pcm_device_id < 0) {
1215 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1216 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001217 ret = -EINVAL;
1218 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001219 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001220
1221 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001222 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1223 uc_info->id = in->usecase;
1224 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001225 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001226 uc_info->devices = in->device;
1227 uc_info->in_snd_device = SND_DEVICE_NONE;
1228 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001229
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001230 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001231
1232 audio_extn_perf_lock_acquire();
1233
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001234 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001235
Eric Laurent0e46adf2016-12-16 12:49:24 -08001236 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001237 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001238 ALOGE("%s: pcm stream not ready", __func__);
1239 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001240 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001241 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001242 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001243 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1244 goto error_open;
1245 }
1246 } else {
1247 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1248 unsigned int pcm_open_retry_count = 0;
1249
1250 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1251 flags |= PCM_MMAP | PCM_NOIRQ;
1252 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1253 } else if (in->realtime) {
1254 flags |= PCM_MMAP | PCM_NOIRQ;
1255 }
1256
1257 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1258 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1259
1260 while (1) {
1261 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1262 flags, &in->config);
1263 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1264 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1265 if (in->pcm != NULL) {
1266 pcm_close(in->pcm);
1267 in->pcm = NULL;
1268 }
1269 if (pcm_open_retry_count-- == 0) {
1270 ret = -EIO;
1271 goto error_open;
1272 }
1273 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1274 continue;
1275 }
1276 break;
1277 }
1278
1279 ALOGV("%s: pcm_prepare", __func__);
1280 ret = pcm_prepare(in->pcm);
1281 if (ret < 0) {
1282 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001283 pcm_close(in->pcm);
1284 in->pcm = NULL;
1285 goto error_open;
1286 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001287 if (in->realtime) {
1288 ret = pcm_start(in->pcm);
1289 if (ret < 0) {
1290 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1291 pcm_close(in->pcm);
1292 in->pcm = NULL;
1293 goto error_open;
1294 }
1295 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001296 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001297 register_in_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001298 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001299 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001300
Eric Laurent0e46adf2016-12-16 12:49:24 -08001301 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001302
1303error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001304 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001305 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001306
1307error_config:
1308 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001309 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001310
1311 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001312}
1313
Eric Laurenta1478072015-09-21 17:21:52 -07001314void lock_input_stream(struct stream_in *in)
1315{
1316 pthread_mutex_lock(&in->pre_lock);
1317 pthread_mutex_lock(&in->lock);
1318 pthread_mutex_unlock(&in->pre_lock);
1319}
1320
1321void lock_output_stream(struct stream_out *out)
1322{
1323 pthread_mutex_lock(&out->pre_lock);
1324 pthread_mutex_lock(&out->lock);
1325 pthread_mutex_unlock(&out->pre_lock);
1326}
1327
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001328/* must be called with out->lock locked */
1329static int send_offload_cmd_l(struct stream_out* out, int command)
1330{
1331 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1332
1333 ALOGVV("%s %d", __func__, command);
1334
1335 cmd->cmd = command;
1336 list_add_tail(&out->offload_cmd_list, &cmd->node);
1337 pthread_cond_signal(&out->offload_cond);
1338 return 0;
1339}
1340
1341/* must be called iwth out->lock locked */
1342static void stop_compressed_output_l(struct stream_out *out)
1343{
1344 out->offload_state = OFFLOAD_STATE_IDLE;
1345 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001346 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001347 if (out->compr != NULL) {
1348 compress_stop(out->compr);
1349 while (out->offload_thread_blocked) {
1350 pthread_cond_wait(&out->cond, &out->lock);
1351 }
1352 }
1353}
1354
1355static void *offload_thread_loop(void *context)
1356{
1357 struct stream_out *out = (struct stream_out *) context;
1358 struct listnode *item;
1359
1360 out->offload_state = OFFLOAD_STATE_IDLE;
1361 out->playback_started = 0;
1362
1363 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1364 set_sched_policy(0, SP_FOREGROUND);
1365 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1366
1367 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001368 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001369 for (;;) {
1370 struct offload_cmd *cmd = NULL;
1371 stream_callback_event_t event;
1372 bool send_callback = false;
1373
1374 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1375 __func__, list_empty(&out->offload_cmd_list),
1376 out->offload_state);
1377 if (list_empty(&out->offload_cmd_list)) {
1378 ALOGV("%s SLEEPING", __func__);
1379 pthread_cond_wait(&out->offload_cond, &out->lock);
1380 ALOGV("%s RUNNING", __func__);
1381 continue;
1382 }
1383
1384 item = list_head(&out->offload_cmd_list);
1385 cmd = node_to_item(item, struct offload_cmd, node);
1386 list_remove(item);
1387
1388 ALOGVV("%s STATE %d CMD %d out->compr %p",
1389 __func__, out->offload_state, cmd->cmd, out->compr);
1390
1391 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1392 free(cmd);
1393 break;
1394 }
1395
1396 if (out->compr == NULL) {
1397 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001398 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001399 pthread_cond_signal(&out->cond);
1400 continue;
1401 }
1402 out->offload_thread_blocked = true;
1403 pthread_mutex_unlock(&out->lock);
1404 send_callback = false;
1405 switch(cmd->cmd) {
1406 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1407 compress_wait(out->compr, -1);
1408 send_callback = true;
1409 event = STREAM_CBK_EVENT_WRITE_READY;
1410 break;
1411 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001412 compress_next_track(out->compr);
1413 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001414 send_callback = true;
1415 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001416 /* Resend the metadata for next iteration */
1417 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001418 break;
1419 case OFFLOAD_CMD_DRAIN:
1420 compress_drain(out->compr);
1421 send_callback = true;
1422 event = STREAM_CBK_EVENT_DRAIN_READY;
1423 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001424 case OFFLOAD_CMD_ERROR:
1425 send_callback = true;
1426 event = STREAM_CBK_EVENT_ERROR;
1427 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001428 default:
1429 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1430 break;
1431 }
Eric Laurenta1478072015-09-21 17:21:52 -07001432 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001433 out->offload_thread_blocked = false;
1434 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001435 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001436 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001437 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001438 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001439 free(cmd);
1440 }
1441
1442 pthread_cond_signal(&out->cond);
1443 while (!list_empty(&out->offload_cmd_list)) {
1444 item = list_head(&out->offload_cmd_list);
1445 list_remove(item);
1446 free(node_to_item(item, struct offload_cmd, node));
1447 }
1448 pthread_mutex_unlock(&out->lock);
1449
1450 return NULL;
1451}
1452
1453static int create_offload_callback_thread(struct stream_out *out)
1454{
1455 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1456 list_init(&out->offload_cmd_list);
1457 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1458 offload_thread_loop, out);
1459 return 0;
1460}
1461
1462static int destroy_offload_callback_thread(struct stream_out *out)
1463{
Eric Laurenta1478072015-09-21 17:21:52 -07001464 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001465 stop_compressed_output_l(out);
1466 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1467
1468 pthread_mutex_unlock(&out->lock);
1469 pthread_join(out->offload_thread, (void **) NULL);
1470 pthread_cond_destroy(&out->offload_cond);
1471
1472 return 0;
1473}
1474
Eric Laurent07eeafd2013-10-06 12:52:49 -07001475static bool allow_hdmi_channel_config(struct audio_device *adev)
1476{
1477 struct listnode *node;
1478 struct audio_usecase *usecase;
1479 bool ret = true;
1480
1481 list_for_each(node, &adev->usecase_list) {
1482 usecase = node_to_item(node, struct audio_usecase, list);
1483 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1484 /*
1485 * If voice call is already existing, do not proceed further to avoid
1486 * disabling/enabling both RX and TX devices, CSD calls, etc.
1487 * Once the voice call done, the HDMI channels can be configured to
1488 * max channels of remaining use cases.
1489 */
1490 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001491 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001492 __func__);
1493 ret = false;
1494 break;
1495 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
Joe Onorato188b6222016-03-01 11:02:27 -08001496 ALOGV("%s: multi channel playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001497 "no change in HDMI channels", __func__);
1498 ret = false;
1499 break;
1500 }
1501 }
1502 }
1503 return ret;
1504}
1505
1506static int check_and_set_hdmi_channels(struct audio_device *adev,
1507 unsigned int channels)
1508{
1509 struct listnode *node;
1510 struct audio_usecase *usecase;
1511
1512 /* Check if change in HDMI channel config is allowed */
1513 if (!allow_hdmi_channel_config(adev))
1514 return 0;
1515
1516 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001517 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001518 return 0;
1519 }
1520
1521 platform_set_hdmi_channels(adev->platform, channels);
1522 adev->cur_hdmi_channels = channels;
1523
1524 /*
1525 * Deroute all the playback streams routed to HDMI so that
1526 * the back end is deactivated. Note that backend will not
1527 * be deactivated if any one stream is connected to it.
1528 */
1529 list_for_each(node, &adev->usecase_list) {
1530 usecase = node_to_item(node, struct audio_usecase, list);
1531 if (usecase->type == PCM_PLAYBACK &&
1532 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001533 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001534 }
1535 }
1536
1537 /*
1538 * Enable all the streams disabled above. Now the HDMI backend
1539 * will be activated with new channel configuration
1540 */
1541 list_for_each(node, &adev->usecase_list) {
1542 usecase = node_to_item(node, struct audio_usecase, list);
1543 if (usecase->type == PCM_PLAYBACK &&
1544 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001545 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001546 }
1547 }
1548
1549 return 0;
1550}
1551
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001552static int stop_output_stream(struct stream_out *out)
1553{
1554 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001555 struct audio_usecase *uc_info;
1556 struct audio_device *adev = out->dev;
1557
Eric Laurent994a6932013-07-17 11:51:42 -07001558 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001559 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001560 uc_info = get_usecase_from_list(adev, out->usecase);
1561 if (uc_info == NULL) {
1562 ALOGE("%s: Could not find the usecase (%d) in the list",
1563 __func__, out->usecase);
1564 return -EINVAL;
1565 }
1566
Haynes Mathew George41f86652014-06-17 14:22:15 -07001567 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1568 if (adev->visualizer_stop_output != NULL)
1569 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1570 if (adev->offload_effects_stop_output != NULL)
1571 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1572 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001573
Eric Laurent150dbfe2013-02-27 14:31:02 -08001574 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001575 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001576
1577 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001578 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001579
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001580 list_remove(&uc_info->list);
1581 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001582
Eric Laurent0499d4f2014-08-25 22:39:29 -05001583 audio_extn_extspk_update(adev->extspk);
1584
Eric Laurent07eeafd2013-10-06 12:52:49 -07001585 /* Must be called after removing the usecase from list */
1586 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1587 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1588
Eric Laurent994a6932013-07-17 11:51:42 -07001589 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001590 return ret;
1591}
1592
1593int start_output_stream(struct stream_out *out)
1594{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001595 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001596 struct audio_usecase *uc_info;
1597 struct audio_device *adev = out->dev;
1598
Eric Laurent994a6932013-07-17 11:51:42 -07001599 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001600 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001601
1602 if (out->card_status == CARD_STATUS_OFFLINE ||
1603 adev->card_status == CARD_STATUS_OFFLINE) {
1604 ALOGW("out->card_status or adev->card_status offline, try again");
1605 ret = -EAGAIN;
1606 goto error_config;
1607 }
1608
Eric Laurentb23d5282013-05-14 15:27:20 -07001609 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001610 if (out->pcm_device_id < 0) {
1611 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1612 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001613 ret = -EINVAL;
1614 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001615 }
1616
1617 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1618 uc_info->id = out->usecase;
1619 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001620 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001621 uc_info->devices = out->devices;
1622 uc_info->in_snd_device = SND_DEVICE_NONE;
1623 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001624
Eric Laurent07eeafd2013-10-06 12:52:49 -07001625 /* This must be called before adding this usecase to the list */
1626 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1627 check_and_set_hdmi_channels(adev, out->config.channels);
1628
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001629 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001630
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001631 audio_extn_perf_lock_acquire();
1632
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001633 select_devices(adev, out->usecase);
1634
Eric Laurent0499d4f2014-08-25 22:39:29 -05001635 audio_extn_extspk_update(adev->extspk);
1636
Andy Hung31aca912014-03-20 17:14:59 -07001637 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001638 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001639 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1640 out->pcm = NULL;
1641 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1642 COMPRESS_IN, &out->compr_config);
1643 if (out->compr && !is_compress_ready(out->compr)) {
1644 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1645 compress_close(out->compr);
1646 out->compr = NULL;
1647 ret = -EIO;
1648 goto error_open;
1649 }
1650 if (out->offload_callback)
1651 compress_nonblock(out->compr, out->non_blocking);
1652
1653 if (adev->visualizer_start_output != NULL)
1654 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1655 if (adev->offload_effects_start_output != NULL)
1656 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
1657 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001658 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001659 ALOGE("%s: pcm stream not ready", __func__);
1660 goto error_open;
1661 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001662 ret = pcm_start(out->pcm);
1663 if (ret < 0) {
1664 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1665 goto error_open;
1666 }
1667 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001668 unsigned int flags = PCM_OUT;
1669 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001670
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001671 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1672 flags |= PCM_MMAP | PCM_NOIRQ;
1673 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001674 } else if (out->realtime) {
1675 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001676 } else
1677 flags |= PCM_MONOTONIC;
1678
1679 while (1) {
1680 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1681 flags, &out->config);
1682 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1683 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1684 if (out->pcm != NULL) {
1685 pcm_close(out->pcm);
1686 out->pcm = NULL;
1687 }
1688 if (pcm_open_retry_count-- == 0) {
1689 ret = -EIO;
1690 goto error_open;
1691 }
1692 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1693 continue;
1694 }
1695 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001696 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001697 ALOGV("%s: pcm_prepare", __func__);
1698 if (pcm_is_ready(out->pcm)) {
1699 ret = pcm_prepare(out->pcm);
1700 if (ret < 0) {
1701 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1702 pcm_close(out->pcm);
1703 out->pcm = NULL;
1704 goto error_open;
1705 }
1706 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001707 if (out->realtime) {
1708 ret = pcm_start(out->pcm);
1709 if (ret < 0) {
1710 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1711 pcm_close(out->pcm);
1712 out->pcm = NULL;
1713 goto error_open;
1714 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001715 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001716 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001717 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001718 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001719 audio_extn_tfa_98xx_enable_speaker();
1720
Eric Laurent994a6932013-07-17 11:51:42 -07001721 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001722 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001723error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001724 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001725 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001726error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001727 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001728}
1729
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001730static int check_input_parameters(uint32_t sample_rate,
1731 audio_format_t format,
1732 int channel_count)
1733{
vivek mehta4ed66e62016-04-15 23:33:34 -07001734 if ((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT)) {
vivek mehtadae44712015-07-27 14:13:18 -07001735 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1736 return -EINVAL;
1737 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001738
vivek mehtadae44712015-07-27 14:13:18 -07001739 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > MAX_CHANNEL_COUNT)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001740 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
vivek mehtadae44712015-07-27 14:13:18 -07001741 channel_count, MIN_CHANNEL_COUNT, MAX_CHANNEL_COUNT);
1742 return -EINVAL;
1743 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001744
1745 switch (sample_rate) {
1746 case 8000:
1747 case 11025:
1748 case 12000:
1749 case 16000:
1750 case 22050:
1751 case 24000:
1752 case 32000:
1753 case 44100:
1754 case 48000:
1755 break;
1756 default:
vivek mehtadae44712015-07-27 14:13:18 -07001757 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001758 return -EINVAL;
1759 }
1760
1761 return 0;
1762}
1763
1764static size_t get_input_buffer_size(uint32_t sample_rate,
1765 audio_format_t format,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001766 int channel_count,
1767 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001768{
1769 size_t size = 0;
1770
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001771 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1772 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001773
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001774 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001775 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001776 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07001777
1778 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001779
Glenn Kasten4f993392014-05-14 07:30:48 -07001780 /* make sure the size is multiple of 32 bytes
1781 * At 48 kHz mono 16-bit PCM:
1782 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1783 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1784 */
1785 size += 0x1f;
1786 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001787
1788 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001789}
1790
1791static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1792{
1793 struct stream_out *out = (struct stream_out *)stream;
1794
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001795 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001796}
1797
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001798static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001799{
1800 return -ENOSYS;
1801}
1802
1803static size_t out_get_buffer_size(const struct audio_stream *stream)
1804{
1805 struct stream_out *out = (struct stream_out *)stream;
1806
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001807 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1808 return out->compr_config.fragment_size;
1809 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001810 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07001811 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001812}
1813
1814static uint32_t out_get_channels(const struct audio_stream *stream)
1815{
1816 struct stream_out *out = (struct stream_out *)stream;
1817
1818 return out->channel_mask;
1819}
1820
1821static audio_format_t out_get_format(const struct audio_stream *stream)
1822{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001823 struct stream_out *out = (struct stream_out *)stream;
1824
1825 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001826}
1827
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001828static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001829{
1830 return -ENOSYS;
1831}
1832
1833static int out_standby(struct audio_stream *stream)
1834{
1835 struct stream_out *out = (struct stream_out *)stream;
1836 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08001837 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001838
Eric Laurent994a6932013-07-17 11:51:42 -07001839 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001840 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001841
Eric Laurenta1478072015-09-21 17:21:52 -07001842 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001843 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001844 if (adev->adm_deregister_stream)
1845 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001846 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001847 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001848 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1849 if (out->pcm) {
1850 pcm_close(out->pcm);
1851 out->pcm = NULL;
1852 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001853 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001854 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08001855 out->playback_started = false;
1856 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001857 } else {
1858 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001859 out->gapless_mdata.encoder_delay = 0;
1860 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001861 if (out->compr != NULL) {
1862 compress_close(out->compr);
1863 out->compr = NULL;
1864 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001865 }
Phil Burkbc991042017-02-24 08:06:44 -08001866 if (do_stop) {
1867 stop_output_stream(out);
1868 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001869 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001870 }
1871 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001872 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001873 return 0;
1874}
1875
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001876static int out_on_error(struct audio_stream *stream)
1877{
1878 struct stream_out *out = (struct stream_out *)stream;
1879 struct audio_device *adev = out->dev;
1880 bool do_standby = false;
1881
1882 lock_output_stream(out);
1883 if (!out->standby) {
1884 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1885 stop_compressed_output_l(out);
1886 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
1887 } else
1888 do_standby = true;
1889 }
1890 pthread_mutex_unlock(&out->lock);
1891
1892 if (do_standby)
1893 return out_standby(&out->stream.common);
1894
1895 return 0;
1896}
1897
Andy Hung7401c7c2016-09-21 12:41:21 -07001898static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001899{
Andy Hung7401c7c2016-09-21 12:41:21 -07001900 struct stream_out *out = (struct stream_out *)stream;
1901
1902 // We try to get the lock for consistency,
1903 // but it isn't necessary for these variables.
1904 // If we're not in standby, we may be blocked on a write.
1905 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
1906 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
1907 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
1908
1909 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07001910 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07001911 }
Andy Hunga452b0a2017-03-15 14:51:15 -07001912
1913 // dump error info
1914 (void)error_log_dump(
1915 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hungfc044e12017-03-20 09:24:22 -07001916 // dump power info (out->power_log may be null)
Andy Hung62c9b882017-03-22 16:43:42 -07001917 (void)power_log_dump(
1918 out->power_log, fd, " " /* prefix */, POWER_LOG_LINES, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001919 return 0;
1920}
1921
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001922static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1923{
1924 int ret = 0;
1925 char value[32];
1926 struct compr_gapless_mdata tmp_mdata;
1927
1928 if (!out || !parms) {
1929 return -EINVAL;
1930 }
1931
1932 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1933 if (ret >= 0) {
1934 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
1935 } else {
1936 return -EINVAL;
1937 }
1938
1939 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1940 if (ret >= 0) {
1941 tmp_mdata.encoder_padding = atoi(value);
1942 } else {
1943 return -EINVAL;
1944 }
1945
1946 out->gapless_mdata = tmp_mdata;
1947 out->send_new_metadata = 1;
1948 ALOGV("%s new encoder delay %u and padding %u", __func__,
1949 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1950
1951 return 0;
1952}
1953
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001954static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1955{
1956 return out == adev->primary_output || out == adev->voice_tx_output;
1957}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001958
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001959static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1960{
1961 struct stream_out *out = (struct stream_out *)stream;
1962 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001963 struct audio_usecase *usecase;
1964 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001965 struct str_parms *parms;
1966 char value[32];
1967 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001968 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07001969 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001970
Eric Laurent2e140aa2016-06-30 17:14:46 -07001971 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001972 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001973 parms = str_parms_create_str(kvpairs);
1974 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1975 if (ret >= 0) {
1976 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07001977 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001978 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001979
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001980 /*
1981 * When HDMI cable is unplugged the music playback is paused and
1982 * the policy manager sends routing=0. But the audioflinger
1983 * continues to write data until standby time (3sec).
1984 * As the HDMI core is turned off, the write gets blocked.
1985 * Avoid this by routing audio to speaker until standby.
1986 */
1987 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
1988 val == AUDIO_DEVICE_NONE) {
1989 val = AUDIO_DEVICE_OUT_SPEAKER;
1990 }
1991
1992 /*
1993 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001994 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001995 * the select_devices(). But how do we undo this?
1996 *
1997 * For example, music playback is active on headset (deep-buffer usecase)
1998 * and if we go to ringtones and select a ringtone, low-latency usecase
1999 * will be started on headset+speaker. As we can't enable headset+speaker
2000 * and headset devices at the same time, select_devices() switches the music
2001 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2002 * So when the ringtone playback is completed, how do we undo the same?
2003 *
2004 * We are relying on the out_set_parameters() call on deep-buffer output,
2005 * once the ringtone playback is ended.
2006 * NOTE: We should not check if the current devices are same as new devices.
2007 * Because select_devices() must be called to switch back the music
2008 * playback to headset.
2009 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002010 audio_devices_t new_dev = val;
2011 if (new_dev != AUDIO_DEVICE_NONE) {
2012 bool same_dev = out->devices == new_dev;
2013 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002014
Eric Laurenta7657192014-10-09 21:09:33 -07002015 if (output_drives_call(adev, out)) {
2016 if (!voice_is_in_call(adev)) {
2017 if (adev->mode == AUDIO_MODE_IN_CALL) {
2018 adev->current_call_output = out;
2019 ret = voice_start_call(adev);
2020 }
2021 } else {
2022 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002023 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002024 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002025 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002026
2027 if (!out->standby) {
2028 if (!same_dev) {
2029 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002030 // inform adm before actual routing to prevent glitches.
2031 if (adev->adm_on_routing_change) {
2032 adev->adm_on_routing_change(adev->adm_data,
2033 out->handle);
2034 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002035 }
2036 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002037 audio_extn_tfa_98xx_update();
vivek mehta0d3637a2016-07-24 09:32:02 -07002038 }
2039
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002040 }
2041
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002042 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002043 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002044
2045 /*handles device and call state changes*/
2046 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002047 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002048
2049 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2050 parse_compress_metadata(out, parms);
2051 }
2052
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002053 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002054 ALOGV("%s: exit: code(%d)", __func__, status);
2055 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002056}
2057
2058static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2059{
2060 struct stream_out *out = (struct stream_out *)stream;
2061 struct str_parms *query = str_parms_create_str(keys);
2062 char *str;
2063 char value[256];
2064 struct str_parms *reply = str_parms_create();
2065 size_t i, j;
2066 int ret;
2067 bool first = true;
Eric Laurent994a6932013-07-17 11:51:42 -07002068 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002069 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2070 if (ret >= 0) {
2071 value[0] = '\0';
2072 i = 0;
2073 while (out->supported_channel_masks[i] != 0) {
2074 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2075 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2076 if (!first) {
2077 strcat(value, "|");
2078 }
2079 strcat(value, out_channels_name_to_enum_table[j].name);
2080 first = false;
2081 break;
2082 }
2083 }
2084 i++;
2085 }
2086 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2087 str = str_parms_to_str(reply);
2088 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002089 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002090 }
2091 str_parms_destroy(query);
2092 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002093 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002094 return str;
2095}
2096
2097static uint32_t out_get_latency(const struct audio_stream_out *stream)
2098{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002099 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002100 struct stream_out *out = (struct stream_out *)stream;
2101
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002102 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2103 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002104 else if ((out->realtime) ||
2105 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002106 // since the buffer won't be filled up faster than realtime,
2107 // return a smaller number
2108 period_ms = (out->af_period_multiplier * out->config.period_size *
2109 1000) / (out->config.rate);
2110 hw_delay = platform_render_latency(out->usecase)/1000;
2111 return period_ms + hw_delay;
2112 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002113
2114 return (out->config.period_count * out->config.period_size * 1000) /
2115 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002116}
2117
2118static int out_set_volume(struct audio_stream_out *stream, float left,
2119 float right)
2120{
Eric Laurenta9024de2013-04-04 09:19:12 -07002121 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002122 int volume[2];
2123
Eric Laurenta9024de2013-04-04 09:19:12 -07002124 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2125 /* only take left channel into account: the API is for stereo anyway */
2126 out->muted = (left == 0.0f);
2127 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002128 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2129 const char *mixer_ctl_name = "Compress Playback Volume";
2130 struct audio_device *adev = out->dev;
2131 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002132 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2133 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002134 /* try with the control based on device id */
2135 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2136 PCM_PLAYBACK);
2137 char ctl_name[128] = {0};
2138 snprintf(ctl_name, sizeof(ctl_name),
2139 "Compress Playback %d Volume", pcm_device_id);
2140 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2141 if (!ctl) {
2142 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2143 return -EINVAL;
2144 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002145 }
2146 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2147 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2148 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2149 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002150 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002151
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002152 return -ENOSYS;
2153}
2154
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002155// note: this call is safe only if the stream_cb is
2156// removed first in close_output_stream (as is done now).
2157static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2158{
2159 if (!stream || !parms)
2160 return;
2161
2162 struct stream_out *out = (struct stream_out *)stream;
2163 struct audio_device *adev = out->dev;
2164
2165 card_status_t status;
2166 int card;
2167 if (parse_snd_card_status(parms, &card, &status) < 0)
2168 return;
2169
2170 pthread_mutex_lock(&adev->lock);
2171 bool valid_cb = (card == adev->snd_card);
2172 pthread_mutex_unlock(&adev->lock);
2173
2174 if (!valid_cb)
2175 return;
2176
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002177 lock_output_stream(out);
2178 if (out->card_status != status)
2179 out->card_status = status;
2180 pthread_mutex_unlock(&out->lock);
2181
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002182 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2183 use_case_table[out->usecase],
2184 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2185
2186 if (status == CARD_STATUS_OFFLINE)
2187 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002188
2189 return;
2190}
2191
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002192#ifdef NO_AUDIO_OUT
2193static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002194 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002195{
2196 struct stream_out *out = (struct stream_out *)stream;
2197
2198 /* No Output device supported other than BT for playback.
2199 * Sleep for the amount of buffer duration
2200 */
Eric Laurenta1478072015-09-21 17:21:52 -07002201 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002202 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2203 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002204 out_get_sample_rate(&out->stream.common));
2205 pthread_mutex_unlock(&out->lock);
2206 return bytes;
2207}
2208#endif
2209
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002210static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2211 size_t bytes)
2212{
2213 struct stream_out *out = (struct stream_out *)stream;
2214 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002215 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002216 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002217
Eric Laurenta1478072015-09-21 17:21:52 -07002218 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002219 // this is always nonzero
2220 const int frame_size = audio_stream_out_frame_size(stream);
2221
Eric Laurent0e46adf2016-12-16 12:49:24 -08002222 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2223 error_code = ERROR_CODE_WRITE;
2224 goto exit;
2225 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002226 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002227 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002228 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002229 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002230 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002231 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002232 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002233 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002234 goto exit;
2235 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002236
2237 if (last_known_cal_step != -1) {
2238 ALOGD("%s: retry previous failed cal level set", __func__);
2239 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2240 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002241 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002242
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002243 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002244 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002245 if (out->send_new_metadata) {
2246 ALOGVV("send new gapless metadata");
2247 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2248 out->send_new_metadata = 0;
2249 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002250 unsigned int avail;
2251 struct timespec tstamp;
2252 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2253 /* Do not limit write size if the available frames count is unknown */
2254 if (ret != 0) {
2255 avail = bytes;
2256 }
2257 if (avail == 0) {
2258 ret = 0;
2259 } else {
2260 if (avail > bytes) {
2261 avail = bytes;
2262 }
2263 ret = compress_write(out->compr, buffer, avail);
2264 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2265 __func__, avail, ret);
2266 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002267
Eric Laurent6e895242013-09-05 16:10:57 -07002268 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002269 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2270 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002271 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002272 compress_start(out->compr);
2273 out->playback_started = 1;
2274 out->offload_state = OFFLOAD_STATE_PLAYING;
2275 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002276 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002277 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002278 } else {
2279 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002280 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002281 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002282 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002283 return ret;
2284 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002285 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002286 if (out->pcm) {
2287 if (out->muted)
2288 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002289
Eric Laurent0e46adf2016-12-16 12:49:24 -08002290 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002291
Haynes Mathew George03c40102016-01-29 17:57:48 -08002292 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2293 out->config.rate;
2294 request_out_focus(out, ns);
2295
2296 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2297 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002298 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002299 else
2300 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002301
Haynes Mathew George03c40102016-01-29 17:57:48 -08002302 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002303 } else {
2304 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002305 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002306 }
2307
2308exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002309 // For PCM we always consume the buffer and return #bytes regardless of ret.
2310 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2311 out->written += bytes / (out->config.channels * sizeof(short));
2312 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002313 long long sleeptime_us = 0;
Andy Hungfc044e12017-03-20 09:24:22 -07002314 const int64_t now_ns = audio_utils_get_real_time_ns();
2315
Andy Hung7401c7c2016-09-21 12:41:21 -07002316 if (ret != 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002317 error_log_log(out->error_log, error_code, now_ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002318 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2319 ALOGE_IF(out->pcm != NULL,
2320 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hungfc044e12017-03-20 09:24:22 -07002321 sleeptime_us = bytes * 1000000LL / frame_size /
Andy Hung7401c7c2016-09-21 12:41:21 -07002322 out_get_sample_rate(&out->stream.common);
2323 // usleep not guaranteed for values over 1 second but we don't limit here.
2324 }
2325 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002326
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002327 pthread_mutex_unlock(&out->lock);
2328
2329 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002330 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002331 if (sleeptime_us != 0)
2332 usleep(sleeptime_us);
Andy Hungfc044e12017-03-20 09:24:22 -07002333 } else {
2334 // only log if the data is properly written (out->power_log may be null)
2335 power_log_log(out->power_log, buffer, bytes / frame_size, now_ns);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002336 }
2337 return bytes;
2338}
2339
2340static int out_get_render_position(const struct audio_stream_out *stream,
2341 uint32_t *dsp_frames)
2342{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002343 struct stream_out *out = (struct stream_out *)stream;
2344 *dsp_frames = 0;
2345 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002346 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002347 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002348 unsigned long frames = 0;
2349 // TODO: check return value
2350 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2351 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002352 ALOGVV("%s rendered frames %d sample_rate %d",
2353 __func__, *dsp_frames, out->sample_rate);
2354 }
2355 pthread_mutex_unlock(&out->lock);
2356 return 0;
2357 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002358 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002359}
2360
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002361static int out_add_audio_effect(const struct audio_stream *stream __unused,
2362 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002363{
2364 return 0;
2365}
2366
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002367static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2368 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002369{
2370 return 0;
2371}
2372
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002373static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2374 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002375{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002376 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002377}
2378
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002379static int out_get_presentation_position(const struct audio_stream_out *stream,
2380 uint64_t *frames, struct timespec *timestamp)
2381{
2382 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002383 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07002384 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002385
Eric Laurenta1478072015-09-21 17:21:52 -07002386 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002387
Eric Laurent949a0892013-09-20 09:20:13 -07002388 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2389 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002390 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002391 compress_get_tstamp(out->compr, &dsp_frames,
2392 &out->sample_rate);
2393 ALOGVV("%s rendered frames %ld sample_rate %d",
2394 __func__, dsp_frames, out->sample_rate);
2395 *frames = dsp_frames;
2396 ret = 0;
2397 /* this is the best we can do */
2398 clock_gettime(CLOCK_MONOTONIC, timestamp);
2399 }
2400 } else {
2401 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002402 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002403 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2404 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002405 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002406 // This adjustment accounts for buffering after app processor.
2407 // It is based on estimated DSP latency per use case, rather than exact.
2408 signed_frames -=
2409 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2410
Eric Laurent949a0892013-09-20 09:20:13 -07002411 // It would be unusual for this value to be negative, but check just in case ...
2412 if (signed_frames >= 0) {
2413 *frames = signed_frames;
2414 ret = 0;
2415 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002416 }
2417 }
2418 }
2419
2420 pthread_mutex_unlock(&out->lock);
2421
2422 return ret;
2423}
2424
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002425static int out_set_callback(struct audio_stream_out *stream,
2426 stream_callback_t callback, void *cookie)
2427{
2428 struct stream_out *out = (struct stream_out *)stream;
2429
2430 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002431 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002432 out->offload_callback = callback;
2433 out->offload_cookie = cookie;
2434 pthread_mutex_unlock(&out->lock);
2435 return 0;
2436}
2437
2438static int out_pause(struct audio_stream_out* stream)
2439{
2440 struct stream_out *out = (struct stream_out *)stream;
2441 int status = -ENOSYS;
2442 ALOGV("%s", __func__);
2443 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002444 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002445 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2446 status = compress_pause(out->compr);
2447 out->offload_state = OFFLOAD_STATE_PAUSED;
2448 }
2449 pthread_mutex_unlock(&out->lock);
2450 }
2451 return status;
2452}
2453
2454static int out_resume(struct audio_stream_out* stream)
2455{
2456 struct stream_out *out = (struct stream_out *)stream;
2457 int status = -ENOSYS;
2458 ALOGV("%s", __func__);
2459 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2460 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002461 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002462 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2463 status = compress_resume(out->compr);
2464 out->offload_state = OFFLOAD_STATE_PLAYING;
2465 }
2466 pthread_mutex_unlock(&out->lock);
2467 }
2468 return status;
2469}
2470
2471static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2472{
2473 struct stream_out *out = (struct stream_out *)stream;
2474 int status = -ENOSYS;
2475 ALOGV("%s", __func__);
2476 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002477 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002478 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2479 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2480 else
2481 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2482 pthread_mutex_unlock(&out->lock);
2483 }
2484 return status;
2485}
2486
2487static int out_flush(struct audio_stream_out* stream)
2488{
2489 struct stream_out *out = (struct stream_out *)stream;
2490 ALOGV("%s", __func__);
2491 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002492 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002493 stop_compressed_output_l(out);
2494 pthread_mutex_unlock(&out->lock);
2495 return 0;
2496 }
2497 return -ENOSYS;
2498}
2499
Eric Laurent0e46adf2016-12-16 12:49:24 -08002500static int out_stop(const struct audio_stream_out* stream)
2501{
2502 struct stream_out *out = (struct stream_out *)stream;
2503 struct audio_device *adev = out->dev;
2504 int ret = -ENOSYS;
2505
2506 ALOGV("%s", __func__);
2507 pthread_mutex_lock(&adev->lock);
2508 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2509 out->playback_started && out->pcm != NULL) {
2510 pcm_stop(out->pcm);
2511 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08002512 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002513 }
2514 pthread_mutex_unlock(&adev->lock);
2515 return ret;
2516}
2517
2518static int out_start(const struct audio_stream_out* stream)
2519{
2520 struct stream_out *out = (struct stream_out *)stream;
2521 struct audio_device *adev = out->dev;
2522 int ret = -ENOSYS;
2523
2524 ALOGV("%s", __func__);
2525 pthread_mutex_lock(&adev->lock);
2526 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2527 !out->playback_started && out->pcm != NULL) {
2528 ret = start_output_stream(out);
2529 if (ret == 0) {
2530 out->playback_started = true;
2531 }
2532 }
2533 pthread_mutex_unlock(&adev->lock);
2534 return ret;
2535}
2536
Phil Burkbc991042017-02-24 08:06:44 -08002537/*
2538 * Modify config->period_count based on min_size_frames
2539 */
2540static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
2541{
2542 int periodCountRequested = (min_size_frames + config->period_size - 1)
2543 / config->period_size;
2544 int periodCount = MMAP_PERIOD_COUNT_MIN;
2545
2546 ALOGV("%s original config.period_size = %d config.period_count = %d",
2547 __func__, config->period_size, config->period_count);
2548
2549 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
2550 periodCount *= 2;
2551 }
2552 config->period_count = periodCount;
2553
2554 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
2555}
2556
Eric Laurent0e46adf2016-12-16 12:49:24 -08002557static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2558 int32_t min_size_frames,
2559 struct audio_mmap_buffer_info *info)
2560{
2561 struct stream_out *out = (struct stream_out *)stream;
2562 struct audio_device *adev = out->dev;
2563 int ret = 0;
2564 unsigned int offset1;
2565 unsigned int frames1;
2566 const char *step = "";
2567
2568 ALOGV("%s", __func__);
2569 pthread_mutex_lock(&adev->lock);
2570
2571 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002572 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002573 ret = -EINVAL;
2574 goto exit;
2575 }
2576 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08002577 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002578 ret = -ENOSYS;
2579 goto exit;
2580 }
2581 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
2582 if (out->pcm_device_id < 0) {
2583 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2584 __func__, out->pcm_device_id, out->usecase);
2585 ret = -EINVAL;
2586 goto exit;
2587 }
Phil Burkbc991042017-02-24 08:06:44 -08002588
2589 adjust_mmap_period_count(&out->config, min_size_frames);
2590
Eric Laurent0e46adf2016-12-16 12:49:24 -08002591 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2592 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
2593 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2594 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
2595 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2596 step = "open";
2597 ret = -ENODEV;
2598 goto exit;
2599 }
2600 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
2601 if (ret < 0) {
2602 step = "begin";
2603 goto exit;
2604 }
2605 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
2606 info->burst_size_frames = out->config.period_size;
2607 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
2608
2609 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
2610 info->buffer_size_frames));
2611
2612 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
2613 if (ret < 0) {
2614 step = "commit";
2615 goto exit;
2616 }
Phil Burkbc991042017-02-24 08:06:44 -08002617
2618 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002619 ret = 0;
2620
2621 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
2622 __func__, info->shared_memory_address, info->buffer_size_frames);
2623
2624exit:
2625 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002626 if (out->pcm == NULL) {
2627 ALOGE("%s: %s - %d", __func__, step, ret);
2628 } else {
2629 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08002630 pcm_close(out->pcm);
2631 out->pcm = NULL;
2632 }
2633 }
2634 pthread_mutex_unlock(&adev->lock);
2635 return ret;
2636}
2637
2638static int out_get_mmap_position(const struct audio_stream_out *stream,
2639 struct audio_mmap_position *position)
2640{
2641 struct stream_out *out = (struct stream_out *)stream;
2642 ALOGVV("%s", __func__);
2643 if (position == NULL) {
2644 return -EINVAL;
2645 }
2646 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
2647 return -ENOSYS;
2648 }
2649 if (out->pcm == NULL) {
2650 return -ENOSYS;
2651 }
2652
2653 struct timespec ts = { 0, 0 };
2654 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
2655 if (ret < 0) {
2656 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2657 return ret;
2658 }
Andy Hungfc044e12017-03-20 09:24:22 -07002659 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002660 return 0;
2661}
2662
2663
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002664/** audio_stream_in implementation **/
2665static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2666{
2667 struct stream_in *in = (struct stream_in *)stream;
2668
2669 return in->config.rate;
2670}
2671
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002672static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002673{
2674 return -ENOSYS;
2675}
2676
2677static size_t in_get_buffer_size(const struct audio_stream *stream)
2678{
2679 struct stream_in *in = (struct stream_in *)stream;
2680
Haynes Mathew George03c40102016-01-29 17:57:48 -08002681 return in->config.period_size * in->af_period_multiplier *
2682 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002683}
2684
2685static uint32_t in_get_channels(const struct audio_stream *stream)
2686{
2687 struct stream_in *in = (struct stream_in *)stream;
2688
2689 return in->channel_mask;
2690}
2691
vivek mehta4ed66e62016-04-15 23:33:34 -07002692static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002693{
vivek mehta4ed66e62016-04-15 23:33:34 -07002694 struct stream_in *in = (struct stream_in *)stream;
2695 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002696}
2697
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002698static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002699{
2700 return -ENOSYS;
2701}
2702
2703static int in_standby(struct audio_stream *stream)
2704{
2705 struct stream_in *in = (struct stream_in *)stream;
2706 struct audio_device *adev = in->dev;
2707 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08002708 bool do_stop = true;
2709
Eric Laurent994a6932013-07-17 11:51:42 -07002710 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002711
2712 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002713
2714 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08002715 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002716 audio_extn_sound_trigger_stop_lab(in);
2717 in->standby = true;
2718 }
2719
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002720 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002721 if (adev->adm_deregister_stream)
2722 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2723
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002724 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002725 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002726 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002727 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002728 in->capture_started = false;
2729 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002730 if (in->pcm) {
2731 pcm_close(in->pcm);
2732 in->pcm = NULL;
2733 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002734 adev->enable_voicerx = false;
2735 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08002736 if (do_stop) {
2737 status = stop_input_stream(in);
2738 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002739 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002740 }
2741 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002742 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002743 return status;
2744}
2745
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002746static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002747{
2748 return 0;
2749}
2750
2751static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2752{
2753 struct stream_in *in = (struct stream_in *)stream;
2754 struct audio_device *adev = in->dev;
2755 struct str_parms *parms;
2756 char *str;
2757 char value[32];
2758 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07002759 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002760
Eric Laurent994a6932013-07-17 11:51:42 -07002761 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002762 parms = str_parms_create_str(kvpairs);
2763
2764 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2765
Eric Laurenta1478072015-09-21 17:21:52 -07002766 lock_input_stream(in);
2767
Eric Laurent150dbfe2013-02-27 14:31:02 -08002768 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002769 if (ret >= 0) {
2770 val = atoi(value);
2771 /* no audio source uses val == 0 */
2772 if ((in->source != val) && (val != 0)) {
2773 in->source = val;
2774 }
2775 }
2776
2777 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07002778
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002779 if (ret >= 0) {
2780 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002781 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002782 in->device = val;
2783 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002784 if (!in->standby) {
2785 ALOGV("update input routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002786 // inform adm before actual routing to prevent glitches.
2787 if (adev->adm_on_routing_change) {
2788 adev->adm_on_routing_change(adev->adm_data,
2789 in->capture_handle);
2790 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002791 select_devices(adev, in->usecase);
2792 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002793 }
2794 }
2795
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002796 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002797 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002798
2799 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002800 ALOGV("%s: exit: status(%d)", __func__, status);
2801 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002802}
2803
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002804static char* in_get_parameters(const struct audio_stream *stream __unused,
2805 const char *keys __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002806{
2807 return strdup("");
2808}
2809
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002810static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002811{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002812 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002813}
2814
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002815static void in_snd_mon_cb(void * stream, struct str_parms * parms)
2816{
2817 if (!stream || !parms)
2818 return;
2819
2820 struct stream_in *in = (struct stream_in *)stream;
2821 struct audio_device *adev = in->dev;
2822
2823 card_status_t status;
2824 int card;
2825 if (parse_snd_card_status(parms, &card, &status) < 0)
2826 return;
2827
2828 pthread_mutex_lock(&adev->lock);
2829 bool valid_cb = (card == adev->snd_card);
2830 pthread_mutex_unlock(&adev->lock);
2831
2832 if (!valid_cb)
2833 return;
2834
2835 lock_input_stream(in);
2836 if (in->card_status != status)
2837 in->card_status = status;
2838 pthread_mutex_unlock(&in->lock);
2839
2840 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
2841 use_case_table[in->usecase],
2842 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2843
2844 // a better solution would be to report error back to AF and let
2845 // it put the stream to standby
2846 if (status == CARD_STATUS_OFFLINE)
2847 in_standby(&in->stream.common);
2848
2849 return;
2850}
2851
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002852static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2853 size_t bytes)
2854{
2855 struct stream_in *in = (struct stream_in *)stream;
2856 struct audio_device *adev = in->dev;
2857 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07002858 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002859
Eric Laurenta1478072015-09-21 17:21:52 -07002860 lock_input_stream(in);
2861
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002862 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002863 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002864 /* Read from sound trigger HAL */
2865 audio_extn_sound_trigger_read(in, buffer, bytes);
2866 pthread_mutex_unlock(&in->lock);
2867 return bytes;
2868 }
2869
Eric Laurent0e46adf2016-12-16 12:49:24 -08002870 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
2871 ret = -ENOSYS;
2872 goto exit;
2873 }
2874
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002875 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002876 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002877 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002878 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002879 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002880 goto exit;
2881 }
2882 in->standby = 0;
2883 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002884
Haynes Mathew George03c40102016-01-29 17:57:48 -08002885 //what's the duration requested by the client?
2886 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
2887 in->config.rate;
2888 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002889
Haynes Mathew George03c40102016-01-29 17:57:48 -08002890 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002891 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002892 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002893 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07002894 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002895 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002896 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002897 if (ret < 0) {
2898 ALOGE("Failed to read w/err %s", strerror(errno));
2899 ret = -errno;
2900 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002901 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
2902 if (bytes % 4 == 0) {
2903 /* data from DSP comes in 24_8 format, convert it to 8_24 */
2904 int_buf_stream = buffer;
2905 for (size_t itt=0; itt < bytes/4 ; itt++) {
2906 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07002907 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002908 } else {
2909 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
2910 ret = -EINVAL;
2911 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07002912 }
2913 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002914 }
2915
Haynes Mathew George03c40102016-01-29 17:57:48 -08002916 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002917
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002918 /*
2919 * Instead of writing zeroes here, we could trust the hardware
2920 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002921 * No need to acquire adev->lock to read mic_muted here as we don't change its state.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002922 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002923 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002924 memset(buffer, 0, bytes);
2925
2926exit:
2927 pthread_mutex_unlock(&in->lock);
2928
2929 if (ret != 0) {
2930 in_standby(&in->stream.common);
2931 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Eric Laurentfdf296a2014-07-03 16:41:51 -07002932 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002933 in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08002934 memset(buffer, 0, bytes); // clear return data
2935 }
2936 if (bytes > 0) {
Andy Hung6ebe5962016-01-15 17:46:57 -08002937 in->frames_read += bytes / audio_stream_in_frame_size(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002938 }
2939 return bytes;
2940}
2941
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002942static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002943{
2944 return 0;
2945}
2946
Andy Hung6ebe5962016-01-15 17:46:57 -08002947static int in_get_capture_position(const struct audio_stream_in *stream,
2948 int64_t *frames, int64_t *time)
2949{
2950 if (stream == NULL || frames == NULL || time == NULL) {
2951 return -EINVAL;
2952 }
2953 struct stream_in *in = (struct stream_in *)stream;
2954 int ret = -ENOSYS;
2955
2956 lock_input_stream(in);
2957 if (in->pcm) {
2958 struct timespec timestamp;
2959 unsigned int avail;
2960 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
2961 *frames = in->frames_read + avail;
2962 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
2963 ret = 0;
2964 }
2965 }
2966 pthread_mutex_unlock(&in->lock);
2967 return ret;
2968}
2969
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002970static int add_remove_audio_effect(const struct audio_stream *stream,
2971 effect_handle_t effect,
2972 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002973{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002974 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002975 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002976 int status = 0;
2977 effect_descriptor_t desc;
2978
2979 status = (*effect)->get_descriptor(effect, &desc);
2980 if (status != 0)
2981 return status;
2982
Eric Laurenta1478072015-09-21 17:21:52 -07002983 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002984 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07002985 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07002986 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07002987 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002988 in->enable_aec != enable &&
2989 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2990 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002991 if (!enable)
2992 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07002993 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2994 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
2995 adev->enable_voicerx = enable;
2996 struct audio_usecase *usecase;
2997 struct listnode *node;
2998 list_for_each(node, &adev->usecase_list) {
2999 usecase = node_to_item(node, struct audio_usecase, list);
3000 if (usecase->type == PCM_PLAYBACK) {
3001 select_devices(adev, usecase->id);
3002 break;
3003 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003004 }
3005 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003006 if (!in->standby)
3007 select_devices(in->dev, in->usecase);
3008 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003009 if (in->enable_ns != enable &&
3010 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3011 in->enable_ns = enable;
3012 if (!in->standby)
3013 select_devices(in->dev, in->usecase);
3014 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003015 pthread_mutex_unlock(&in->dev->lock);
3016 pthread_mutex_unlock(&in->lock);
3017
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003018 return 0;
3019}
3020
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003021static int in_add_audio_effect(const struct audio_stream *stream,
3022 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003023{
Eric Laurent994a6932013-07-17 11:51:42 -07003024 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003025 return add_remove_audio_effect(stream, effect, true);
3026}
3027
3028static int in_remove_audio_effect(const struct audio_stream *stream,
3029 effect_handle_t effect)
3030{
Eric Laurent994a6932013-07-17 11:51:42 -07003031 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003032 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003033}
3034
Eric Laurent0e46adf2016-12-16 12:49:24 -08003035static int in_stop(const struct audio_stream_in* stream)
3036{
3037 struct stream_in *in = (struct stream_in *)stream;
3038 struct audio_device *adev = in->dev;
3039
3040 int ret = -ENOSYS;
3041 ALOGV("%s", __func__);
3042 pthread_mutex_lock(&adev->lock);
3043 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3044 in->capture_started && in->pcm != NULL) {
3045 pcm_stop(in->pcm);
3046 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003047 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003048 }
3049 pthread_mutex_unlock(&adev->lock);
3050 return ret;
3051}
3052
3053static int in_start(const struct audio_stream_in* stream)
3054{
3055 struct stream_in *in = (struct stream_in *)stream;
3056 struct audio_device *adev = in->dev;
3057 int ret = -ENOSYS;
3058
3059 ALOGV("%s in %p", __func__, in);
3060 pthread_mutex_lock(&adev->lock);
3061 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3062 !in->capture_started && in->pcm != NULL) {
3063 if (!in->capture_started) {
3064 ret = start_input_stream(in);
3065 if (ret == 0) {
3066 in->capture_started = true;
3067 }
3068 }
3069 }
3070 pthread_mutex_unlock(&adev->lock);
3071 return ret;
3072}
3073
3074static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3075 int32_t min_size_frames,
3076 struct audio_mmap_buffer_info *info)
3077{
3078 struct stream_in *in = (struct stream_in *)stream;
3079 struct audio_device *adev = in->dev;
3080 int ret = 0;
3081 unsigned int offset1;
3082 unsigned int frames1;
3083 const char *step = "";
3084
3085 pthread_mutex_lock(&adev->lock);
3086 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003087
Eric Laurent0e46adf2016-12-16 12:49:24 -08003088 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003089 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003090 ret = -EINVAL;
3091 goto exit;
3092 }
3093 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003094 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003095 ALOGV("%s in %p", __func__, in);
3096 ret = -ENOSYS;
3097 goto exit;
3098 }
3099 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3100 if (in->pcm_device_id < 0) {
3101 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3102 __func__, in->pcm_device_id, in->usecase);
3103 ret = -EINVAL;
3104 goto exit;
3105 }
Phil Burkbc991042017-02-24 08:06:44 -08003106
3107 adjust_mmap_period_count(&in->config, min_size_frames);
3108
Eric Laurent0e46adf2016-12-16 12:49:24 -08003109 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3110 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3111 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3112 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3113 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3114 step = "open";
3115 ret = -ENODEV;
3116 goto exit;
3117 }
3118
3119 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3120 if (ret < 0) {
3121 step = "begin";
3122 goto exit;
3123 }
3124 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
3125 info->burst_size_frames = in->config.period_size;
3126 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3127
3128 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(in->pcm,
3129 info->buffer_size_frames));
3130
3131 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3132 if (ret < 0) {
3133 step = "commit";
3134 goto exit;
3135 }
3136
Phil Burkbc991042017-02-24 08:06:44 -08003137 in->standby = false;
3138 ret = 0;
3139
Eric Laurent0e46adf2016-12-16 12:49:24 -08003140 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3141 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003142
3143exit:
3144 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003145 if (in->pcm == NULL) {
3146 ALOGE("%s: %s - %d", __func__, step, ret);
3147 } else {
3148 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003149 pcm_close(in->pcm);
3150 in->pcm = NULL;
3151 }
3152 }
3153 pthread_mutex_unlock(&adev->lock);
3154 return ret;
3155}
3156
3157static int in_get_mmap_position(const struct audio_stream_in *stream,
3158 struct audio_mmap_position *position)
3159{
3160 struct stream_in *in = (struct stream_in *)stream;
3161 ALOGVV("%s", __func__);
3162 if (position == NULL) {
3163 return -EINVAL;
3164 }
3165 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
3166 return -ENOSYS;
3167 }
3168 if (in->pcm == NULL) {
3169 return -ENOSYS;
3170 }
3171 struct timespec ts = { 0, 0 };
3172 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
3173 if (ret < 0) {
3174 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3175 return ret;
3176 }
Andy Hungfc044e12017-03-20 09:24:22 -07003177 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003178 return 0;
3179}
3180
3181
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003182static int adev_open_output_stream(struct audio_hw_device *dev,
3183 audio_io_handle_t handle,
3184 audio_devices_t devices,
3185 audio_output_flags_t flags,
3186 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003187 struct audio_stream_out **stream_out,
3188 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003189{
3190 struct audio_device *adev = (struct audio_device *)dev;
3191 struct stream_out *out;
3192 int i, ret;
3193
Eric Laurent994a6932013-07-17 11:51:42 -07003194 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003195 __func__, config->sample_rate, config->channel_mask, devices, flags);
3196 *stream_out = NULL;
3197 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3198
3199 if (devices == AUDIO_DEVICE_NONE)
3200 devices = AUDIO_DEVICE_OUT_SPEAKER;
3201
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003202 out->flags = flags;
3203 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003204 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003205 out->format = config->format;
3206 out->sample_rate = config->sample_rate;
3207 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3208 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003209 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003210
3211 /* Init use case and pcm_config */
3212 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
Eric Laurent7f245042013-09-30 19:22:50 -07003213 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003214 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003215 pthread_mutex_lock(&adev->lock);
3216 ret = read_hdmi_channel_masks(out);
3217 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003218 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003219 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003220
3221 if (config->sample_rate == 0)
3222 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3223 if (config->channel_mask == 0)
3224 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Eric Laurentad1cec22015-12-16 10:12:27 -08003225 if (config->format == AUDIO_FORMAT_DEFAULT)
3226 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003227
3228 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003229 out->sample_rate = config->sample_rate;
Eric Laurentad1cec22015-12-16 10:12:27 -08003230 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003231 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3232 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003233 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003234 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003235 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003236 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003237 pthread_mutex_lock(&adev->lock);
3238 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3239 pthread_mutex_unlock(&adev->lock);
3240
3241 // reject offload during card offline to allow
3242 // fallback to s/w paths
3243 if (offline) {
3244 ret = -ENODEV;
3245 goto error_open;
3246 }
3247
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003248 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3249 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3250 ALOGE("%s: Unsupported Offload information", __func__);
3251 ret = -EINVAL;
3252 goto error_open;
3253 }
3254 if (!is_supported_format(config->offload_info.format)) {
3255 ALOGE("%s: Unsupported audio format", __func__);
3256 ret = -EINVAL;
3257 goto error_open;
3258 }
3259
3260 out->compr_config.codec = (struct snd_codec *)
3261 calloc(1, sizeof(struct snd_codec));
3262
3263 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3264 if (config->offload_info.channel_mask)
3265 out->channel_mask = config->offload_info.channel_mask;
3266 else if (config->channel_mask)
3267 out->channel_mask = config->channel_mask;
3268 out->format = config->offload_info.format;
3269 out->sample_rate = config->offload_info.sample_rate;
3270
3271 out->stream.set_callback = out_set_callback;
3272 out->stream.pause = out_pause;
3273 out->stream.resume = out_resume;
3274 out->stream.drain = out_drain;
3275 out->stream.flush = out_flush;
3276
3277 out->compr_config.codec->id =
3278 get_snd_codec_id(config->offload_info.format);
3279 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3280 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07003281 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003282 out->compr_config.codec->bit_rate =
3283 config->offload_info.bit_rate;
3284 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003285 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003286 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3287
3288 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3289 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003290
3291 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003292 create_offload_callback_thread(out);
3293 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3294 __func__, config->offload_info.version,
3295 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003296 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3297 if (config->sample_rate == 0)
3298 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3299 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3300 config->sample_rate != 8000) {
3301 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3302 ret = -EINVAL;
3303 goto error_open;
3304 }
3305 out->sample_rate = config->sample_rate;
3306 out->config.rate = config->sample_rate;
3307 if (config->format == AUDIO_FORMAT_DEFAULT)
3308 config->format = AUDIO_FORMAT_PCM_16_BIT;
3309 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3310 config->format = AUDIO_FORMAT_PCM_16_BIT;
3311 ret = -EINVAL;
3312 goto error_open;
3313 }
3314 out->format = config->format;
3315 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3316 out->config = pcm_config_afe_proxy_playback;
3317 adev->voice_tx_output = out;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003318 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003319 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3320 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3321 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003322 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
3323 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3324 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003325 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3326 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003327 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003328 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003329 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3330 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3331 out->config = pcm_config_mmap_playback;
3332 out->stream.start = out_start;
3333 out->stream.stop = out_stop;
3334 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3335 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003336 } else {
3337 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3338 out->config = pcm_config_low_latency;
3339 }
3340 if (config->format != audio_format_from_pcm_format(out->config.format)) {
3341 if (k_enable_extended_precision
3342 && pcm_params_format_test(adev->use_case_table[out->usecase],
3343 pcm_format_from_audio_format(config->format))) {
3344 out->config.format = pcm_format_from_audio_format(config->format);
3345 /* out->format already set to config->format */
3346 } else {
3347 /* deny the externally proposed config format
3348 * and use the one specified in audio_hw layer configuration.
3349 * Note: out->format is returned by out->stream.common.get_format()
3350 * and is used to set config->format in the code several lines below.
3351 */
3352 out->format = audio_format_from_pcm_format(out->config.format);
3353 }
3354 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003355 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003356 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07003357 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3358 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003359
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003360 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003361 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003362 adev->primary_output = out;
3363 else {
3364 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003365 ret = -EEXIST;
3366 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003367 }
3368 }
3369
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003370 /* Check if this usecase is already existing */
3371 pthread_mutex_lock(&adev->lock);
3372 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3373 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003374 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003375 ret = -EEXIST;
3376 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003377 }
3378 pthread_mutex_unlock(&adev->lock);
3379
3380 out->stream.common.get_sample_rate = out_get_sample_rate;
3381 out->stream.common.set_sample_rate = out_set_sample_rate;
3382 out->stream.common.get_buffer_size = out_get_buffer_size;
3383 out->stream.common.get_channels = out_get_channels;
3384 out->stream.common.get_format = out_get_format;
3385 out->stream.common.set_format = out_set_format;
3386 out->stream.common.standby = out_standby;
3387 out->stream.common.dump = out_dump;
3388 out->stream.common.set_parameters = out_set_parameters;
3389 out->stream.common.get_parameters = out_get_parameters;
3390 out->stream.common.add_audio_effect = out_add_audio_effect;
3391 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3392 out->stream.get_latency = out_get_latency;
3393 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003394#ifdef NO_AUDIO_OUT
3395 out->stream.write = out_write_for_no_output;
3396#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003397 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003398#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003399 out->stream.get_render_position = out_get_render_position;
3400 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003401 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003402
Eric Laurent0e46adf2016-12-16 12:49:24 -08003403 if (out->realtime)
3404 out->af_period_multiplier = af_period_multiplier;
3405 else
3406 out->af_period_multiplier = 1;
3407
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003408 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003409 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003410 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003411
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003412 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003413 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003414 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3415
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003416 config->format = out->stream.common.get_format(&out->stream.common);
3417 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3418 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3419
Andy Hunga452b0a2017-03-15 14:51:15 -07003420 out->error_log = error_log_create(
3421 ERROR_LOG_ENTRIES,
3422 1000000000 /* aggregate consecutive identical errors within one second in ns */);
3423
Andy Hungfc044e12017-03-20 09:24:22 -07003424 const size_t POWER_LOG_FRAMES_PER_ENTRY =
3425 config->sample_rate * POWER_LOG_SAMPLING_INTERVAL_MS / 1000;
3426 // power_log may be null if the format is not supported
3427 out->power_log = power_log_create(
3428 config->sample_rate,
3429 audio_channel_count_from_out_mask(config->channel_mask),
3430 config->format,
3431 POWER_LOG_ENTRIES,
3432 POWER_LOG_FRAMES_PER_ENTRY);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003433
3434 /*
3435 By locking output stream before registering, we allow the callback
3436 to update stream's state only after stream's initial state is set to
3437 adev state.
3438 */
3439 lock_output_stream(out);
3440 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3441 pthread_mutex_lock(&adev->lock);
3442 out->card_status = adev->card_status;
3443 pthread_mutex_unlock(&adev->lock);
3444 pthread_mutex_unlock(&out->lock);
3445
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003446 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003447
Eric Laurent994a6932013-07-17 11:51:42 -07003448 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003449 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003450
3451error_open:
3452 free(out);
3453 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003454 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003455 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003456}
3457
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003458static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003459 struct audio_stream_out *stream)
3460{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003461 struct stream_out *out = (struct stream_out *)stream;
3462 struct audio_device *adev = out->dev;
3463
Eric Laurent994a6932013-07-17 11:51:42 -07003464 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003465
3466 // must deregister from sndmonitor first to prevent races
3467 // between the callback and close_stream
3468 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003469 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003470 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3471 destroy_offload_callback_thread(out);
3472
3473 if (out->compr_config.codec != NULL)
3474 free(out->compr_config.codec);
3475 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003476
3477 if (adev->voice_tx_output == out)
3478 adev->voice_tx_output = NULL;
3479
Andy Hungfc044e12017-03-20 09:24:22 -07003480 power_log_destroy(out->power_log);
3481 out->power_log = NULL;
3482
Andy Hunga452b0a2017-03-15 14:51:15 -07003483 error_log_destroy(out->error_log);
3484 out->error_log = NULL;
3485
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003486 pthread_cond_destroy(&out->cond);
3487 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003488 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003489 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003490}
3491
3492static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3493{
3494 struct audio_device *adev = (struct audio_device *)dev;
3495 struct str_parms *parms;
3496 char *str;
3497 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003498 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003499 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003500 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003501
Joe Onorato188b6222016-03-01 11:02:27 -08003502 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003503
3504 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003505
3506 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003507 status = voice_set_parameters(adev, parms);
3508 if (status != 0) {
3509 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003510 }
3511
3512 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3513 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003514 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003515 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3516 adev->bluetooth_nrec = true;
3517 else
3518 adev->bluetooth_nrec = false;
3519 }
3520
3521 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3522 if (ret >= 0) {
3523 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3524 adev->screen_off = false;
3525 else
3526 adev->screen_off = true;
3527 }
3528
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003529 ret = str_parms_get_int(parms, "rotation", &val);
3530 if (ret >= 0) {
3531 bool reverse_speakers = false;
3532 switch(val) {
3533 // FIXME: note that the code below assumes that the speakers are in the correct placement
3534 // relative to the user when the device is rotated 90deg from its default rotation. This
3535 // assumption is device-specific, not platform-specific like this code.
3536 case 270:
3537 reverse_speakers = true;
3538 break;
3539 case 0:
3540 case 90:
3541 case 180:
3542 break;
3543 default:
3544 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003545 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003546 }
Eric Laurent03f09432014-03-25 18:09:11 -07003547 if (status == 0) {
Ravi Kumar Alamanda1f60cf82015-04-23 19:45:17 -07003548 platform_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003549 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003550 }
3551
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003552 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3553 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003554 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003555 }
3556
David Linee3fe402017-03-13 10:00:42 -07003557 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3558 if (ret >= 0) {
3559 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
3560 if (device == AUDIO_DEVICE_OUT_USB_DEVICE) {
3561 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3562 if (ret >= 0) {
3563 const int card = atoi(value);
3564 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, card);
3565 }
3566 } else if (device == AUDIO_DEVICE_IN_USB_DEVICE) {
3567 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3568 if (ret >= 0) {
3569 const int card = atoi(value);
3570 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, card);
3571 }
3572 }
3573 }
3574
3575 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3576 if (ret >= 0) {
3577 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
3578 if (device == AUDIO_DEVICE_OUT_USB_DEVICE) {
3579 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3580 if (ret >= 0) {
3581 const int card = atoi(value);
3582
3583 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, card);
3584 }
3585 } else if (device == AUDIO_DEVICE_IN_USB_DEVICE) {
3586 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3587 if (ret >= 0) {
3588 const int card = atoi(value);
3589 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, card);
3590 }
3591 }
3592 }
3593
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08003594 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003595done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003596 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003597 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07003598 ALOGV("%s: exit with code(%d)", __func__, status);
3599 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003600}
3601
3602static char* adev_get_parameters(const struct audio_hw_device *dev,
3603 const char *keys)
3604{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003605 struct audio_device *adev = (struct audio_device *)dev;
3606 struct str_parms *reply = str_parms_create();
3607 struct str_parms *query = str_parms_create_str(keys);
3608 char *str;
3609
3610 pthread_mutex_lock(&adev->lock);
3611
3612 voice_get_parameters(adev, query, reply);
3613 str = str_parms_to_str(reply);
3614 str_parms_destroy(query);
3615 str_parms_destroy(reply);
3616
3617 pthread_mutex_unlock(&adev->lock);
3618 ALOGV("%s: exit: returns - %s", __func__, str);
3619 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003620}
3621
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003622static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003623{
3624 return 0;
3625}
3626
Haynes Mathew George5191a852013-09-11 14:19:36 -07003627static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3628{
3629 int ret;
3630 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003631
Eric Laurent4cc4ce12014-09-10 13:21:01 -05003632 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
3633
Haynes Mathew George5191a852013-09-11 14:19:36 -07003634 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003635 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003636 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003637
Haynes Mathew George5191a852013-09-11 14:19:36 -07003638 return ret;
3639}
3640
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003641static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003642{
3643 return -ENOSYS;
3644}
3645
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003646static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3647 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003648{
3649 return -ENOSYS;
3650}
3651
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003652static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003653{
3654 return -ENOSYS;
3655}
3656
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003657static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003658{
3659 return -ENOSYS;
3660}
3661
3662static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3663{
3664 struct audio_device *adev = (struct audio_device *)dev;
3665
3666 pthread_mutex_lock(&adev->lock);
3667 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07003668 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003669 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07003670 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3671 voice_is_in_call(adev)) {
3672 voice_stop_call(adev);
3673 adev->current_call_output = NULL;
3674 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003675 }
3676 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003677
3678 audio_extn_extspk_set_mode(adev->extspk, mode);
3679
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003680 return 0;
3681}
3682
3683static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3684{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003685 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003686 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003687
Eric Laurent2bafff12016-03-17 12:17:23 -07003688 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003689 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08003690 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
3691 ret = audio_extn_hfp_set_mic_mute(adev, state);
3692 } else {
3693 ret = voice_set_mic_mute(adev, state);
3694 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003695 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00003696 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003697
3698 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003699}
3700
3701static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3702{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003703 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003704 return 0;
3705}
3706
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003707static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003708 const struct audio_config *config)
3709{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003710 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003711
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003712 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3713 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003714}
3715
3716static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003717 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003718 audio_devices_t devices,
3719 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003720 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07003721 audio_input_flags_t flags,
3722 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05003723 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003724{
3725 struct audio_device *adev = (struct audio_device *)dev;
3726 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003727 int ret = 0, buffer_size, frame_size;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003728 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003729 bool is_low_latency = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003730
Eric Laurent994a6932013-07-17 11:51:42 -07003731 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003732 *stream_in = NULL;
3733 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3734 return -EINVAL;
3735
Zheng Zhang6185d572016-12-01 20:35:17 +08003736 if (audio_extn_tfa_98xx_is_supported() && (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08003737 return -EINVAL;
3738
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003739 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
3740
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003741 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003742 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003743
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003744 in->stream.common.get_sample_rate = in_get_sample_rate;
3745 in->stream.common.set_sample_rate = in_set_sample_rate;
3746 in->stream.common.get_buffer_size = in_get_buffer_size;
3747 in->stream.common.get_channels = in_get_channels;
3748 in->stream.common.get_format = in_get_format;
3749 in->stream.common.set_format = in_set_format;
3750 in->stream.common.standby = in_standby;
3751 in->stream.common.dump = in_dump;
3752 in->stream.common.set_parameters = in_set_parameters;
3753 in->stream.common.get_parameters = in_get_parameters;
3754 in->stream.common.add_audio_effect = in_add_audio_effect;
3755 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3756 in->stream.set_gain = in_set_gain;
3757 in->stream.read = in_read;
3758 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08003759 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003760
3761 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003762 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003763 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003764 in->standby = 1;
3765 in->channel_mask = config->channel_mask;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003766 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003767 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003768
vivek mehta57ff9b52016-04-28 14:13:08 -07003769 // restrict 24 bit capture for unprocessed source only
3770 // for other sources if 24 bit requested reject 24 and set 16 bit capture only
3771 if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07003772 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07003773 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
3774 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
3775 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
3776 bool ret_error = false;
3777 /* 24 bit is restricted to UNPROCESSED source only,also format supported
3778 from HAL is 8_24
3779 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
3780 8_24 return error indicating supported format is 8_24
3781 *> In case of any other source requesting 24 bit or float return error
3782 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07003783
vivek mehta57ff9b52016-04-28 14:13:08 -07003784 on error flinger will retry with supported format passed
3785 */
3786 if (source != AUDIO_SOURCE_UNPROCESSED) {
3787 config->format = AUDIO_FORMAT_PCM_16_BIT;
3788 ret_error = true;
3789 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
3790 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
3791 ret_error = true;
3792 }
3793
3794 if (ret_error) {
3795 ret = -EINVAL;
3796 goto err_open;
3797 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003798 }
3799
vivek mehta57ff9b52016-04-28 14:13:08 -07003800 in->format = config->format;
3801
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003802 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003803 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
3804 if (config->sample_rate == 0)
3805 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3806 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3807 config->sample_rate != 8000) {
3808 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3809 ret = -EINVAL;
3810 goto err_open;
3811 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003812
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003813 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3814 config->format = AUDIO_FORMAT_PCM_16_BIT;
3815 ret = -EINVAL;
3816 goto err_open;
3817 }
3818
3819 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3820 in->config = pcm_config_afe_proxy_record;
David Lin73f45252017-03-29 13:37:33 -07003821 in->af_period_multiplier = 1;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003822 } 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
Kevin Rocarda5453442017-05-02 15:09:20 -07004054 audio_extn_snd_mon_unregister_listener(adev);
Kevin Rocard8342c2c2017-04-07 18:50:00 -07004055 audio_extn_snd_mon_deinit();
Kevin Rocarda5453442017-05-02 15:09:20 -07004056
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004057 audio_extn_tfa_98xx_deinit();
4058
vivek mehta1a9b7c02015-06-25 11:49:38 -07004059 pthread_mutex_lock(&adev_init_lock);
4060
4061 if ((--audio_device_ref_count) == 0) {
4062 audio_route_free(adev->audio_route);
4063 free(adev->snd_dev_ref_cnt);
4064 platform_deinit(adev->platform);
4065 audio_extn_extspk_deinit(adev->extspk);
4066 audio_extn_sound_trigger_deinit(adev);
4067 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4068 pcm_params_free(adev->use_case_table[i]);
4069 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004070 if (adev->adm_deinit)
4071 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004072 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004073 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004074
4075 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004076
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004077 return 0;
4078}
4079
Glenn Kasten4f993392014-05-14 07:30:48 -07004080/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4081 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4082 * just that it _might_ work.
4083 */
4084static int period_size_is_plausible_for_low_latency(int period_size)
4085{
4086 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004087 case 48:
4088 case 96:
4089 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004090 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004091 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004092 case 240:
4093 case 320:
4094 case 480:
4095 return 1;
4096 default:
4097 return 0;
4098 }
4099}
4100
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004101static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4102{
4103 int card;
4104 card_status_t status;
4105
4106 if (!parms)
4107 return;
4108
4109 if (parse_snd_card_status(parms, &card, &status) < 0)
4110 return;
4111
4112 pthread_mutex_lock(&adev->lock);
4113 bool valid_cb = (card == adev->snd_card);
4114 if (valid_cb) {
4115 if (adev->card_status != status) {
4116 adev->card_status = status;
4117 platform_snd_card_update(adev->platform, status);
4118 }
4119 }
4120 pthread_mutex_unlock(&adev->lock);
4121 return;
4122}
4123
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004124static int adev_open(const hw_module_t *module, const char *name,
4125 hw_device_t **device)
4126{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004127 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004128
Eric Laurent2bafff12016-03-17 12:17:23 -07004129 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004130 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004131 pthread_mutex_lock(&adev_init_lock);
4132 if (audio_device_ref_count != 0) {
4133 *device = &adev->device.common;
4134 audio_device_ref_count++;
4135 ALOGV("%s: returning existing instance of adev", __func__);
4136 ALOGV("%s: exit", __func__);
4137 pthread_mutex_unlock(&adev_init_lock);
4138 return 0;
4139 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004140 adev = calloc(1, sizeof(struct audio_device));
4141
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004142 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4143
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004144 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4145 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4146 adev->device.common.module = (struct hw_module_t *)module;
4147 adev->device.common.close = adev_close;
4148
4149 adev->device.init_check = adev_init_check;
4150 adev->device.set_voice_volume = adev_set_voice_volume;
4151 adev->device.set_master_volume = adev_set_master_volume;
4152 adev->device.get_master_volume = adev_get_master_volume;
4153 adev->device.set_master_mute = adev_set_master_mute;
4154 adev->device.get_master_mute = adev_get_master_mute;
4155 adev->device.set_mode = adev_set_mode;
4156 adev->device.set_mic_mute = adev_set_mic_mute;
4157 adev->device.get_mic_mute = adev_get_mic_mute;
4158 adev->device.set_parameters = adev_set_parameters;
4159 adev->device.get_parameters = adev_get_parameters;
4160 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4161 adev->device.open_output_stream = adev_open_output_stream;
4162 adev->device.close_output_stream = adev_close_output_stream;
4163 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004164
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004165 adev->device.close_input_stream = adev_close_input_stream;
4166 adev->device.dump = adev_dump;
4167
4168 /* Set the default route before the PCM stream is opened */
4169 pthread_mutex_lock(&adev->lock);
4170 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004171 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004172 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004173 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004174 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004175 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004176 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004177 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004178 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004179 pthread_mutex_unlock(&adev->lock);
4180
4181 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004182 adev->platform = platform_init(adev);
4183 if (!adev->platform) {
4184 free(adev->snd_dev_ref_cnt);
4185 free(adev);
4186 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4187 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004188 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004189 return -EINVAL;
4190 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05004191 adev->extspk = audio_extn_extspk_init(adev);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004192 audio_extn_sound_trigger_init(adev);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004193
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004194 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4195 if (adev->visualizer_lib == NULL) {
4196 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4197 } else {
4198 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4199 adev->visualizer_start_output =
4200 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4201 "visualizer_hal_start_output");
4202 adev->visualizer_stop_output =
4203 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4204 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07004205 }
4206
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004207 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4208 if (adev->offload_effects_lib == NULL) {
4209 ALOGW("%s: DLOPEN failed for %s", __func__,
4210 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4211 } else {
4212 ALOGV("%s: DLOPEN successful for %s", __func__,
4213 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4214 adev->offload_effects_start_output =
4215 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4216 "offload_effects_bundle_hal_start_output");
4217 adev->offload_effects_stop_output =
4218 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4219 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07004220 }
4221
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004222 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4223 if (adev->adm_lib == NULL) {
4224 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4225 } else {
4226 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4227 adev->adm_init = (adm_init_t)
4228 dlsym(adev->adm_lib, "adm_init");
4229 adev->adm_deinit = (adm_deinit_t)
4230 dlsym(adev->adm_lib, "adm_deinit");
4231 adev->adm_register_input_stream = (adm_register_input_stream_t)
4232 dlsym(adev->adm_lib, "adm_register_input_stream");
4233 adev->adm_register_output_stream = (adm_register_output_stream_t)
4234 dlsym(adev->adm_lib, "adm_register_output_stream");
4235 adev->adm_deregister_stream = (adm_deregister_stream_t)
4236 dlsym(adev->adm_lib, "adm_deregister_stream");
4237 adev->adm_request_focus = (adm_request_focus_t)
4238 dlsym(adev->adm_lib, "adm_request_focus");
4239 adev->adm_abandon_focus = (adm_abandon_focus_t)
4240 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08004241 adev->adm_set_config = (adm_set_config_t)
4242 dlsym(adev->adm_lib, "adm_set_config");
4243 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4244 dlsym(adev->adm_lib, "adm_request_focus_v2");
4245 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4246 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4247 adev->adm_on_routing_change = (adm_on_routing_change_t)
4248 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004249 }
4250
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004251 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004252 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004253
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004254 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004255
Andy Hung31aca912014-03-20 17:14:59 -07004256 if (k_enable_extended_precision)
4257 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004258
Glenn Kasten4f993392014-05-14 07:30:48 -07004259 char value[PROPERTY_VALUE_MAX];
4260 int trial;
4261 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4262 trial = atoi(value);
4263 if (period_size_is_plausible_for_low_latency(trial)) {
4264 pcm_config_low_latency.period_size = trial;
4265 pcm_config_low_latency.start_threshold = trial / 4;
4266 pcm_config_low_latency.avail_min = trial / 4;
4267 configured_low_latency_capture_period_size = trial;
4268 }
4269 }
4270 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4271 trial = atoi(value);
4272 if (period_size_is_plausible_for_low_latency(trial)) {
4273 configured_low_latency_capture_period_size = trial;
4274 }
4275 }
4276
Yamit Mehtae3b99562016-09-16 22:44:00 +05304277 audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004278 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004279
4280 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4281 af_period_multiplier = atoi(value);
4282 if (af_period_multiplier < 0) {
4283 af_period_multiplier = 2;
4284 } else if (af_period_multiplier > 4) {
4285 af_period_multiplier = 4;
4286 }
4287 ALOGV("new period_multiplier = %d", af_period_multiplier);
4288 }
4289
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004290 audio_extn_tfa_98xx_init(adev);
4291
vivek mehta1a9b7c02015-06-25 11:49:38 -07004292 pthread_mutex_unlock(&adev_init_lock);
4293
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004294 if (adev->adm_init)
4295 adev->adm_data = adev->adm_init();
4296
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004297 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004298 audio_extn_snd_mon_init();
4299 pthread_mutex_lock(&adev->lock);
4300 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
4301 adev->card_status = CARD_STATUS_ONLINE;
4302 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004303
Eric Laurent2bafff12016-03-17 12:17:23 -07004304 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004305 return 0;
4306}
4307
4308static struct hw_module_methods_t hal_module_methods = {
4309 .open = adev_open,
4310};
4311
4312struct audio_module HAL_MODULE_INFO_SYM = {
4313 .common = {
4314 .tag = HARDWARE_MODULE_TAG,
4315 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4316 .hal_api_version = HARDWARE_HAL_API_VERSION,
4317 .id = AUDIO_HARDWARE_MODULE_ID,
4318 .name = "QCOM Audio HAL",
4319 .author = "Code Aurora Forum",
4320 .methods = &hal_module_methods,
4321 },
4322};