blob: 2349a566de6364658174fff2bc8fe563c3db64f6 [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;
Andy Hung9e737de2017-05-22 10:51:22 -0700274static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700275static 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
Andy Hung9e737de2017-05-22 10:51:22 -0700279// TODO: Consider moving this to a pthread_once() if we have more
280// static initialization required.
281static bool is_userdebug_or_eng_build() {
282 char value[PROPERTY_VALUE_MAX];
283 (void)property_get("ro.build.type", value, "unknown"); // ignore actual length
284 return strcmp(value, "userdebug") == 0 || strcmp(value, "eng") == 0;
285}
286
Haynes Mathew George03c40102016-01-29 17:57:48 -0800287static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
288 int flags __unused)
289{
290 int dir = 0;
291 switch (uc_id) {
292 case USECASE_AUDIO_RECORD_LOW_LATENCY:
293 dir = 1;
294 case USECASE_AUDIO_PLAYBACK_ULL:
295 break;
296 default:
297 return false;
298 }
299
300 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
301 PCM_PLAYBACK : PCM_CAPTURE);
302 if (adev->adm_is_noirq_avail)
303 return adev->adm_is_noirq_avail(adev->adm_data,
304 adev->snd_card, dev_id, dir);
305 return false;
306}
307
308static void register_out_stream(struct stream_out *out)
309{
310 struct audio_device *adev = out->dev;
311 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
312 return;
313
314 if (!adev->adm_register_output_stream)
315 return;
316
317 adev->adm_register_output_stream(adev->adm_data,
318 out->handle,
319 out->flags);
320
321 if (!adev->adm_set_config)
322 return;
323
324 if (out->realtime) {
325 adev->adm_set_config(adev->adm_data,
326 out->handle,
327 out->pcm, &out->config);
328 }
329}
330
331static void register_in_stream(struct stream_in *in)
332{
333 struct audio_device *adev = in->dev;
334 if (!adev->adm_register_input_stream)
335 return;
336
337 adev->adm_register_input_stream(adev->adm_data,
338 in->capture_handle,
339 in->flags);
340
341 if (!adev->adm_set_config)
342 return;
343
344 if (in->realtime) {
345 adev->adm_set_config(adev->adm_data,
346 in->capture_handle,
347 in->pcm,
348 &in->config);
349 }
350}
351
352static void request_out_focus(struct stream_out *out, long ns)
353{
354 struct audio_device *adev = out->dev;
355
Haynes Mathew George03c40102016-01-29 17:57:48 -0800356 if (adev->adm_request_focus_v2) {
357 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
358 } else if (adev->adm_request_focus) {
359 adev->adm_request_focus(adev->adm_data, out->handle);
360 }
361}
362
363static void request_in_focus(struct stream_in *in, long ns)
364{
365 struct audio_device *adev = in->dev;
366
Haynes Mathew George03c40102016-01-29 17:57:48 -0800367 if (adev->adm_request_focus_v2) {
368 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
369 } else if (adev->adm_request_focus) {
370 adev->adm_request_focus(adev->adm_data, in->capture_handle);
371 }
372}
373
374static void release_out_focus(struct stream_out *out, long ns __unused)
375{
376 struct audio_device *adev = out->dev;
377
378 if (adev->adm_abandon_focus)
379 adev->adm_abandon_focus(adev->adm_data, out->handle);
380}
381
382static void release_in_focus(struct stream_in *in, long ns __unused)
383{
384 struct audio_device *adev = in->dev;
385 if (adev->adm_abandon_focus)
386 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
387}
388
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700389static int parse_snd_card_status(struct str_parms * parms, int * card,
390 card_status_t * status)
391{
392 char value[32]={0};
393 char state[32]={0};
394
395 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
396
397 if (ret < 0)
398 return -1;
399
400 // sscanf should be okay as value is of max length 32.
401 // same as sizeof state.
402 if (sscanf(value, "%d,%s", card, state) < 2)
403 return -1;
404
405 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
406 CARD_STATUS_OFFLINE;
407 return 0;
408}
409
vivek mehta1a9b7c02015-06-25 11:49:38 -0700410__attribute__ ((visibility ("default")))
411bool audio_hw_send_gain_dep_calibration(int level) {
412 bool ret_val = false;
413 ALOGV("%s: enter ... ", __func__);
414
415 pthread_mutex_lock(&adev_init_lock);
416
417 if (adev != NULL && adev->platform != NULL) {
418 pthread_mutex_lock(&adev->lock);
419 ret_val = platform_send_gain_dep_cal(adev->platform, level);
420 pthread_mutex_unlock(&adev->lock);
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700421
422 // if cal set fails, cache level info
423 // if cal set succeds, reset known last cal set
424 if (!ret_val)
425 last_known_cal_step = level;
426 else if (last_known_cal_step != -1)
427 last_known_cal_step = -1;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700428 } else {
429 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
430 }
431
432 pthread_mutex_unlock(&adev_init_lock);
433
434 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
435 return ret_val;
436}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700437
vivek mehtaa8d7c922016-05-25 14:40:44 -0700438__attribute__ ((visibility ("default")))
439int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
440 int table_size) {
441 int ret_val = 0;
442 ALOGV("%s: enter ... ", __func__);
443
444 pthread_mutex_lock(&adev_init_lock);
445 if (adev == NULL) {
446 ALOGW("%s: adev is NULL .... ", __func__);
447 goto done;
448 }
449
450 pthread_mutex_lock(&adev->lock);
451 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
452 pthread_mutex_unlock(&adev->lock);
453done:
454 pthread_mutex_unlock(&adev_init_lock);
455 ALOGV("%s: exit ... ", __func__);
456 return ret_val;
457}
458
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700459static bool is_supported_format(audio_format_t format)
460{
Eric Laurent8251ac82014-07-23 11:00:25 -0700461 switch (format) {
462 case AUDIO_FORMAT_MP3:
463 case AUDIO_FORMAT_AAC_LC:
464 case AUDIO_FORMAT_AAC_HE_V1:
465 case AUDIO_FORMAT_AAC_HE_V2:
466 return true;
467 default:
468 break;
469 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700470 return false;
471}
472
Haynes Mathew George03c40102016-01-29 17:57:48 -0800473static inline bool is_mmap_usecase(audio_usecase_t uc_id)
474{
475 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
476 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
477}
478
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700479static int get_snd_codec_id(audio_format_t format)
480{
481 int id = 0;
482
Eric Laurent8251ac82014-07-23 11:00:25 -0700483 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700484 case AUDIO_FORMAT_MP3:
485 id = SND_AUDIOCODEC_MP3;
486 break;
487 case AUDIO_FORMAT_AAC:
488 id = SND_AUDIOCODEC_AAC;
489 break;
490 default:
491 ALOGE("%s: Unsupported audio format", __func__);
492 }
493
494 return id;
495}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800496
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800497static int audio_ssr_status(struct audio_device *adev)
498{
499 int ret = 0;
500 struct mixer_ctl *ctl;
501 const char *mixer_ctl_name = "Audio SSR Status";
502
503 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
504 ret = mixer_ctl_get_value(ctl, 0);
505 ALOGD("%s: value: %d", __func__, ret);
506 return ret;
507}
508
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800509int enable_audio_route(struct audio_device *adev,
510 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800511{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700512 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800513 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800514
515 if (usecase == NULL)
516 return -EINVAL;
517
518 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
519
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800520 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700521 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800522 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700523 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800524
Yamit Mehtae3b99562016-09-16 22:44:00 +0530525 audio_extn_utils_send_app_type_cfg(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800526 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500527 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700528 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700529 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800530
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800531 ALOGV("%s: exit", __func__);
532 return 0;
533}
534
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800535int disable_audio_route(struct audio_device *adev,
536 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800537{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700538 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800539 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800540
541 if (usecase == NULL)
542 return -EINVAL;
543
544 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700545 if (usecase->type == PCM_CAPTURE)
546 snd_device = usecase->in_snd_device;
547 else
548 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800549 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500550 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700551 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700552 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800553
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800554 ALOGV("%s: exit", __func__);
555 return 0;
556}
557
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800558int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700559 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800560{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700561 int i, num_devices = 0;
562 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800563 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800564 if (snd_device < SND_DEVICE_MIN ||
565 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800566 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800567 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800568 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700569
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700570 platform_send_audio_calibration(adev->platform, snd_device);
571
vivek mehtade4849c2016-03-03 17:23:38 -0800572 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700573 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700574 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800575 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700576 }
577
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700578 /* due to the possibility of calibration overwrite between listen
579 and audio, notify sound trigger hal before audio calibration is sent */
580 audio_extn_sound_trigger_update_device_status(snd_device,
581 ST_EVENT_SND_DEVICE_BUSY);
582
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700583 if (audio_extn_spkr_prot_is_enabled())
584 audio_extn_spkr_prot_calib_cancel(adev);
585
zhaoyang yin4211fad2015-06-04 21:13:25 +0800586 audio_extn_dsm_feedback_enable(adev, snd_device, true);
587
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700588 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
589 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
590 audio_extn_spkr_prot_is_enabled()) {
591 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800592 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700593 }
594 if (audio_extn_spkr_prot_start_processing(snd_device)) {
595 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800596 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700597 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700598 } else if (platform_can_split_snd_device(snd_device,
599 &num_devices,
600 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700601 for (i = 0; i < num_devices; i++) {
602 enable_snd_device(adev, new_snd_devices[i]);
603 }
vivek mehtab6506412015-08-07 16:55:17 -0700604 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700605 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800606 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
607 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
608 ALOGE(" %s: Invalid sound device returned", __func__);
609 goto on_error;
610 }
Ed Tam70b5c142016-03-21 19:14:29 -0700611
Eric Laurent2e140aa2016-06-30 17:14:46 -0700612 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800613 audio_route_apply_and_update_path(adev->audio_route, device_name);
614 }
615on_success:
616 adev->snd_dev_ref_cnt[snd_device]++;
617 ret_val = 0;
618on_error:
619 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800620}
621
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800622int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700623 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800624{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700625 int i, num_devices = 0;
626 snd_device_t new_snd_devices[2];
627
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800628 if (snd_device < SND_DEVICE_MIN ||
629 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800630 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800631 return -EINVAL;
632 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700633 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
634 ALOGE("%s: device ref cnt is already 0", __func__);
635 return -EINVAL;
636 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800637 audio_extn_tfa_98xx_disable_speaker(snd_device);
638
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700639 adev->snd_dev_ref_cnt[snd_device]--;
640 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800641 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700642 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
643 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
644 audio_extn_spkr_prot_is_enabled()) {
645 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700646 } else if (platform_can_split_snd_device(snd_device,
647 &num_devices,
648 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700649 for (i = 0; i < num_devices; i++) {
650 disable_snd_device(adev, new_snd_devices[i]);
651 }
vivek mehtab6506412015-08-07 16:55:17 -0700652 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700653 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800654 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
655 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
656 ALOGE(" %s: Invalid sound device returned", __func__);
657 return -EINVAL;
658 }
659
Eric Laurent2e140aa2016-06-30 17:14:46 -0700660 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800661 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700662 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700663 audio_extn_sound_trigger_update_device_status(snd_device,
664 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700665 }
vivek mehtab6506412015-08-07 16:55:17 -0700666
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800667 return 0;
668}
669
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700670/*
671 legend:
672 uc - existing usecase
673 new_uc - new usecase
674 d1, d11, d2 - SND_DEVICE enums
675 a1, a2 - corresponding ANDROID device enums
676 B, B1, B2 - backend strings
677
678case 1
679 uc->dev d1 (a1) B1
680 new_uc->dev d1 (a1), d2 (a2) B1, B2
681
682 resolution: disable and enable uc->dev on d1
683
684case 2
685 uc->dev d1 (a1) B1
686 new_uc->dev d11 (a1) B1
687
688 resolution: need to switch uc since d1 and d11 are related
689 (e.g. speaker and voice-speaker)
690 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
691
692case 3
693 uc->dev d1 (a1) B1
694 new_uc->dev d2 (a2) B2
695
696 resolution: no need to switch uc
697
698case 4
699 uc->dev d1 (a1) B
700 new_uc->dev d2 (a2) B
701
702 resolution: disable enable uc-dev on d2 since backends match
703 we cannot enable two streams on two different devices if they
704 share the same backend. e.g. if offload is on speaker device using
705 QUAD_MI2S backend and a low-latency stream is started on voice-handset
706 using the same backend, offload must also be switched to voice-handset.
707
708case 5
709 uc->dev d1 (a1) B
710 new_uc->dev d1 (a1), d2 (a2) B
711
712 resolution: disable enable uc-dev on d2 since backends match
713 we cannot enable two streams on two different devices if they
714 share the same backend.
715
716case 6
717 uc->dev d1 a1 B1
718 new_uc->dev d2 a1 B2
719
720 resolution: no need to switch
721
722case 7
723
724 uc->dev d1 (a1), d2 (a2) B1, B2
725 new_uc->dev d1 B1
726
727 resolution: no need to switch
728
729*/
730static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
731 struct audio_usecase *new_uc,
732 snd_device_t new_snd_device)
733{
734 audio_devices_t a1 = uc->stream.out->devices;
735 audio_devices_t a2 = new_uc->stream.out->devices;
736
737 snd_device_t d1 = uc->out_snd_device;
738 snd_device_t d2 = new_snd_device;
739
740 // Treat as a special case when a1 and a2 are not disjoint
741 if ((a1 != a2) && (a1 & a2)) {
742 snd_device_t d3[2];
743 int num_devices = 0;
744 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
745 &num_devices,
746 d3);
747 if (ret < 0) {
748 if (ret != -ENOSYS) {
749 ALOGW("%s failed to split snd_device %d",
750 __func__,
751 popcount(a1) > 1 ? d1 : d2);
752 }
753 goto end;
754 }
755
756 // NB: case 7 is hypothetical and isn't a practical usecase yet.
757 // But if it does happen, we need to give priority to d2 if
758 // the combo devices active on the existing usecase share a backend.
759 // This is because we cannot have a usecase active on a combo device
760 // and a new usecase requests one device in this combo pair.
761 if (platform_check_backends_match(d3[0], d3[1])) {
762 return d2; // case 5
763 } else {
764 return d1; // case 1
765 }
766 } else {
767 if (platform_check_backends_match(d1, d2)) {
768 return d2; // case 2, 4
769 } else {
770 return d1; // case 6, 3
771 }
772 }
773
774end:
775 return d2; // return whatever was calculated before.
776}
777
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700778static void check_and_route_playback_usecases(struct audio_device *adev,
779 struct audio_usecase *uc_info,
780 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700781{
782 struct listnode *node;
783 struct audio_usecase *usecase;
784 bool switch_device[AUDIO_USECASE_MAX];
785 int i, num_uc_to_switch = 0;
786
David Linee3fe402017-03-13 10:00:42 -0700787 platform_check_and_set_playback_backend_cfg(adev, uc_info, snd_device);
788
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700789 /*
790 * This function is to make sure that all the usecases that are active on
791 * the hardware codec backend are always routed to any one device that is
792 * handled by the hardware codec.
793 * For example, if low-latency and deep-buffer usecases are currently active
794 * on speaker and out_set_parameters(headset) is received on low-latency
795 * output, then we have to make sure deep-buffer is also switched to headset,
796 * because of the limitation that both the devices cannot be enabled
797 * at the same time as they share the same backend.
798 */
799 /* Disable all the usecases on the shared backend other than the
800 specified usecase */
801 for (i = 0; i < AUDIO_USECASE_MAX; i++)
802 switch_device[i] = false;
803
804 list_for_each(node, &adev->usecase_list) {
805 usecase = node_to_item(node, struct audio_usecase, list);
806 if (usecase->type != PCM_CAPTURE &&
807 usecase != uc_info &&
808 usecase->out_snd_device != snd_device &&
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700809 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
810 platform_check_backends_match(snd_device, usecase->out_snd_device)) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700811 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
812 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700813 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700814 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700815 switch_device[usecase->id] = true;
816 num_uc_to_switch++;
817 }
818 }
819
820 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700821 list_for_each(node, &adev->usecase_list) {
822 usecase = node_to_item(node, struct audio_usecase, list);
823 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700824 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900825 }
826 }
827
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700828 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900829 list_for_each(node, &adev->usecase_list) {
830 usecase = node_to_item(node, struct audio_usecase, list);
831 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700832 d_device = derive_playback_snd_device(usecase, uc_info,
833 snd_device);
834 enable_snd_device(adev, d_device);
835 /* Update the out_snd_device before enabling the audio route */
836 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700837 }
838 }
839
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700840 /* Re-route all the usecases on the shared backend other than the
841 specified usecase to new snd devices */
842 list_for_each(node, &adev->usecase_list) {
843 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700844 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700845 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700846 }
847 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700848 }
849}
850
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700851static void check_and_route_capture_usecases(struct audio_device *adev,
852 struct audio_usecase *uc_info,
853 snd_device_t snd_device)
854{
855 struct listnode *node;
856 struct audio_usecase *usecase;
857 bool switch_device[AUDIO_USECASE_MAX];
858 int i, num_uc_to_switch = 0;
859
vivek mehta4ed66e62016-04-15 23:33:34 -0700860 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
861
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700862 /*
863 * This function is to make sure that all the active capture usecases
864 * are always routed to the same input sound device.
865 * For example, if audio-record and voice-call usecases are currently
866 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
867 * is received for voice call then we have to make sure that audio-record
868 * usecase is also switched to earpiece i.e. voice-dmic-ef,
869 * because of the limitation that two devices cannot be enabled
870 * at the same time if they share the same backend.
871 */
872 for (i = 0; i < AUDIO_USECASE_MAX; i++)
873 switch_device[i] = false;
874
875 list_for_each(node, &adev->usecase_list) {
876 usecase = node_to_item(node, struct audio_usecase, list);
877 if (usecase->type != PCM_PLAYBACK &&
878 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700879 usecase->in_snd_device != snd_device &&
880 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700881 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
882 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700883 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700884 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700885 switch_device[usecase->id] = true;
886 num_uc_to_switch++;
887 }
888 }
889
890 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700891 list_for_each(node, &adev->usecase_list) {
892 usecase = node_to_item(node, struct audio_usecase, list);
893 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700894 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700895 }
896 }
897
898 list_for_each(node, &adev->usecase_list) {
899 usecase = node_to_item(node, struct audio_usecase, list);
900 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700901 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700902 }
903 }
904
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700905 /* Re-route all the usecases on the shared backend other than the
906 specified usecase to new snd devices */
907 list_for_each(node, &adev->usecase_list) {
908 usecase = node_to_item(node, struct audio_usecase, list);
909 /* Update the in_snd_device only before enabling the audio route */
910 if (switch_device[usecase->id] ) {
911 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700912 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700913 }
914 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700915 }
916}
917
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800918/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700919static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800920{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700921 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700922 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800923
924 switch (channels) {
925 /*
926 * Do not handle stereo output in Multi-channel cases
927 * Stereo case is handled in normal playback path
928 */
929 case 6:
930 ALOGV("%s: HDMI supports 5.1", __func__);
931 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
932 break;
933 case 8:
934 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
935 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
936 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
937 break;
938 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700939 ALOGE("HDMI does not support multi channel playback");
940 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800941 break;
942 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700943 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800944}
945
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -0700946static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
947{
948 struct audio_usecase *usecase;
949 struct listnode *node;
950
951 list_for_each(node, &adev->usecase_list) {
952 usecase = node_to_item(node, struct audio_usecase, list);
953 if (usecase->type == VOICE_CALL) {
954 ALOGV("%s: usecase id %d", __func__, usecase->id);
955 return usecase->id;
956 }
957 }
958 return USECASE_INVALID;
959}
960
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800961struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
962 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700963{
964 struct audio_usecase *usecase;
965 struct listnode *node;
966
967 list_for_each(node, &adev->usecase_list) {
968 usecase = node_to_item(node, struct audio_usecase, list);
969 if (usecase->id == uc_id)
970 return usecase;
971 }
972 return NULL;
973}
974
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800975int select_devices(struct audio_device *adev,
976 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800977{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800978 snd_device_t out_snd_device = SND_DEVICE_NONE;
979 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700980 struct audio_usecase *usecase = NULL;
981 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800982 struct audio_usecase *hfp_usecase = NULL;
983 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800984 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700985 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800986
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700987 usecase = get_usecase_from_list(adev, uc_id);
988 if (usecase == NULL) {
989 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
990 return -EINVAL;
991 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800992
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800993 if ((usecase->type == VOICE_CALL) ||
994 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700995 out_snd_device = platform_get_output_snd_device(adev->platform,
996 usecase->stream.out->devices);
997 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700998 usecase->devices = usecase->stream.out->devices;
999 } else {
1000 /*
1001 * If the voice call is active, use the sound devices of voice call usecase
1002 * so that it would not result any device switch. All the usecases will
1003 * be switched to new device when select_devices() is called for voice call
1004 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001005 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001006 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001007 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001008 vc_usecase = get_usecase_from_list(adev,
1009 get_voice_usecase_id_from_list(adev));
1010 if ((vc_usecase != NULL) &&
1011 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1012 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001013 in_snd_device = vc_usecase->in_snd_device;
1014 out_snd_device = vc_usecase->out_snd_device;
1015 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001016 } else if (audio_extn_hfp_is_active(adev)) {
1017 hfp_ucid = audio_extn_hfp_get_usecase();
1018 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1019 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1020 in_snd_device = hfp_usecase->in_snd_device;
1021 out_snd_device = hfp_usecase->out_snd_device;
1022 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001023 }
1024 if (usecase->type == PCM_PLAYBACK) {
1025 usecase->devices = usecase->stream.out->devices;
1026 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001027 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001028 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001029 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001030 if (usecase->stream.out == adev->primary_output &&
1031 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001032 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1033 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001034 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001035 select_devices(adev, adev->active_input->usecase);
1036 }
1037 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001038 } else if (usecase->type == PCM_CAPTURE) {
1039 usecase->devices = usecase->stream.in->device;
1040 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001041 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001042 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001043 if (adev->active_input &&
1044 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1045 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001046 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001047 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1048 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
1049 } else if (adev->primary_output) {
1050 out_device = adev->primary_output->devices;
1051 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001052 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001053 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001054 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001055 }
1056 }
1057
1058 if (out_snd_device == usecase->out_snd_device &&
1059 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001060 return 0;
1061 }
1062
Eric Laurent2bafff12016-03-17 12:17:23 -07001063 if (out_snd_device != SND_DEVICE_NONE &&
1064 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1065 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1066 __func__,
1067 use_case_table[uc_id],
1068 adev->last_logged_snd_device[uc_id][0],
1069 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1070 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1071 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1072 -1,
1073 out_snd_device,
1074 platform_get_snd_device_name(out_snd_device),
1075 platform_get_snd_device_acdb_id(out_snd_device));
1076 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1077 }
1078 if (in_snd_device != SND_DEVICE_NONE &&
1079 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1080 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1081 __func__,
1082 use_case_table[uc_id],
1083 adev->last_logged_snd_device[uc_id][1],
1084 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1085 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1086 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1087 -1,
1088 in_snd_device,
1089 platform_get_snd_device_name(in_snd_device),
1090 platform_get_snd_device_acdb_id(in_snd_device));
1091 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1092 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001093
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001094 /*
1095 * Limitation: While in call, to do a device switch we need to disable
1096 * and enable both RX and TX devices though one of them is same as current
1097 * device.
1098 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001099 if ((usecase->type == VOICE_CALL) &&
1100 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1101 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001102 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001103 /* Disable sidetone only if voice call already exists */
1104 if (voice_is_call_state_active(adev))
1105 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001106 }
1107
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001108 /* Disable current sound devices */
1109 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001110 disable_audio_route(adev, usecase);
1111 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001112 }
1113
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001114 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001115 disable_audio_route(adev, usecase);
1116 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001117 }
1118
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001119 /* Applicable only on the targets that has external modem.
1120 * New device information should be sent to modem before enabling
1121 * the devices to reduce in-call device switch time.
1122 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001123 if ((usecase->type == VOICE_CALL) &&
1124 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1125 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001126 status = platform_switch_voice_call_enable_device_config(adev->platform,
1127 out_snd_device,
1128 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001129 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001130
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001131 /* Enable new sound devices */
1132 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001133 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1134 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001135 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001136 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001137 }
1138
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001139 if (in_snd_device != SND_DEVICE_NONE) {
1140 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001141 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001142 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001143
Eric Laurentb23d5282013-05-14 15:27:20 -07001144 if (usecase->type == VOICE_CALL)
1145 status = platform_switch_voice_call_device_post(adev->platform,
1146 out_snd_device,
1147 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001148
sangwoo170731f2013-06-08 15:36:36 +09001149 usecase->in_snd_device = in_snd_device;
1150 usecase->out_snd_device = out_snd_device;
1151
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001152 audio_extn_tfa_98xx_set_mode();
1153
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001154 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001155
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001156 /* Applicable only on the targets that has external modem.
1157 * Enable device command should be sent to modem only after
1158 * enabling voice call mixer controls
1159 */
vivek mehta765eb642015-08-07 19:46:06 -07001160 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001161 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1162 out_snd_device,
1163 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001164 /* Enable sidetone only if voice call already exists */
1165 if (voice_is_call_state_active(adev))
1166 voice_set_sidetone(adev, out_snd_device, true);
1167 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001168
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001169 return status;
1170}
1171
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001172static int stop_input_stream(struct stream_in *in)
1173{
1174 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001175 struct audio_usecase *uc_info;
1176 struct audio_device *adev = in->dev;
1177
Eric Laurentc8400632013-02-14 19:04:54 -08001178 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001179
Eric Laurent994a6932013-07-17 11:51:42 -07001180 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001181 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001182 uc_info = get_usecase_from_list(adev, in->usecase);
1183 if (uc_info == NULL) {
1184 ALOGE("%s: Could not find the usecase (%d) in the list",
1185 __func__, in->usecase);
1186 return -EINVAL;
1187 }
1188
Eric Laurent150dbfe2013-02-27 14:31:02 -08001189 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001190 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001191
1192 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001193 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001194
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001195 list_remove(&uc_info->list);
1196 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001197
Eric Laurent994a6932013-07-17 11:51:42 -07001198 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001199 return ret;
1200}
1201
1202int start_input_stream(struct stream_in *in)
1203{
1204 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001205 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001206 struct audio_usecase *uc_info;
1207 struct audio_device *adev = in->dev;
1208
Eric Laurent994a6932013-07-17 11:51:42 -07001209 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001210
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001211 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1212 return -EIO;
1213
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001214 if (in->card_status == CARD_STATUS_OFFLINE ||
1215 adev->card_status == CARD_STATUS_OFFLINE) {
1216 ALOGW("in->card_status or adev->card_status offline, try again");
1217 ret = -EAGAIN;
1218 goto error_config;
1219 }
1220
Eric Laurentb23d5282013-05-14 15:27:20 -07001221 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001222 if (in->pcm_device_id < 0) {
1223 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1224 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001225 ret = -EINVAL;
1226 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001227 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001228
1229 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001230 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1231 uc_info->id = in->usecase;
1232 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001233 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001234 uc_info->devices = in->device;
1235 uc_info->in_snd_device = SND_DEVICE_NONE;
1236 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001237
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001238 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001239
1240 audio_extn_perf_lock_acquire();
1241
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001242 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001243
Eric Laurent0e46adf2016-12-16 12:49:24 -08001244 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001245 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001246 ALOGE("%s: pcm stream not ready", __func__);
1247 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001248 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001249 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001250 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001251 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1252 goto error_open;
1253 }
1254 } else {
1255 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1256 unsigned int pcm_open_retry_count = 0;
1257
1258 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1259 flags |= PCM_MMAP | PCM_NOIRQ;
1260 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1261 } else if (in->realtime) {
1262 flags |= PCM_MMAP | PCM_NOIRQ;
1263 }
1264
1265 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1266 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1267
1268 while (1) {
1269 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1270 flags, &in->config);
1271 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1272 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1273 if (in->pcm != NULL) {
1274 pcm_close(in->pcm);
1275 in->pcm = NULL;
1276 }
1277 if (pcm_open_retry_count-- == 0) {
1278 ret = -EIO;
1279 goto error_open;
1280 }
1281 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1282 continue;
1283 }
1284 break;
1285 }
1286
1287 ALOGV("%s: pcm_prepare", __func__);
1288 ret = pcm_prepare(in->pcm);
1289 if (ret < 0) {
1290 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001291 pcm_close(in->pcm);
1292 in->pcm = NULL;
1293 goto error_open;
1294 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001295 if (in->realtime) {
1296 ret = pcm_start(in->pcm);
1297 if (ret < 0) {
1298 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1299 pcm_close(in->pcm);
1300 in->pcm = NULL;
1301 goto error_open;
1302 }
1303 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001304 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001305 register_in_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001306 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001307 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001308
Eric Laurent0e46adf2016-12-16 12:49:24 -08001309 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001310
1311error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001312 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001313 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001314
1315error_config:
1316 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001317 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001318
1319 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001320}
1321
Eric Laurenta1478072015-09-21 17:21:52 -07001322void lock_input_stream(struct stream_in *in)
1323{
1324 pthread_mutex_lock(&in->pre_lock);
1325 pthread_mutex_lock(&in->lock);
1326 pthread_mutex_unlock(&in->pre_lock);
1327}
1328
1329void lock_output_stream(struct stream_out *out)
1330{
1331 pthread_mutex_lock(&out->pre_lock);
1332 pthread_mutex_lock(&out->lock);
1333 pthread_mutex_unlock(&out->pre_lock);
1334}
1335
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001336/* must be called with out->lock locked */
1337static int send_offload_cmd_l(struct stream_out* out, int command)
1338{
1339 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1340
1341 ALOGVV("%s %d", __func__, command);
1342
1343 cmd->cmd = command;
1344 list_add_tail(&out->offload_cmd_list, &cmd->node);
1345 pthread_cond_signal(&out->offload_cond);
1346 return 0;
1347}
1348
1349/* must be called iwth out->lock locked */
1350static void stop_compressed_output_l(struct stream_out *out)
1351{
1352 out->offload_state = OFFLOAD_STATE_IDLE;
1353 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001354 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001355 if (out->compr != NULL) {
1356 compress_stop(out->compr);
1357 while (out->offload_thread_blocked) {
1358 pthread_cond_wait(&out->cond, &out->lock);
1359 }
1360 }
1361}
1362
1363static void *offload_thread_loop(void *context)
1364{
1365 struct stream_out *out = (struct stream_out *) context;
1366 struct listnode *item;
1367
1368 out->offload_state = OFFLOAD_STATE_IDLE;
1369 out->playback_started = 0;
1370
1371 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1372 set_sched_policy(0, SP_FOREGROUND);
1373 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1374
1375 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001376 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001377 for (;;) {
1378 struct offload_cmd *cmd = NULL;
1379 stream_callback_event_t event;
1380 bool send_callback = false;
1381
1382 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1383 __func__, list_empty(&out->offload_cmd_list),
1384 out->offload_state);
1385 if (list_empty(&out->offload_cmd_list)) {
1386 ALOGV("%s SLEEPING", __func__);
1387 pthread_cond_wait(&out->offload_cond, &out->lock);
1388 ALOGV("%s RUNNING", __func__);
1389 continue;
1390 }
1391
1392 item = list_head(&out->offload_cmd_list);
1393 cmd = node_to_item(item, struct offload_cmd, node);
1394 list_remove(item);
1395
1396 ALOGVV("%s STATE %d CMD %d out->compr %p",
1397 __func__, out->offload_state, cmd->cmd, out->compr);
1398
1399 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1400 free(cmd);
1401 break;
1402 }
1403
1404 if (out->compr == NULL) {
1405 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001406 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001407 pthread_cond_signal(&out->cond);
1408 continue;
1409 }
1410 out->offload_thread_blocked = true;
1411 pthread_mutex_unlock(&out->lock);
1412 send_callback = false;
1413 switch(cmd->cmd) {
1414 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1415 compress_wait(out->compr, -1);
1416 send_callback = true;
1417 event = STREAM_CBK_EVENT_WRITE_READY;
1418 break;
1419 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001420 compress_next_track(out->compr);
1421 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001422 send_callback = true;
1423 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001424 /* Resend the metadata for next iteration */
1425 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001426 break;
1427 case OFFLOAD_CMD_DRAIN:
1428 compress_drain(out->compr);
1429 send_callback = true;
1430 event = STREAM_CBK_EVENT_DRAIN_READY;
1431 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001432 case OFFLOAD_CMD_ERROR:
1433 send_callback = true;
1434 event = STREAM_CBK_EVENT_ERROR;
1435 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001436 default:
1437 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1438 break;
1439 }
Eric Laurenta1478072015-09-21 17:21:52 -07001440 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001441 out->offload_thread_blocked = false;
1442 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001443 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001444 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001445 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001446 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001447 free(cmd);
1448 }
1449
1450 pthread_cond_signal(&out->cond);
1451 while (!list_empty(&out->offload_cmd_list)) {
1452 item = list_head(&out->offload_cmd_list);
1453 list_remove(item);
1454 free(node_to_item(item, struct offload_cmd, node));
1455 }
1456 pthread_mutex_unlock(&out->lock);
1457
1458 return NULL;
1459}
1460
1461static int create_offload_callback_thread(struct stream_out *out)
1462{
1463 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1464 list_init(&out->offload_cmd_list);
1465 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1466 offload_thread_loop, out);
1467 return 0;
1468}
1469
1470static int destroy_offload_callback_thread(struct stream_out *out)
1471{
Eric Laurenta1478072015-09-21 17:21:52 -07001472 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001473 stop_compressed_output_l(out);
1474 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1475
1476 pthread_mutex_unlock(&out->lock);
1477 pthread_join(out->offload_thread, (void **) NULL);
1478 pthread_cond_destroy(&out->offload_cond);
1479
1480 return 0;
1481}
1482
Eric Laurent07eeafd2013-10-06 12:52:49 -07001483static bool allow_hdmi_channel_config(struct audio_device *adev)
1484{
1485 struct listnode *node;
1486 struct audio_usecase *usecase;
1487 bool ret = true;
1488
1489 list_for_each(node, &adev->usecase_list) {
1490 usecase = node_to_item(node, struct audio_usecase, list);
1491 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1492 /*
1493 * If voice call is already existing, do not proceed further to avoid
1494 * disabling/enabling both RX and TX devices, CSD calls, etc.
1495 * Once the voice call done, the HDMI channels can be configured to
1496 * max channels of remaining use cases.
1497 */
1498 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001499 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001500 __func__);
1501 ret = false;
1502 break;
1503 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
Joe Onorato188b6222016-03-01 11:02:27 -08001504 ALOGV("%s: multi channel playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001505 "no change in HDMI channels", __func__);
1506 ret = false;
1507 break;
1508 }
1509 }
1510 }
1511 return ret;
1512}
1513
1514static int check_and_set_hdmi_channels(struct audio_device *adev,
1515 unsigned int channels)
1516{
1517 struct listnode *node;
1518 struct audio_usecase *usecase;
1519
1520 /* Check if change in HDMI channel config is allowed */
1521 if (!allow_hdmi_channel_config(adev))
1522 return 0;
1523
1524 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001525 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001526 return 0;
1527 }
1528
1529 platform_set_hdmi_channels(adev->platform, channels);
1530 adev->cur_hdmi_channels = channels;
1531
1532 /*
1533 * Deroute all the playback streams routed to HDMI so that
1534 * the back end is deactivated. Note that backend will not
1535 * be deactivated if any one stream is connected to it.
1536 */
1537 list_for_each(node, &adev->usecase_list) {
1538 usecase = node_to_item(node, struct audio_usecase, list);
1539 if (usecase->type == PCM_PLAYBACK &&
1540 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001541 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001542 }
1543 }
1544
1545 /*
1546 * Enable all the streams disabled above. Now the HDMI backend
1547 * will be activated with new channel configuration
1548 */
1549 list_for_each(node, &adev->usecase_list) {
1550 usecase = node_to_item(node, struct audio_usecase, list);
1551 if (usecase->type == PCM_PLAYBACK &&
1552 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001553 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001554 }
1555 }
1556
1557 return 0;
1558}
1559
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001560static int stop_output_stream(struct stream_out *out)
1561{
1562 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001563 struct audio_usecase *uc_info;
1564 struct audio_device *adev = out->dev;
1565
Eric Laurent994a6932013-07-17 11:51:42 -07001566 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001567 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001568 uc_info = get_usecase_from_list(adev, out->usecase);
1569 if (uc_info == NULL) {
1570 ALOGE("%s: Could not find the usecase (%d) in the list",
1571 __func__, out->usecase);
1572 return -EINVAL;
1573 }
1574
Haynes Mathew George41f86652014-06-17 14:22:15 -07001575 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1576 if (adev->visualizer_stop_output != NULL)
1577 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1578 if (adev->offload_effects_stop_output != NULL)
1579 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1580 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001581
Eric Laurent150dbfe2013-02-27 14:31:02 -08001582 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001583 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001584
1585 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001586 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001587
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001588 list_remove(&uc_info->list);
1589 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001590
Eric Laurent0499d4f2014-08-25 22:39:29 -05001591 audio_extn_extspk_update(adev->extspk);
1592
Eric Laurent07eeafd2013-10-06 12:52:49 -07001593 /* Must be called after removing the usecase from list */
1594 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1595 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1596
Eric Laurent994a6932013-07-17 11:51:42 -07001597 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001598 return ret;
1599}
1600
1601int start_output_stream(struct stream_out *out)
1602{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001603 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001604 struct audio_usecase *uc_info;
1605 struct audio_device *adev = out->dev;
1606
Eric Laurent994a6932013-07-17 11:51:42 -07001607 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001608 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001609
1610 if (out->card_status == CARD_STATUS_OFFLINE ||
1611 adev->card_status == CARD_STATUS_OFFLINE) {
1612 ALOGW("out->card_status or adev->card_status offline, try again");
1613 ret = -EAGAIN;
1614 goto error_config;
1615 }
1616
Eric Laurentb23d5282013-05-14 15:27:20 -07001617 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001618 if (out->pcm_device_id < 0) {
1619 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1620 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001621 ret = -EINVAL;
1622 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001623 }
1624
1625 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1626 uc_info->id = out->usecase;
1627 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001628 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001629 uc_info->devices = out->devices;
1630 uc_info->in_snd_device = SND_DEVICE_NONE;
1631 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001632
Eric Laurent07eeafd2013-10-06 12:52:49 -07001633 /* This must be called before adding this usecase to the list */
1634 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1635 check_and_set_hdmi_channels(adev, out->config.channels);
1636
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001637 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001638
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001639 audio_extn_perf_lock_acquire();
1640
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001641 select_devices(adev, out->usecase);
1642
Eric Laurent0499d4f2014-08-25 22:39:29 -05001643 audio_extn_extspk_update(adev->extspk);
1644
Andy Hung31aca912014-03-20 17:14:59 -07001645 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001646 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001647 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1648 out->pcm = NULL;
1649 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1650 COMPRESS_IN, &out->compr_config);
1651 if (out->compr && !is_compress_ready(out->compr)) {
1652 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1653 compress_close(out->compr);
1654 out->compr = NULL;
1655 ret = -EIO;
1656 goto error_open;
1657 }
1658 if (out->offload_callback)
1659 compress_nonblock(out->compr, out->non_blocking);
1660
1661 if (adev->visualizer_start_output != NULL)
1662 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1663 if (adev->offload_effects_start_output != NULL)
1664 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
1665 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001666 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001667 ALOGE("%s: pcm stream not ready", __func__);
1668 goto error_open;
1669 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001670 ret = pcm_start(out->pcm);
1671 if (ret < 0) {
1672 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1673 goto error_open;
1674 }
1675 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07001676 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001677 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001678
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001679 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1680 flags |= PCM_MMAP | PCM_NOIRQ;
1681 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001682 } else if (out->realtime) {
1683 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07001684 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001685
1686 while (1) {
1687 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1688 flags, &out->config);
1689 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1690 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1691 if (out->pcm != NULL) {
1692 pcm_close(out->pcm);
1693 out->pcm = NULL;
1694 }
1695 if (pcm_open_retry_count-- == 0) {
1696 ret = -EIO;
1697 goto error_open;
1698 }
1699 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1700 continue;
1701 }
1702 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001703 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001704 ALOGV("%s: pcm_prepare", __func__);
1705 if (pcm_is_ready(out->pcm)) {
1706 ret = pcm_prepare(out->pcm);
1707 if (ret < 0) {
1708 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1709 pcm_close(out->pcm);
1710 out->pcm = NULL;
1711 goto error_open;
1712 }
1713 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001714 if (out->realtime) {
1715 ret = pcm_start(out->pcm);
1716 if (ret < 0) {
1717 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1718 pcm_close(out->pcm);
1719 out->pcm = NULL;
1720 goto error_open;
1721 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001722 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001723 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001724 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001725 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001726 audio_extn_tfa_98xx_enable_speaker();
1727
Eric Laurent994a6932013-07-17 11:51:42 -07001728 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001729 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001730error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001731 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001732 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001733error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001734 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001735}
1736
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001737static int check_input_parameters(uint32_t sample_rate,
1738 audio_format_t format,
1739 int channel_count)
1740{
vivek mehta4ed66e62016-04-15 23:33:34 -07001741 if ((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT)) {
vivek mehtadae44712015-07-27 14:13:18 -07001742 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1743 return -EINVAL;
1744 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001745
vivek mehtadae44712015-07-27 14:13:18 -07001746 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > MAX_CHANNEL_COUNT)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001747 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
vivek mehtadae44712015-07-27 14:13:18 -07001748 channel_count, MIN_CHANNEL_COUNT, MAX_CHANNEL_COUNT);
1749 return -EINVAL;
1750 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001751
1752 switch (sample_rate) {
1753 case 8000:
1754 case 11025:
1755 case 12000:
1756 case 16000:
1757 case 22050:
1758 case 24000:
1759 case 32000:
1760 case 44100:
1761 case 48000:
1762 break;
1763 default:
vivek mehtadae44712015-07-27 14:13:18 -07001764 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001765 return -EINVAL;
1766 }
1767
1768 return 0;
1769}
1770
1771static size_t get_input_buffer_size(uint32_t sample_rate,
1772 audio_format_t format,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001773 int channel_count,
1774 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001775{
1776 size_t size = 0;
1777
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001778 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1779 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001780
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001781 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001782 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001783 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07001784
1785 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001786
Glenn Kasten4f993392014-05-14 07:30:48 -07001787 /* make sure the size is multiple of 32 bytes
1788 * At 48 kHz mono 16-bit PCM:
1789 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1790 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1791 */
1792 size += 0x1f;
1793 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001794
1795 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001796}
1797
1798static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1799{
1800 struct stream_out *out = (struct stream_out *)stream;
1801
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001802 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001803}
1804
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001805static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001806{
1807 return -ENOSYS;
1808}
1809
1810static size_t out_get_buffer_size(const struct audio_stream *stream)
1811{
1812 struct stream_out *out = (struct stream_out *)stream;
1813
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001814 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1815 return out->compr_config.fragment_size;
1816 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001817 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07001818 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001819}
1820
1821static uint32_t out_get_channels(const struct audio_stream *stream)
1822{
1823 struct stream_out *out = (struct stream_out *)stream;
1824
1825 return out->channel_mask;
1826}
1827
1828static audio_format_t out_get_format(const struct audio_stream *stream)
1829{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001830 struct stream_out *out = (struct stream_out *)stream;
1831
1832 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001833}
1834
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001835static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001836{
1837 return -ENOSYS;
1838}
1839
1840static int out_standby(struct audio_stream *stream)
1841{
1842 struct stream_out *out = (struct stream_out *)stream;
1843 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08001844 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001845
Eric Laurent994a6932013-07-17 11:51:42 -07001846 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001847 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001848
Eric Laurenta1478072015-09-21 17:21:52 -07001849 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001850 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001851 if (adev->adm_deregister_stream)
1852 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001853 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001854 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001855 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1856 if (out->pcm) {
1857 pcm_close(out->pcm);
1858 out->pcm = NULL;
1859 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001860 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001861 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08001862 out->playback_started = false;
1863 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001864 } else {
1865 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001866 out->gapless_mdata.encoder_delay = 0;
1867 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001868 if (out->compr != NULL) {
1869 compress_close(out->compr);
1870 out->compr = NULL;
1871 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001872 }
Phil Burkbc991042017-02-24 08:06:44 -08001873 if (do_stop) {
1874 stop_output_stream(out);
1875 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001876 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001877 }
1878 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001879 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001880 return 0;
1881}
1882
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001883static int out_on_error(struct audio_stream *stream)
1884{
1885 struct stream_out *out = (struct stream_out *)stream;
1886 struct audio_device *adev = out->dev;
1887 bool do_standby = false;
1888
1889 lock_output_stream(out);
1890 if (!out->standby) {
1891 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1892 stop_compressed_output_l(out);
1893 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
1894 } else
1895 do_standby = true;
1896 }
1897 pthread_mutex_unlock(&out->lock);
1898
1899 if (do_standby)
1900 return out_standby(&out->stream.common);
1901
1902 return 0;
1903}
1904
Andy Hung7401c7c2016-09-21 12:41:21 -07001905static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001906{
Andy Hung7401c7c2016-09-21 12:41:21 -07001907 struct stream_out *out = (struct stream_out *)stream;
1908
1909 // We try to get the lock for consistency,
1910 // but it isn't necessary for these variables.
1911 // If we're not in standby, we may be blocked on a write.
1912 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
1913 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
1914 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
1915
1916 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07001917 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07001918 }
Andy Hunga452b0a2017-03-15 14:51:15 -07001919
1920 // dump error info
1921 (void)error_log_dump(
1922 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hungfc044e12017-03-20 09:24:22 -07001923 // dump power info (out->power_log may be null)
Andy Hung62c9b882017-03-22 16:43:42 -07001924 (void)power_log_dump(
1925 out->power_log, fd, " " /* prefix */, POWER_LOG_LINES, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001926 return 0;
1927}
1928
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001929static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1930{
1931 int ret = 0;
1932 char value[32];
1933 struct compr_gapless_mdata tmp_mdata;
1934
1935 if (!out || !parms) {
1936 return -EINVAL;
1937 }
1938
1939 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1940 if (ret >= 0) {
1941 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
1942 } else {
1943 return -EINVAL;
1944 }
1945
1946 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1947 if (ret >= 0) {
1948 tmp_mdata.encoder_padding = atoi(value);
1949 } else {
1950 return -EINVAL;
1951 }
1952
1953 out->gapless_mdata = tmp_mdata;
1954 out->send_new_metadata = 1;
1955 ALOGV("%s new encoder delay %u and padding %u", __func__,
1956 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1957
1958 return 0;
1959}
1960
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001961static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1962{
1963 return out == adev->primary_output || out == adev->voice_tx_output;
1964}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001965
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001966static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1967{
1968 struct stream_out *out = (struct stream_out *)stream;
1969 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001970 struct audio_usecase *usecase;
1971 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001972 struct str_parms *parms;
1973 char value[32];
1974 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001975 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07001976 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001977
Eric Laurent2e140aa2016-06-30 17:14:46 -07001978 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001979 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001980 parms = str_parms_create_str(kvpairs);
1981 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1982 if (ret >= 0) {
1983 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07001984 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001985 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001986
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001987 /*
1988 * When HDMI cable is unplugged the music playback is paused and
1989 * the policy manager sends routing=0. But the audioflinger
1990 * continues to write data until standby time (3sec).
1991 * As the HDMI core is turned off, the write gets blocked.
1992 * Avoid this by routing audio to speaker until standby.
1993 */
1994 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
1995 val == AUDIO_DEVICE_NONE) {
1996 val = AUDIO_DEVICE_OUT_SPEAKER;
1997 }
1998
1999 /*
2000 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002001 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002002 * the select_devices(). But how do we undo this?
2003 *
2004 * For example, music playback is active on headset (deep-buffer usecase)
2005 * and if we go to ringtones and select a ringtone, low-latency usecase
2006 * will be started on headset+speaker. As we can't enable headset+speaker
2007 * and headset devices at the same time, select_devices() switches the music
2008 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2009 * So when the ringtone playback is completed, how do we undo the same?
2010 *
2011 * We are relying on the out_set_parameters() call on deep-buffer output,
2012 * once the ringtone playback is ended.
2013 * NOTE: We should not check if the current devices are same as new devices.
2014 * Because select_devices() must be called to switch back the music
2015 * playback to headset.
2016 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002017 audio_devices_t new_dev = val;
2018 if (new_dev != AUDIO_DEVICE_NONE) {
2019 bool same_dev = out->devices == new_dev;
2020 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002021
Eric Laurenta7657192014-10-09 21:09:33 -07002022 if (output_drives_call(adev, out)) {
2023 if (!voice_is_in_call(adev)) {
2024 if (adev->mode == AUDIO_MODE_IN_CALL) {
2025 adev->current_call_output = out;
2026 ret = voice_start_call(adev);
2027 }
2028 } else {
2029 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002030 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002031 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002032 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002033
2034 if (!out->standby) {
2035 if (!same_dev) {
2036 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002037 // inform adm before actual routing to prevent glitches.
2038 if (adev->adm_on_routing_change) {
2039 adev->adm_on_routing_change(adev->adm_data,
2040 out->handle);
2041 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002042 }
2043 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002044 audio_extn_tfa_98xx_update();
vivek mehta0d3637a2016-07-24 09:32:02 -07002045 }
2046
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002047 }
2048
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002049 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002050 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002051
2052 /*handles device and call state changes*/
2053 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002054 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002055
2056 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2057 parse_compress_metadata(out, parms);
2058 }
2059
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002060 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002061 ALOGV("%s: exit: code(%d)", __func__, status);
2062 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002063}
2064
2065static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2066{
2067 struct stream_out *out = (struct stream_out *)stream;
2068 struct str_parms *query = str_parms_create_str(keys);
2069 char *str;
2070 char value[256];
2071 struct str_parms *reply = str_parms_create();
2072 size_t i, j;
2073 int ret;
2074 bool first = true;
Eric Laurent994a6932013-07-17 11:51:42 -07002075 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002076 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2077 if (ret >= 0) {
2078 value[0] = '\0';
2079 i = 0;
2080 while (out->supported_channel_masks[i] != 0) {
2081 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2082 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2083 if (!first) {
2084 strcat(value, "|");
2085 }
2086 strcat(value, out_channels_name_to_enum_table[j].name);
2087 first = false;
2088 break;
2089 }
2090 }
2091 i++;
2092 }
2093 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2094 str = str_parms_to_str(reply);
2095 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002096 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002097 }
2098 str_parms_destroy(query);
2099 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002100 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002101 return str;
2102}
2103
2104static uint32_t out_get_latency(const struct audio_stream_out *stream)
2105{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002106 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002107 struct stream_out *out = (struct stream_out *)stream;
2108
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002109 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2110 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002111 else if ((out->realtime) ||
2112 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002113 // since the buffer won't be filled up faster than realtime,
2114 // return a smaller number
2115 period_ms = (out->af_period_multiplier * out->config.period_size *
2116 1000) / (out->config.rate);
2117 hw_delay = platform_render_latency(out->usecase)/1000;
2118 return period_ms + hw_delay;
2119 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002120
2121 return (out->config.period_count * out->config.period_size * 1000) /
2122 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002123}
2124
2125static int out_set_volume(struct audio_stream_out *stream, float left,
2126 float right)
2127{
Eric Laurenta9024de2013-04-04 09:19:12 -07002128 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002129 int volume[2];
2130
Eric Laurenta9024de2013-04-04 09:19:12 -07002131 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2132 /* only take left channel into account: the API is for stereo anyway */
2133 out->muted = (left == 0.0f);
2134 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002135 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2136 const char *mixer_ctl_name = "Compress Playback Volume";
2137 struct audio_device *adev = out->dev;
2138 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002139 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2140 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002141 /* try with the control based on device id */
2142 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2143 PCM_PLAYBACK);
2144 char ctl_name[128] = {0};
2145 snprintf(ctl_name, sizeof(ctl_name),
2146 "Compress Playback %d Volume", pcm_device_id);
2147 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2148 if (!ctl) {
2149 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2150 return -EINVAL;
2151 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002152 }
2153 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2154 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2155 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2156 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002157 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002158
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002159 return -ENOSYS;
2160}
2161
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002162// note: this call is safe only if the stream_cb is
2163// removed first in close_output_stream (as is done now).
2164static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2165{
2166 if (!stream || !parms)
2167 return;
2168
2169 struct stream_out *out = (struct stream_out *)stream;
2170 struct audio_device *adev = out->dev;
2171
2172 card_status_t status;
2173 int card;
2174 if (parse_snd_card_status(parms, &card, &status) < 0)
2175 return;
2176
2177 pthread_mutex_lock(&adev->lock);
2178 bool valid_cb = (card == adev->snd_card);
2179 pthread_mutex_unlock(&adev->lock);
2180
2181 if (!valid_cb)
2182 return;
2183
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002184 lock_output_stream(out);
2185 if (out->card_status != status)
2186 out->card_status = status;
2187 pthread_mutex_unlock(&out->lock);
2188
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002189 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2190 use_case_table[out->usecase],
2191 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2192
2193 if (status == CARD_STATUS_OFFLINE)
2194 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002195
2196 return;
2197}
2198
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002199#ifdef NO_AUDIO_OUT
2200static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002201 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002202{
2203 struct stream_out *out = (struct stream_out *)stream;
2204
2205 /* No Output device supported other than BT for playback.
2206 * Sleep for the amount of buffer duration
2207 */
Eric Laurenta1478072015-09-21 17:21:52 -07002208 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002209 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2210 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002211 out_get_sample_rate(&out->stream.common));
2212 pthread_mutex_unlock(&out->lock);
2213 return bytes;
2214}
2215#endif
2216
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002217static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2218 size_t bytes)
2219{
2220 struct stream_out *out = (struct stream_out *)stream;
2221 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002222 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002223 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002224
Eric Laurenta1478072015-09-21 17:21:52 -07002225 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002226 // this is always nonzero
2227 const int frame_size = audio_stream_out_frame_size(stream);
2228
Eric Laurent0e46adf2016-12-16 12:49:24 -08002229 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2230 error_code = ERROR_CODE_WRITE;
2231 goto exit;
2232 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002233 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002234 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002235 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002236 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002237 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002238 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002239 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002240 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002241 goto exit;
2242 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002243
2244 if (last_known_cal_step != -1) {
2245 ALOGD("%s: retry previous failed cal level set", __func__);
2246 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2247 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002248 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002249
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002250 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002251 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002252 if (out->send_new_metadata) {
2253 ALOGVV("send new gapless metadata");
2254 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2255 out->send_new_metadata = 0;
2256 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002257 unsigned int avail;
2258 struct timespec tstamp;
2259 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2260 /* Do not limit write size if the available frames count is unknown */
2261 if (ret != 0) {
2262 avail = bytes;
2263 }
2264 if (avail == 0) {
2265 ret = 0;
2266 } else {
2267 if (avail > bytes) {
2268 avail = bytes;
2269 }
2270 ret = compress_write(out->compr, buffer, avail);
2271 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2272 __func__, avail, ret);
2273 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002274
Eric Laurent6e895242013-09-05 16:10:57 -07002275 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002276 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2277 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002278 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002279 compress_start(out->compr);
2280 out->playback_started = 1;
2281 out->offload_state = OFFLOAD_STATE_PLAYING;
2282 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002283 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002284 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002285 } else {
2286 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002287 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002288 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002289 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002290 return ret;
2291 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002292 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002293 if (out->pcm) {
2294 if (out->muted)
2295 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002296
Eric Laurent0e46adf2016-12-16 12:49:24 -08002297 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002298
Haynes Mathew George03c40102016-01-29 17:57:48 -08002299 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2300 out->config.rate;
2301 request_out_focus(out, ns);
2302
2303 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2304 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002305 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002306 else
2307 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002308
Haynes Mathew George03c40102016-01-29 17:57:48 -08002309 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002310 } else {
2311 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002312 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002313 }
2314
2315exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002316 // For PCM we always consume the buffer and return #bytes regardless of ret.
2317 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2318 out->written += bytes / (out->config.channels * sizeof(short));
2319 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002320 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07002321
2322 // only get time if needed for logging, as it is a system call on 32 bit devices.
2323 // TODO: Consider always enabling for 64 bit vDSO using compile time check on __LP64__.
2324 const int64_t now_ns = out->power_log != 0 || (ret != 0 && out->error_log != 0)
2325 ? audio_utils_get_real_time_ns() : 0;
Andy Hungfc044e12017-03-20 09:24:22 -07002326
Andy Hung7401c7c2016-09-21 12:41:21 -07002327 if (ret != 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002328 error_log_log(out->error_log, error_code, now_ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002329 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2330 ALOGE_IF(out->pcm != NULL,
2331 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hungfc044e12017-03-20 09:24:22 -07002332 sleeptime_us = bytes * 1000000LL / frame_size /
Andy Hung7401c7c2016-09-21 12:41:21 -07002333 out_get_sample_rate(&out->stream.common);
2334 // usleep not guaranteed for values over 1 second but we don't limit here.
2335 }
2336 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002337
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002338 pthread_mutex_unlock(&out->lock);
2339
2340 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002341 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002342 if (sleeptime_us != 0)
2343 usleep(sleeptime_us);
Andy Hungfc044e12017-03-20 09:24:22 -07002344 } else {
2345 // only log if the data is properly written (out->power_log may be null)
2346 power_log_log(out->power_log, buffer, bytes / frame_size, now_ns);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002347 }
2348 return bytes;
2349}
2350
2351static int out_get_render_position(const struct audio_stream_out *stream,
2352 uint32_t *dsp_frames)
2353{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002354 struct stream_out *out = (struct stream_out *)stream;
2355 *dsp_frames = 0;
2356 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002357 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002358 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002359 unsigned long frames = 0;
2360 // TODO: check return value
2361 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2362 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002363 ALOGVV("%s rendered frames %d sample_rate %d",
2364 __func__, *dsp_frames, out->sample_rate);
2365 }
2366 pthread_mutex_unlock(&out->lock);
2367 return 0;
2368 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002369 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002370}
2371
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002372static int out_add_audio_effect(const struct audio_stream *stream __unused,
2373 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002374{
2375 return 0;
2376}
2377
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002378static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2379 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002380{
2381 return 0;
2382}
2383
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002384static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2385 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002386{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002387 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002388}
2389
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002390static int out_get_presentation_position(const struct audio_stream_out *stream,
2391 uint64_t *frames, struct timespec *timestamp)
2392{
2393 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002394 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07002395 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002396
Eric Laurenta1478072015-09-21 17:21:52 -07002397 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002398
Eric Laurent949a0892013-09-20 09:20:13 -07002399 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2400 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002401 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002402 compress_get_tstamp(out->compr, &dsp_frames,
2403 &out->sample_rate);
2404 ALOGVV("%s rendered frames %ld sample_rate %d",
2405 __func__, dsp_frames, out->sample_rate);
2406 *frames = dsp_frames;
2407 ret = 0;
2408 /* this is the best we can do */
2409 clock_gettime(CLOCK_MONOTONIC, timestamp);
2410 }
2411 } else {
2412 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002413 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002414 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2415 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002416 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002417 // This adjustment accounts for buffering after app processor.
2418 // It is based on estimated DSP latency per use case, rather than exact.
2419 signed_frames -=
2420 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2421
Eric Laurent949a0892013-09-20 09:20:13 -07002422 // It would be unusual for this value to be negative, but check just in case ...
2423 if (signed_frames >= 0) {
2424 *frames = signed_frames;
2425 ret = 0;
2426 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002427 }
2428 }
2429 }
2430
2431 pthread_mutex_unlock(&out->lock);
2432
2433 return ret;
2434}
2435
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002436static int out_set_callback(struct audio_stream_out *stream,
2437 stream_callback_t callback, void *cookie)
2438{
2439 struct stream_out *out = (struct stream_out *)stream;
2440
2441 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002442 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002443 out->offload_callback = callback;
2444 out->offload_cookie = cookie;
2445 pthread_mutex_unlock(&out->lock);
2446 return 0;
2447}
2448
2449static int out_pause(struct audio_stream_out* stream)
2450{
2451 struct stream_out *out = (struct stream_out *)stream;
2452 int status = -ENOSYS;
2453 ALOGV("%s", __func__);
2454 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002455 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002456 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2457 status = compress_pause(out->compr);
2458 out->offload_state = OFFLOAD_STATE_PAUSED;
2459 }
2460 pthread_mutex_unlock(&out->lock);
2461 }
2462 return status;
2463}
2464
2465static int out_resume(struct audio_stream_out* stream)
2466{
2467 struct stream_out *out = (struct stream_out *)stream;
2468 int status = -ENOSYS;
2469 ALOGV("%s", __func__);
2470 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2471 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002472 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002473 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2474 status = compress_resume(out->compr);
2475 out->offload_state = OFFLOAD_STATE_PLAYING;
2476 }
2477 pthread_mutex_unlock(&out->lock);
2478 }
2479 return status;
2480}
2481
2482static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2483{
2484 struct stream_out *out = (struct stream_out *)stream;
2485 int status = -ENOSYS;
2486 ALOGV("%s", __func__);
2487 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002488 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002489 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2490 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2491 else
2492 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2493 pthread_mutex_unlock(&out->lock);
2494 }
2495 return status;
2496}
2497
2498static int out_flush(struct audio_stream_out* stream)
2499{
2500 struct stream_out *out = (struct stream_out *)stream;
2501 ALOGV("%s", __func__);
2502 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002503 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002504 stop_compressed_output_l(out);
2505 pthread_mutex_unlock(&out->lock);
2506 return 0;
2507 }
2508 return -ENOSYS;
2509}
2510
Eric Laurent0e46adf2016-12-16 12:49:24 -08002511static int out_stop(const struct audio_stream_out* stream)
2512{
2513 struct stream_out *out = (struct stream_out *)stream;
2514 struct audio_device *adev = out->dev;
2515 int ret = -ENOSYS;
2516
2517 ALOGV("%s", __func__);
2518 pthread_mutex_lock(&adev->lock);
2519 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2520 out->playback_started && out->pcm != NULL) {
2521 pcm_stop(out->pcm);
2522 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08002523 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002524 }
2525 pthread_mutex_unlock(&adev->lock);
2526 return ret;
2527}
2528
2529static int out_start(const struct audio_stream_out* stream)
2530{
2531 struct stream_out *out = (struct stream_out *)stream;
2532 struct audio_device *adev = out->dev;
2533 int ret = -ENOSYS;
2534
2535 ALOGV("%s", __func__);
2536 pthread_mutex_lock(&adev->lock);
2537 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2538 !out->playback_started && out->pcm != NULL) {
2539 ret = start_output_stream(out);
2540 if (ret == 0) {
2541 out->playback_started = true;
2542 }
2543 }
2544 pthread_mutex_unlock(&adev->lock);
2545 return ret;
2546}
2547
Phil Burkbc991042017-02-24 08:06:44 -08002548/*
2549 * Modify config->period_count based on min_size_frames
2550 */
2551static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
2552{
2553 int periodCountRequested = (min_size_frames + config->period_size - 1)
2554 / config->period_size;
2555 int periodCount = MMAP_PERIOD_COUNT_MIN;
2556
2557 ALOGV("%s original config.period_size = %d config.period_count = %d",
2558 __func__, config->period_size, config->period_count);
2559
2560 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
2561 periodCount *= 2;
2562 }
2563 config->period_count = periodCount;
2564
2565 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
2566}
2567
Eric Laurent0e46adf2016-12-16 12:49:24 -08002568static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2569 int32_t min_size_frames,
2570 struct audio_mmap_buffer_info *info)
2571{
2572 struct stream_out *out = (struct stream_out *)stream;
2573 struct audio_device *adev = out->dev;
2574 int ret = 0;
2575 unsigned int offset1;
2576 unsigned int frames1;
2577 const char *step = "";
2578
2579 ALOGV("%s", __func__);
2580 pthread_mutex_lock(&adev->lock);
2581
2582 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002583 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002584 ret = -EINVAL;
2585 goto exit;
2586 }
2587 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08002588 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002589 ret = -ENOSYS;
2590 goto exit;
2591 }
2592 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
2593 if (out->pcm_device_id < 0) {
2594 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2595 __func__, out->pcm_device_id, out->usecase);
2596 ret = -EINVAL;
2597 goto exit;
2598 }
Phil Burkbc991042017-02-24 08:06:44 -08002599
2600 adjust_mmap_period_count(&out->config, min_size_frames);
2601
Eric Laurent0e46adf2016-12-16 12:49:24 -08002602 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2603 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
2604 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2605 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
2606 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2607 step = "open";
2608 ret = -ENODEV;
2609 goto exit;
2610 }
2611 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
2612 if (ret < 0) {
2613 step = "begin";
2614 goto exit;
2615 }
2616 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
2617 info->burst_size_frames = out->config.period_size;
2618 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
2619
2620 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
2621 info->buffer_size_frames));
2622
2623 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
2624 if (ret < 0) {
2625 step = "commit";
2626 goto exit;
2627 }
Phil Burkbc991042017-02-24 08:06:44 -08002628
2629 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002630 ret = 0;
2631
2632 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
2633 __func__, info->shared_memory_address, info->buffer_size_frames);
2634
2635exit:
2636 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002637 if (out->pcm == NULL) {
2638 ALOGE("%s: %s - %d", __func__, step, ret);
2639 } else {
2640 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08002641 pcm_close(out->pcm);
2642 out->pcm = NULL;
2643 }
2644 }
2645 pthread_mutex_unlock(&adev->lock);
2646 return ret;
2647}
2648
2649static int out_get_mmap_position(const struct audio_stream_out *stream,
2650 struct audio_mmap_position *position)
2651{
2652 struct stream_out *out = (struct stream_out *)stream;
2653 ALOGVV("%s", __func__);
2654 if (position == NULL) {
2655 return -EINVAL;
2656 }
2657 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
2658 return -ENOSYS;
2659 }
2660 if (out->pcm == NULL) {
2661 return -ENOSYS;
2662 }
2663
2664 struct timespec ts = { 0, 0 };
2665 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
2666 if (ret < 0) {
2667 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2668 return ret;
2669 }
Andy Hungfc044e12017-03-20 09:24:22 -07002670 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002671 return 0;
2672}
2673
2674
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002675/** audio_stream_in implementation **/
2676static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2677{
2678 struct stream_in *in = (struct stream_in *)stream;
2679
2680 return in->config.rate;
2681}
2682
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002683static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002684{
2685 return -ENOSYS;
2686}
2687
2688static size_t in_get_buffer_size(const struct audio_stream *stream)
2689{
2690 struct stream_in *in = (struct stream_in *)stream;
2691
Haynes Mathew George03c40102016-01-29 17:57:48 -08002692 return in->config.period_size * in->af_period_multiplier *
2693 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002694}
2695
2696static uint32_t in_get_channels(const struct audio_stream *stream)
2697{
2698 struct stream_in *in = (struct stream_in *)stream;
2699
2700 return in->channel_mask;
2701}
2702
vivek mehta4ed66e62016-04-15 23:33:34 -07002703static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002704{
vivek mehta4ed66e62016-04-15 23:33:34 -07002705 struct stream_in *in = (struct stream_in *)stream;
2706 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002707}
2708
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002709static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002710{
2711 return -ENOSYS;
2712}
2713
2714static int in_standby(struct audio_stream *stream)
2715{
2716 struct stream_in *in = (struct stream_in *)stream;
2717 struct audio_device *adev = in->dev;
2718 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08002719 bool do_stop = true;
2720
Eric Laurent994a6932013-07-17 11:51:42 -07002721 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002722
2723 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002724
2725 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08002726 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002727 audio_extn_sound_trigger_stop_lab(in);
2728 in->standby = true;
2729 }
2730
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002731 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002732 if (adev->adm_deregister_stream)
2733 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2734
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002735 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002736 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002737 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002738 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002739 in->capture_started = false;
2740 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002741 if (in->pcm) {
2742 pcm_close(in->pcm);
2743 in->pcm = NULL;
2744 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002745 adev->enable_voicerx = false;
2746 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08002747 if (do_stop) {
2748 status = stop_input_stream(in);
2749 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002750 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002751 }
2752 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002753 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002754 return status;
2755}
2756
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002757static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002758{
2759 return 0;
2760}
2761
2762static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2763{
2764 struct stream_in *in = (struct stream_in *)stream;
2765 struct audio_device *adev = in->dev;
2766 struct str_parms *parms;
2767 char *str;
2768 char value[32];
2769 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07002770 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002771
Eric Laurent994a6932013-07-17 11:51:42 -07002772 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002773 parms = str_parms_create_str(kvpairs);
2774
2775 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2776
Eric Laurenta1478072015-09-21 17:21:52 -07002777 lock_input_stream(in);
2778
Eric Laurent150dbfe2013-02-27 14:31:02 -08002779 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002780 if (ret >= 0) {
2781 val = atoi(value);
2782 /* no audio source uses val == 0 */
2783 if ((in->source != val) && (val != 0)) {
2784 in->source = val;
2785 }
2786 }
2787
2788 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07002789
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002790 if (ret >= 0) {
2791 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002792 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002793 in->device = val;
2794 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002795 if (!in->standby) {
2796 ALOGV("update input routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002797 // inform adm before actual routing to prevent glitches.
2798 if (adev->adm_on_routing_change) {
2799 adev->adm_on_routing_change(adev->adm_data,
2800 in->capture_handle);
2801 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002802 select_devices(adev, in->usecase);
2803 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002804 }
2805 }
2806
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002807 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002808 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002809
2810 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002811 ALOGV("%s: exit: status(%d)", __func__, status);
2812 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002813}
2814
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002815static char* in_get_parameters(const struct audio_stream *stream __unused,
2816 const char *keys __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002817{
2818 return strdup("");
2819}
2820
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002821static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002822{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002823 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002824}
2825
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002826static void in_snd_mon_cb(void * stream, struct str_parms * parms)
2827{
2828 if (!stream || !parms)
2829 return;
2830
2831 struct stream_in *in = (struct stream_in *)stream;
2832 struct audio_device *adev = in->dev;
2833
2834 card_status_t status;
2835 int card;
2836 if (parse_snd_card_status(parms, &card, &status) < 0)
2837 return;
2838
2839 pthread_mutex_lock(&adev->lock);
2840 bool valid_cb = (card == adev->snd_card);
2841 pthread_mutex_unlock(&adev->lock);
2842
2843 if (!valid_cb)
2844 return;
2845
2846 lock_input_stream(in);
2847 if (in->card_status != status)
2848 in->card_status = status;
2849 pthread_mutex_unlock(&in->lock);
2850
2851 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
2852 use_case_table[in->usecase],
2853 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2854
2855 // a better solution would be to report error back to AF and let
2856 // it put the stream to standby
2857 if (status == CARD_STATUS_OFFLINE)
2858 in_standby(&in->stream.common);
2859
2860 return;
2861}
2862
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002863static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2864 size_t bytes)
2865{
2866 struct stream_in *in = (struct stream_in *)stream;
2867 struct audio_device *adev = in->dev;
2868 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07002869 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002870
Eric Laurenta1478072015-09-21 17:21:52 -07002871 lock_input_stream(in);
2872
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002873 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002874 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002875 /* Read from sound trigger HAL */
2876 audio_extn_sound_trigger_read(in, buffer, bytes);
2877 pthread_mutex_unlock(&in->lock);
2878 return bytes;
2879 }
2880
Eric Laurent0e46adf2016-12-16 12:49:24 -08002881 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
2882 ret = -ENOSYS;
2883 goto exit;
2884 }
2885
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002886 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002887 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002888 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002889 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002890 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002891 goto exit;
2892 }
2893 in->standby = 0;
2894 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002895
Haynes Mathew George03c40102016-01-29 17:57:48 -08002896 //what's the duration requested by the client?
2897 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
2898 in->config.rate;
2899 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002900
Haynes Mathew George03c40102016-01-29 17:57:48 -08002901 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002902 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002903 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002904 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07002905 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002906 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002907 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002908 if (ret < 0) {
2909 ALOGE("Failed to read w/err %s", strerror(errno));
2910 ret = -errno;
2911 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002912 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
2913 if (bytes % 4 == 0) {
2914 /* data from DSP comes in 24_8 format, convert it to 8_24 */
2915 int_buf_stream = buffer;
2916 for (size_t itt=0; itt < bytes/4 ; itt++) {
2917 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07002918 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002919 } else {
2920 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
2921 ret = -EINVAL;
2922 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07002923 }
2924 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002925 }
2926
Haynes Mathew George03c40102016-01-29 17:57:48 -08002927 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002928
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002929 /*
2930 * Instead of writing zeroes here, we could trust the hardware
2931 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002932 * 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 -08002933 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002934 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002935 memset(buffer, 0, bytes);
2936
2937exit:
2938 pthread_mutex_unlock(&in->lock);
2939
2940 if (ret != 0) {
2941 in_standby(&in->stream.common);
2942 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Eric Laurentfdf296a2014-07-03 16:41:51 -07002943 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002944 in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08002945 memset(buffer, 0, bytes); // clear return data
2946 }
2947 if (bytes > 0) {
Andy Hung6ebe5962016-01-15 17:46:57 -08002948 in->frames_read += bytes / audio_stream_in_frame_size(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002949 }
2950 return bytes;
2951}
2952
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002953static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002954{
2955 return 0;
2956}
2957
Andy Hung6ebe5962016-01-15 17:46:57 -08002958static int in_get_capture_position(const struct audio_stream_in *stream,
2959 int64_t *frames, int64_t *time)
2960{
2961 if (stream == NULL || frames == NULL || time == NULL) {
2962 return -EINVAL;
2963 }
2964 struct stream_in *in = (struct stream_in *)stream;
2965 int ret = -ENOSYS;
2966
2967 lock_input_stream(in);
2968 if (in->pcm) {
2969 struct timespec timestamp;
2970 unsigned int avail;
2971 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
2972 *frames = in->frames_read + avail;
2973 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
2974 ret = 0;
2975 }
2976 }
2977 pthread_mutex_unlock(&in->lock);
2978 return ret;
2979}
2980
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002981static int add_remove_audio_effect(const struct audio_stream *stream,
2982 effect_handle_t effect,
2983 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002984{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002985 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002986 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002987 int status = 0;
2988 effect_descriptor_t desc;
2989
2990 status = (*effect)->get_descriptor(effect, &desc);
2991 if (status != 0)
2992 return status;
2993
Eric Laurenta1478072015-09-21 17:21:52 -07002994 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002995 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07002996 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07002997 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07002998 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002999 in->enable_aec != enable &&
3000 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3001 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003002 if (!enable)
3003 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003004 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3005 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3006 adev->enable_voicerx = enable;
3007 struct audio_usecase *usecase;
3008 struct listnode *node;
3009 list_for_each(node, &adev->usecase_list) {
3010 usecase = node_to_item(node, struct audio_usecase, list);
3011 if (usecase->type == PCM_PLAYBACK) {
3012 select_devices(adev, usecase->id);
3013 break;
3014 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003015 }
3016 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003017 if (!in->standby)
3018 select_devices(in->dev, in->usecase);
3019 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003020 if (in->enable_ns != enable &&
3021 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3022 in->enable_ns = enable;
3023 if (!in->standby)
3024 select_devices(in->dev, in->usecase);
3025 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003026 pthread_mutex_unlock(&in->dev->lock);
3027 pthread_mutex_unlock(&in->lock);
3028
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003029 return 0;
3030}
3031
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003032static int in_add_audio_effect(const struct audio_stream *stream,
3033 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003034{
Eric Laurent994a6932013-07-17 11:51:42 -07003035 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003036 return add_remove_audio_effect(stream, effect, true);
3037}
3038
3039static int in_remove_audio_effect(const struct audio_stream *stream,
3040 effect_handle_t effect)
3041{
Eric Laurent994a6932013-07-17 11:51:42 -07003042 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003043 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003044}
3045
Eric Laurent0e46adf2016-12-16 12:49:24 -08003046static int in_stop(const struct audio_stream_in* stream)
3047{
3048 struct stream_in *in = (struct stream_in *)stream;
3049 struct audio_device *adev = in->dev;
3050
3051 int ret = -ENOSYS;
3052 ALOGV("%s", __func__);
3053 pthread_mutex_lock(&adev->lock);
3054 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3055 in->capture_started && in->pcm != NULL) {
3056 pcm_stop(in->pcm);
3057 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003058 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003059 }
3060 pthread_mutex_unlock(&adev->lock);
3061 return ret;
3062}
3063
3064static int in_start(const struct audio_stream_in* stream)
3065{
3066 struct stream_in *in = (struct stream_in *)stream;
3067 struct audio_device *adev = in->dev;
3068 int ret = -ENOSYS;
3069
3070 ALOGV("%s in %p", __func__, in);
3071 pthread_mutex_lock(&adev->lock);
3072 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3073 !in->capture_started && in->pcm != NULL) {
3074 if (!in->capture_started) {
3075 ret = start_input_stream(in);
3076 if (ret == 0) {
3077 in->capture_started = true;
3078 }
3079 }
3080 }
3081 pthread_mutex_unlock(&adev->lock);
3082 return ret;
3083}
3084
3085static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3086 int32_t min_size_frames,
3087 struct audio_mmap_buffer_info *info)
3088{
3089 struct stream_in *in = (struct stream_in *)stream;
3090 struct audio_device *adev = in->dev;
3091 int ret = 0;
3092 unsigned int offset1;
3093 unsigned int frames1;
3094 const char *step = "";
3095
3096 pthread_mutex_lock(&adev->lock);
3097 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003098
Eric Laurent0e46adf2016-12-16 12:49:24 -08003099 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003100 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003101 ret = -EINVAL;
3102 goto exit;
3103 }
3104 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003105 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003106 ALOGV("%s in %p", __func__, in);
3107 ret = -ENOSYS;
3108 goto exit;
3109 }
3110 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3111 if (in->pcm_device_id < 0) {
3112 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3113 __func__, in->pcm_device_id, in->usecase);
3114 ret = -EINVAL;
3115 goto exit;
3116 }
Phil Burkbc991042017-02-24 08:06:44 -08003117
3118 adjust_mmap_period_count(&in->config, min_size_frames);
3119
Eric Laurent0e46adf2016-12-16 12:49:24 -08003120 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3121 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3122 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3123 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3124 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3125 step = "open";
3126 ret = -ENODEV;
3127 goto exit;
3128 }
3129
3130 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3131 if (ret < 0) {
3132 step = "begin";
3133 goto exit;
3134 }
3135 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
3136 info->burst_size_frames = in->config.period_size;
3137 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3138
3139 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(in->pcm,
3140 info->buffer_size_frames));
3141
3142 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3143 if (ret < 0) {
3144 step = "commit";
3145 goto exit;
3146 }
3147
Phil Burkbc991042017-02-24 08:06:44 -08003148 in->standby = false;
3149 ret = 0;
3150
Eric Laurent0e46adf2016-12-16 12:49:24 -08003151 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3152 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003153
3154exit:
3155 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003156 if (in->pcm == NULL) {
3157 ALOGE("%s: %s - %d", __func__, step, ret);
3158 } else {
3159 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003160 pcm_close(in->pcm);
3161 in->pcm = NULL;
3162 }
3163 }
3164 pthread_mutex_unlock(&adev->lock);
3165 return ret;
3166}
3167
3168static int in_get_mmap_position(const struct audio_stream_in *stream,
3169 struct audio_mmap_position *position)
3170{
3171 struct stream_in *in = (struct stream_in *)stream;
3172 ALOGVV("%s", __func__);
3173 if (position == NULL) {
3174 return -EINVAL;
3175 }
3176 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
3177 return -ENOSYS;
3178 }
3179 if (in->pcm == NULL) {
3180 return -ENOSYS;
3181 }
3182 struct timespec ts = { 0, 0 };
3183 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
3184 if (ret < 0) {
3185 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3186 return ret;
3187 }
Andy Hungfc044e12017-03-20 09:24:22 -07003188 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003189 return 0;
3190}
3191
3192
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003193static int adev_open_output_stream(struct audio_hw_device *dev,
3194 audio_io_handle_t handle,
3195 audio_devices_t devices,
3196 audio_output_flags_t flags,
3197 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003198 struct audio_stream_out **stream_out,
3199 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003200{
3201 struct audio_device *adev = (struct audio_device *)dev;
3202 struct stream_out *out;
3203 int i, ret;
3204
Eric Laurent994a6932013-07-17 11:51:42 -07003205 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003206 __func__, config->sample_rate, config->channel_mask, devices, flags);
3207 *stream_out = NULL;
3208 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3209
3210 if (devices == AUDIO_DEVICE_NONE)
3211 devices = AUDIO_DEVICE_OUT_SPEAKER;
3212
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003213 out->flags = flags;
3214 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003215 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003216 out->format = config->format;
3217 out->sample_rate = config->sample_rate;
3218 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3219 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003220 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003221
3222 /* Init use case and pcm_config */
3223 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
Eric Laurent7f245042013-09-30 19:22:50 -07003224 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003225 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003226 pthread_mutex_lock(&adev->lock);
3227 ret = read_hdmi_channel_masks(out);
3228 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003229 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003230 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003231
3232 if (config->sample_rate == 0)
3233 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3234 if (config->channel_mask == 0)
3235 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Eric Laurentad1cec22015-12-16 10:12:27 -08003236 if (config->format == AUDIO_FORMAT_DEFAULT)
3237 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003238
3239 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003240 out->sample_rate = config->sample_rate;
Eric Laurentad1cec22015-12-16 10:12:27 -08003241 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003242 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3243 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003244 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003245 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003246 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003247 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003248 pthread_mutex_lock(&adev->lock);
3249 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3250 pthread_mutex_unlock(&adev->lock);
3251
3252 // reject offload during card offline to allow
3253 // fallback to s/w paths
3254 if (offline) {
3255 ret = -ENODEV;
3256 goto error_open;
3257 }
3258
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003259 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3260 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3261 ALOGE("%s: Unsupported Offload information", __func__);
3262 ret = -EINVAL;
3263 goto error_open;
3264 }
3265 if (!is_supported_format(config->offload_info.format)) {
3266 ALOGE("%s: Unsupported audio format", __func__);
3267 ret = -EINVAL;
3268 goto error_open;
3269 }
3270
3271 out->compr_config.codec = (struct snd_codec *)
3272 calloc(1, sizeof(struct snd_codec));
3273
3274 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3275 if (config->offload_info.channel_mask)
3276 out->channel_mask = config->offload_info.channel_mask;
3277 else if (config->channel_mask)
3278 out->channel_mask = config->channel_mask;
3279 out->format = config->offload_info.format;
3280 out->sample_rate = config->offload_info.sample_rate;
3281
3282 out->stream.set_callback = out_set_callback;
3283 out->stream.pause = out_pause;
3284 out->stream.resume = out_resume;
3285 out->stream.drain = out_drain;
3286 out->stream.flush = out_flush;
3287
3288 out->compr_config.codec->id =
3289 get_snd_codec_id(config->offload_info.format);
3290 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3291 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07003292 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003293 out->compr_config.codec->bit_rate =
3294 config->offload_info.bit_rate;
3295 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003296 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003297 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3298
3299 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3300 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003301
3302 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003303 create_offload_callback_thread(out);
3304 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3305 __func__, config->offload_info.version,
3306 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003307 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3308 if (config->sample_rate == 0)
3309 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3310 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3311 config->sample_rate != 8000) {
3312 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3313 ret = -EINVAL;
3314 goto error_open;
3315 }
3316 out->sample_rate = config->sample_rate;
3317 out->config.rate = config->sample_rate;
3318 if (config->format == AUDIO_FORMAT_DEFAULT)
3319 config->format = AUDIO_FORMAT_PCM_16_BIT;
3320 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3321 config->format = AUDIO_FORMAT_PCM_16_BIT;
3322 ret = -EINVAL;
3323 goto error_open;
3324 }
3325 out->format = config->format;
3326 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3327 out->config = pcm_config_afe_proxy_playback;
3328 adev->voice_tx_output = out;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003329 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003330 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3331 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3332 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003333 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
3334 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3335 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003336 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3337 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003338 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003339 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003340 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3341 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3342 out->config = pcm_config_mmap_playback;
3343 out->stream.start = out_start;
3344 out->stream.stop = out_stop;
3345 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3346 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003347 } else {
3348 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3349 out->config = pcm_config_low_latency;
3350 }
3351 if (config->format != audio_format_from_pcm_format(out->config.format)) {
3352 if (k_enable_extended_precision
3353 && pcm_params_format_test(adev->use_case_table[out->usecase],
3354 pcm_format_from_audio_format(config->format))) {
3355 out->config.format = pcm_format_from_audio_format(config->format);
3356 /* out->format already set to config->format */
3357 } else {
3358 /* deny the externally proposed config format
3359 * and use the one specified in audio_hw layer configuration.
3360 * Note: out->format is returned by out->stream.common.get_format()
3361 * and is used to set config->format in the code several lines below.
3362 */
3363 out->format = audio_format_from_pcm_format(out->config.format);
3364 }
3365 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003366 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003367 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07003368 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3369 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003370
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003371 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003372 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003373 adev->primary_output = out;
3374 else {
3375 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003376 ret = -EEXIST;
3377 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003378 }
3379 }
3380
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003381 /* Check if this usecase is already existing */
3382 pthread_mutex_lock(&adev->lock);
3383 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3384 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003385 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003386 ret = -EEXIST;
3387 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003388 }
3389 pthread_mutex_unlock(&adev->lock);
3390
3391 out->stream.common.get_sample_rate = out_get_sample_rate;
3392 out->stream.common.set_sample_rate = out_set_sample_rate;
3393 out->stream.common.get_buffer_size = out_get_buffer_size;
3394 out->stream.common.get_channels = out_get_channels;
3395 out->stream.common.get_format = out_get_format;
3396 out->stream.common.set_format = out_set_format;
3397 out->stream.common.standby = out_standby;
3398 out->stream.common.dump = out_dump;
3399 out->stream.common.set_parameters = out_set_parameters;
3400 out->stream.common.get_parameters = out_get_parameters;
3401 out->stream.common.add_audio_effect = out_add_audio_effect;
3402 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3403 out->stream.get_latency = out_get_latency;
3404 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003405#ifdef NO_AUDIO_OUT
3406 out->stream.write = out_write_for_no_output;
3407#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003408 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003409#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003410 out->stream.get_render_position = out_get_render_position;
3411 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003412 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003413
Eric Laurent0e46adf2016-12-16 12:49:24 -08003414 if (out->realtime)
3415 out->af_period_multiplier = af_period_multiplier;
3416 else
3417 out->af_period_multiplier = 1;
3418
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003419 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003420 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003421 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003422
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003423 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003424 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003425 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3426
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003427 config->format = out->stream.common.get_format(&out->stream.common);
3428 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3429 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3430
Andy Hunga452b0a2017-03-15 14:51:15 -07003431 out->error_log = error_log_create(
3432 ERROR_LOG_ENTRIES,
3433 1000000000 /* aggregate consecutive identical errors within one second in ns */);
3434
Andy Hungfc044e12017-03-20 09:24:22 -07003435 // power_log may be null if the format is not supported
Andy Hung9e737de2017-05-22 10:51:22 -07003436 // or not a userdebug or eng build.
Andy Hung02caae52017-06-06 12:33:33 -07003437 if (false /* is_userdebug_or_eng_build() */) {
Andy Hung9e737de2017-05-22 10:51:22 -07003438 const size_t POWER_LOG_FRAMES_PER_ENTRY =
3439 (long long)config->sample_rate * POWER_LOG_SAMPLING_INTERVAL_MS / 1000;
3440
3441 out->power_log = power_log_create(
3442 config->sample_rate,
3443 audio_channel_count_from_out_mask(config->channel_mask),
3444 config->format,
3445 POWER_LOG_ENTRIES,
3446 POWER_LOG_FRAMES_PER_ENTRY);
3447 }
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003448
3449 /*
3450 By locking output stream before registering, we allow the callback
3451 to update stream's state only after stream's initial state is set to
3452 adev state.
3453 */
3454 lock_output_stream(out);
3455 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3456 pthread_mutex_lock(&adev->lock);
3457 out->card_status = adev->card_status;
3458 pthread_mutex_unlock(&adev->lock);
3459 pthread_mutex_unlock(&out->lock);
3460
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003461 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003462
Eric Laurent994a6932013-07-17 11:51:42 -07003463 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003464 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003465
3466error_open:
3467 free(out);
3468 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003469 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003470 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003471}
3472
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003473static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003474 struct audio_stream_out *stream)
3475{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003476 struct stream_out *out = (struct stream_out *)stream;
3477 struct audio_device *adev = out->dev;
3478
Eric Laurent994a6932013-07-17 11:51:42 -07003479 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003480
3481 // must deregister from sndmonitor first to prevent races
3482 // between the callback and close_stream
3483 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003484 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003485 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3486 destroy_offload_callback_thread(out);
3487
3488 if (out->compr_config.codec != NULL)
3489 free(out->compr_config.codec);
3490 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003491
3492 if (adev->voice_tx_output == out)
3493 adev->voice_tx_output = NULL;
3494
Andy Hungfc044e12017-03-20 09:24:22 -07003495 power_log_destroy(out->power_log);
3496 out->power_log = NULL;
3497
Andy Hunga452b0a2017-03-15 14:51:15 -07003498 error_log_destroy(out->error_log);
3499 out->error_log = NULL;
3500
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003501 pthread_cond_destroy(&out->cond);
3502 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003503 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003504 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003505}
3506
3507static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3508{
3509 struct audio_device *adev = (struct audio_device *)dev;
3510 struct str_parms *parms;
3511 char *str;
3512 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003513 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003514 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003515 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003516
Joe Onorato188b6222016-03-01 11:02:27 -08003517 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003518
3519 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003520
3521 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003522 status = voice_set_parameters(adev, parms);
3523 if (status != 0) {
3524 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003525 }
3526
3527 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3528 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003529 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003530 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3531 adev->bluetooth_nrec = true;
3532 else
3533 adev->bluetooth_nrec = false;
3534 }
3535
3536 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3537 if (ret >= 0) {
3538 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3539 adev->screen_off = false;
3540 else
3541 adev->screen_off = true;
3542 }
3543
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003544 ret = str_parms_get_int(parms, "rotation", &val);
3545 if (ret >= 0) {
3546 bool reverse_speakers = false;
3547 switch(val) {
3548 // FIXME: note that the code below assumes that the speakers are in the correct placement
3549 // relative to the user when the device is rotated 90deg from its default rotation. This
3550 // assumption is device-specific, not platform-specific like this code.
3551 case 270:
3552 reverse_speakers = true;
3553 break;
3554 case 0:
3555 case 90:
3556 case 180:
3557 break;
3558 default:
3559 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003560 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003561 }
Eric Laurent03f09432014-03-25 18:09:11 -07003562 if (status == 0) {
Ravi Kumar Alamanda1f60cf82015-04-23 19:45:17 -07003563 platform_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003564 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003565 }
3566
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003567 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3568 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003569 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003570 }
3571
David Linee3fe402017-03-13 10:00:42 -07003572 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3573 if (ret >= 0) {
3574 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
3575 if (device == AUDIO_DEVICE_OUT_USB_DEVICE) {
3576 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3577 if (ret >= 0) {
3578 const int card = atoi(value);
3579 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, card);
3580 }
3581 } else if (device == AUDIO_DEVICE_IN_USB_DEVICE) {
3582 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3583 if (ret >= 0) {
3584 const int card = atoi(value);
3585 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, card);
3586 }
3587 }
3588 }
3589
3590 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3591 if (ret >= 0) {
3592 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
3593 if (device == AUDIO_DEVICE_OUT_USB_DEVICE) {
3594 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3595 if (ret >= 0) {
3596 const int card = atoi(value);
3597
3598 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, card);
3599 }
3600 } else if (device == AUDIO_DEVICE_IN_USB_DEVICE) {
3601 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3602 if (ret >= 0) {
3603 const int card = atoi(value);
3604 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, card);
3605 }
3606 }
3607 }
3608
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08003609 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003610done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003611 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003612 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07003613 ALOGV("%s: exit with code(%d)", __func__, status);
3614 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003615}
3616
3617static char* adev_get_parameters(const struct audio_hw_device *dev,
3618 const char *keys)
3619{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003620 struct audio_device *adev = (struct audio_device *)dev;
3621 struct str_parms *reply = str_parms_create();
3622 struct str_parms *query = str_parms_create_str(keys);
3623 char *str;
3624
3625 pthread_mutex_lock(&adev->lock);
3626
3627 voice_get_parameters(adev, query, reply);
3628 str = str_parms_to_str(reply);
3629 str_parms_destroy(query);
3630 str_parms_destroy(reply);
3631
3632 pthread_mutex_unlock(&adev->lock);
3633 ALOGV("%s: exit: returns - %s", __func__, str);
3634 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003635}
3636
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003637static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003638{
3639 return 0;
3640}
3641
Haynes Mathew George5191a852013-09-11 14:19:36 -07003642static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3643{
3644 int ret;
3645 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003646
Eric Laurent4cc4ce12014-09-10 13:21:01 -05003647 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
3648
Haynes Mathew George5191a852013-09-11 14:19:36 -07003649 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003650 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003651 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003652
Haynes Mathew George5191a852013-09-11 14:19:36 -07003653 return ret;
3654}
3655
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003656static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003657{
3658 return -ENOSYS;
3659}
3660
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003661static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3662 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003663{
3664 return -ENOSYS;
3665}
3666
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003667static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003668{
3669 return -ENOSYS;
3670}
3671
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003672static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003673{
3674 return -ENOSYS;
3675}
3676
3677static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3678{
3679 struct audio_device *adev = (struct audio_device *)dev;
3680
3681 pthread_mutex_lock(&adev->lock);
3682 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07003683 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003684 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07003685 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3686 voice_is_in_call(adev)) {
3687 voice_stop_call(adev);
3688 adev->current_call_output = NULL;
3689 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003690 }
3691 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003692
3693 audio_extn_extspk_set_mode(adev->extspk, mode);
3694
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003695 return 0;
3696}
3697
3698static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3699{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003700 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003701 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003702
Eric Laurent2bafff12016-03-17 12:17:23 -07003703 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003704 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08003705 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
3706 ret = audio_extn_hfp_set_mic_mute(adev, state);
3707 } else {
3708 ret = voice_set_mic_mute(adev, state);
3709 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003710 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00003711 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003712
3713 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003714}
3715
3716static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3717{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003718 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003719 return 0;
3720}
3721
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003722static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003723 const struct audio_config *config)
3724{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003725 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003726
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003727 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3728 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003729}
3730
3731static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003732 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003733 audio_devices_t devices,
3734 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003735 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07003736 audio_input_flags_t flags,
3737 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05003738 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003739{
3740 struct audio_device *adev = (struct audio_device *)dev;
3741 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003742 int ret = 0, buffer_size, frame_size;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003743 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003744 bool is_low_latency = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003745
Eric Laurent994a6932013-07-17 11:51:42 -07003746 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003747 *stream_in = NULL;
3748 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3749 return -EINVAL;
3750
Zheng Zhang6185d572016-12-01 20:35:17 +08003751 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 -08003752 return -EINVAL;
3753
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003754 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
3755
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003756 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003757 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003758
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003759 in->stream.common.get_sample_rate = in_get_sample_rate;
3760 in->stream.common.set_sample_rate = in_set_sample_rate;
3761 in->stream.common.get_buffer_size = in_get_buffer_size;
3762 in->stream.common.get_channels = in_get_channels;
3763 in->stream.common.get_format = in_get_format;
3764 in->stream.common.set_format = in_set_format;
3765 in->stream.common.standby = in_standby;
3766 in->stream.common.dump = in_dump;
3767 in->stream.common.set_parameters = in_set_parameters;
3768 in->stream.common.get_parameters = in_get_parameters;
3769 in->stream.common.add_audio_effect = in_add_audio_effect;
3770 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3771 in->stream.set_gain = in_set_gain;
3772 in->stream.read = in_read;
3773 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08003774 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003775
3776 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003777 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003778 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003779 in->standby = 1;
3780 in->channel_mask = config->channel_mask;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003781 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003782 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003783
vivek mehta57ff9b52016-04-28 14:13:08 -07003784 // restrict 24 bit capture for unprocessed source only
3785 // for other sources if 24 bit requested reject 24 and set 16 bit capture only
3786 if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07003787 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07003788 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
3789 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
3790 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
3791 bool ret_error = false;
3792 /* 24 bit is restricted to UNPROCESSED source only,also format supported
3793 from HAL is 8_24
3794 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
3795 8_24 return error indicating supported format is 8_24
3796 *> In case of any other source requesting 24 bit or float return error
3797 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07003798
vivek mehta57ff9b52016-04-28 14:13:08 -07003799 on error flinger will retry with supported format passed
3800 */
3801 if (source != AUDIO_SOURCE_UNPROCESSED) {
3802 config->format = AUDIO_FORMAT_PCM_16_BIT;
3803 ret_error = true;
3804 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
3805 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
3806 ret_error = true;
3807 }
3808
3809 if (ret_error) {
3810 ret = -EINVAL;
3811 goto err_open;
3812 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003813 }
3814
vivek mehta57ff9b52016-04-28 14:13:08 -07003815 in->format = config->format;
3816
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003817 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003818 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
3819 if (config->sample_rate == 0)
3820 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3821 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3822 config->sample_rate != 8000) {
3823 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3824 ret = -EINVAL;
3825 goto err_open;
3826 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003827
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003828 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3829 config->format = AUDIO_FORMAT_PCM_16_BIT;
3830 ret = -EINVAL;
3831 goto err_open;
3832 }
3833
3834 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3835 in->config = pcm_config_afe_proxy_record;
David Lin73f45252017-03-29 13:37:33 -07003836 in->af_period_multiplier = 1;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003837 } else {
3838 in->usecase = USECASE_AUDIO_RECORD;
3839 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08003840 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003841 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07003842#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003843 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07003844#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08003845 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003846 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08003847 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003848 frame_size = audio_stream_in_frame_size(&in->stream);
3849 buffer_size = get_input_buffer_size(config->sample_rate,
3850 config->format,
3851 channel_count,
3852 is_low_latency);
3853 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003854 in->config.rate = config->sample_rate;
3855 in->af_period_multiplier = 1;
3856 } else {
3857 // period size is left untouched for rt mode playback
3858 in->config = pcm_config_audio_capture_rt;
3859 in->af_period_multiplier = af_period_multiplier;
3860 }
3861 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
3862 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
3863 in->usecase = USECASE_AUDIO_RECORD_MMAP;
3864 in->config = pcm_config_mmap_capture;
3865 in->stream.start = in_start;
3866 in->stream.stop = in_stop;
3867 in->stream.create_mmap_buffer = in_create_mmap_buffer;
3868 in->stream.get_mmap_position = in_get_mmap_position;
3869 in->af_period_multiplier = 1;
3870 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
3871 } else {
3872 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003873 frame_size = audio_stream_in_frame_size(&in->stream);
3874 buffer_size = get_input_buffer_size(config->sample_rate,
3875 config->format,
3876 channel_count,
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003877 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003878 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003879 in->config.rate = config->sample_rate;
3880 in->af_period_multiplier = 1;
3881 }
3882 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
3883 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003884 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003885
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003886 in->config.channels = channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003887
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003888 /* This stream could be for sound trigger lab,
3889 get sound trigger pcm if present */
3890 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003891
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003892 lock_input_stream(in);
3893 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
3894 pthread_mutex_lock(&adev->lock);
3895 in->card_status = adev->card_status;
3896 pthread_mutex_unlock(&adev->lock);
3897 pthread_mutex_unlock(&in->lock);
3898
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003899 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003900 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003901 return 0;
3902
3903err_open:
3904 free(in);
3905 *stream_in = NULL;
3906 return ret;
3907}
3908
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003909static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003910 struct audio_stream_in *stream)
3911{
Eric Laurent994a6932013-07-17 11:51:42 -07003912 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003913
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003914 // must deregister from sndmonitor first to prevent races
3915 // between the callback and close_stream
3916 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003917 in_standby(&stream->common);
3918 free(stream);
3919
3920 return;
3921}
3922
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003923static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003924{
3925 return 0;
3926}
3927
Andy Hung31aca912014-03-20 17:14:59 -07003928/* verifies input and output devices and their capabilities.
3929 *
3930 * This verification is required when enabling extended bit-depth or
3931 * sampling rates, as not all qcom products support it.
3932 *
3933 * Suitable for calling only on initialization such as adev_open().
3934 * It fills the audio_device use_case_table[] array.
3935 *
3936 * Has a side-effect that it needs to configure audio routing / devices
3937 * in order to power up the devices and read the device parameters.
3938 * It does not acquire any hw device lock. Should restore the devices
3939 * back to "normal state" upon completion.
3940 */
3941static int adev_verify_devices(struct audio_device *adev)
3942{
3943 /* enumeration is a bit difficult because one really wants to pull
3944 * the use_case, device id, etc from the hidden pcm_device_table[].
3945 * In this case there are the following use cases and device ids.
3946 *
3947 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
3948 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
3949 * [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
3950 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
3951 * [USECASE_AUDIO_RECORD] = {0, 0},
3952 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
3953 * [USECASE_VOICE_CALL] = {2, 2},
3954 *
3955 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_MULTI_CH omitted.
3956 * USECASE_VOICE_CALL omitted, but possible for either input or output.
3957 */
3958
3959 /* should be the usecases enabled in adev_open_input_stream() */
3960 static const int test_in_usecases[] = {
3961 USECASE_AUDIO_RECORD,
3962 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
3963 };
3964 /* should be the usecases enabled in adev_open_output_stream()*/
3965 static const int test_out_usecases[] = {
3966 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
3967 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
3968 };
3969 static const usecase_type_t usecase_type_by_dir[] = {
3970 PCM_PLAYBACK,
3971 PCM_CAPTURE,
3972 };
3973 static const unsigned flags_by_dir[] = {
3974 PCM_OUT,
3975 PCM_IN,
3976 };
3977
3978 size_t i;
3979 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003980 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07003981 char info[512]; /* for possible debug info */
3982
3983 for (dir = 0; dir < 2; ++dir) {
3984 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
3985 const unsigned flags_dir = flags_by_dir[dir];
3986 const size_t testsize =
3987 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
3988 const int *testcases =
3989 dir ? test_in_usecases : test_out_usecases;
3990 const audio_devices_t audio_device =
3991 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
3992
3993 for (i = 0; i < testsize; ++i) {
3994 const audio_usecase_t audio_usecase = testcases[i];
3995 int device_id;
3996 snd_device_t snd_device;
3997 struct pcm_params **pparams;
3998 struct stream_out out;
3999 struct stream_in in;
4000 struct audio_usecase uc_info;
4001 int retval;
4002
4003 pparams = &adev->use_case_table[audio_usecase];
4004 pcm_params_free(*pparams); /* can accept null input */
4005 *pparams = NULL;
4006
4007 /* find the device ID for the use case (signed, for error) */
4008 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
4009 if (device_id < 0)
4010 continue;
4011
4012 /* prepare structures for device probing */
4013 memset(&uc_info, 0, sizeof(uc_info));
4014 uc_info.id = audio_usecase;
4015 uc_info.type = usecase_type;
4016 if (dir) {
4017 adev->active_input = &in;
4018 memset(&in, 0, sizeof(in));
4019 in.device = audio_device;
4020 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4021 uc_info.stream.in = &in;
4022 } else {
4023 adev->active_input = NULL;
4024 }
4025 memset(&out, 0, sizeof(out));
4026 out.devices = audio_device; /* only field needed in select_devices */
4027 uc_info.stream.out = &out;
4028 uc_info.devices = audio_device;
4029 uc_info.in_snd_device = SND_DEVICE_NONE;
4030 uc_info.out_snd_device = SND_DEVICE_NONE;
4031 list_add_tail(&adev->usecase_list, &uc_info.list);
4032
4033 /* select device - similar to start_(in/out)put_stream() */
4034 retval = select_devices(adev, audio_usecase);
4035 if (retval >= 0) {
4036 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4037#if LOG_NDEBUG == 0
4038 if (*pparams) {
4039 ALOGV("%s: (%s) card %d device %d", __func__,
4040 dir ? "input" : "output", card_id, device_id);
4041 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004042 } else {
4043 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4044 }
4045#endif
4046 }
4047
4048 /* deselect device - similar to stop_(in/out)put_stream() */
4049 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004050 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004051 /* 2. Disable the rx device */
4052 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004053 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004054 list_remove(&uc_info.list);
4055 }
4056 }
4057 adev->active_input = NULL; /* restore adev state */
4058 return 0;
4059}
4060
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004061static int adev_close(hw_device_t *device)
4062{
Andy Hung31aca912014-03-20 17:14:59 -07004063 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004064 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004065
4066 if (!adev)
4067 return 0;
4068
Kevin Rocarda5453442017-05-02 15:09:20 -07004069 audio_extn_snd_mon_unregister_listener(adev);
Kevin Rocard8342c2c2017-04-07 18:50:00 -07004070 audio_extn_snd_mon_deinit();
Kevin Rocarda5453442017-05-02 15:09:20 -07004071
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004072 audio_extn_tfa_98xx_deinit();
4073
vivek mehta1a9b7c02015-06-25 11:49:38 -07004074 pthread_mutex_lock(&adev_init_lock);
4075
4076 if ((--audio_device_ref_count) == 0) {
4077 audio_route_free(adev->audio_route);
4078 free(adev->snd_dev_ref_cnt);
4079 platform_deinit(adev->platform);
4080 audio_extn_extspk_deinit(adev->extspk);
4081 audio_extn_sound_trigger_deinit(adev);
4082 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4083 pcm_params_free(adev->use_case_table[i]);
4084 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004085 if (adev->adm_deinit)
4086 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004087 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004088 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004089
4090 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004091
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004092 return 0;
4093}
4094
Glenn Kasten4f993392014-05-14 07:30:48 -07004095/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4096 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4097 * just that it _might_ work.
4098 */
4099static int period_size_is_plausible_for_low_latency(int period_size)
4100{
4101 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004102 case 48:
4103 case 96:
4104 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004105 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004106 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004107 case 240:
4108 case 320:
4109 case 480:
4110 return 1;
4111 default:
4112 return 0;
4113 }
4114}
4115
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004116static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4117{
4118 int card;
4119 card_status_t status;
4120
4121 if (!parms)
4122 return;
4123
4124 if (parse_snd_card_status(parms, &card, &status) < 0)
4125 return;
4126
4127 pthread_mutex_lock(&adev->lock);
4128 bool valid_cb = (card == adev->snd_card);
4129 if (valid_cb) {
4130 if (adev->card_status != status) {
4131 adev->card_status = status;
4132 platform_snd_card_update(adev->platform, status);
4133 }
4134 }
4135 pthread_mutex_unlock(&adev->lock);
4136 return;
4137}
4138
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004139static int adev_open(const hw_module_t *module, const char *name,
4140 hw_device_t **device)
4141{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004142 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004143
Eric Laurent2bafff12016-03-17 12:17:23 -07004144 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004145 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004146 pthread_mutex_lock(&adev_init_lock);
4147 if (audio_device_ref_count != 0) {
4148 *device = &adev->device.common;
4149 audio_device_ref_count++;
4150 ALOGV("%s: returning existing instance of adev", __func__);
4151 ALOGV("%s: exit", __func__);
4152 pthread_mutex_unlock(&adev_init_lock);
4153 return 0;
4154 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004155 adev = calloc(1, sizeof(struct audio_device));
4156
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004157 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4158
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004159 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4160 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4161 adev->device.common.module = (struct hw_module_t *)module;
4162 adev->device.common.close = adev_close;
4163
4164 adev->device.init_check = adev_init_check;
4165 adev->device.set_voice_volume = adev_set_voice_volume;
4166 adev->device.set_master_volume = adev_set_master_volume;
4167 adev->device.get_master_volume = adev_get_master_volume;
4168 adev->device.set_master_mute = adev_set_master_mute;
4169 adev->device.get_master_mute = adev_get_master_mute;
4170 adev->device.set_mode = adev_set_mode;
4171 adev->device.set_mic_mute = adev_set_mic_mute;
4172 adev->device.get_mic_mute = adev_get_mic_mute;
4173 adev->device.set_parameters = adev_set_parameters;
4174 adev->device.get_parameters = adev_get_parameters;
4175 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4176 adev->device.open_output_stream = adev_open_output_stream;
4177 adev->device.close_output_stream = adev_close_output_stream;
4178 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004179
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004180 adev->device.close_input_stream = adev_close_input_stream;
4181 adev->device.dump = adev_dump;
4182
4183 /* Set the default route before the PCM stream is opened */
4184 pthread_mutex_lock(&adev->lock);
4185 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004186 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004187 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004188 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004189 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004190 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004191 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004192 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004193 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004194 pthread_mutex_unlock(&adev->lock);
4195
4196 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004197 adev->platform = platform_init(adev);
4198 if (!adev->platform) {
4199 free(adev->snd_dev_ref_cnt);
4200 free(adev);
4201 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4202 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004203 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004204 return -EINVAL;
4205 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05004206 adev->extspk = audio_extn_extspk_init(adev);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004207 audio_extn_sound_trigger_init(adev);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004208
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004209 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4210 if (adev->visualizer_lib == NULL) {
4211 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4212 } else {
4213 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4214 adev->visualizer_start_output =
4215 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4216 "visualizer_hal_start_output");
4217 adev->visualizer_stop_output =
4218 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4219 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07004220 }
4221
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004222 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4223 if (adev->offload_effects_lib == NULL) {
4224 ALOGW("%s: DLOPEN failed for %s", __func__,
4225 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4226 } else {
4227 ALOGV("%s: DLOPEN successful for %s", __func__,
4228 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4229 adev->offload_effects_start_output =
4230 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4231 "offload_effects_bundle_hal_start_output");
4232 adev->offload_effects_stop_output =
4233 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4234 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07004235 }
4236
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004237 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4238 if (adev->adm_lib == NULL) {
4239 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4240 } else {
4241 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4242 adev->adm_init = (adm_init_t)
4243 dlsym(adev->adm_lib, "adm_init");
4244 adev->adm_deinit = (adm_deinit_t)
4245 dlsym(adev->adm_lib, "adm_deinit");
4246 adev->adm_register_input_stream = (adm_register_input_stream_t)
4247 dlsym(adev->adm_lib, "adm_register_input_stream");
4248 adev->adm_register_output_stream = (adm_register_output_stream_t)
4249 dlsym(adev->adm_lib, "adm_register_output_stream");
4250 adev->adm_deregister_stream = (adm_deregister_stream_t)
4251 dlsym(adev->adm_lib, "adm_deregister_stream");
4252 adev->adm_request_focus = (adm_request_focus_t)
4253 dlsym(adev->adm_lib, "adm_request_focus");
4254 adev->adm_abandon_focus = (adm_abandon_focus_t)
4255 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08004256 adev->adm_set_config = (adm_set_config_t)
4257 dlsym(adev->adm_lib, "adm_set_config");
4258 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4259 dlsym(adev->adm_lib, "adm_request_focus_v2");
4260 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4261 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4262 adev->adm_on_routing_change = (adm_on_routing_change_t)
4263 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004264 }
4265
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004266 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004267 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004268
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004269 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004270
Andy Hung31aca912014-03-20 17:14:59 -07004271 if (k_enable_extended_precision)
4272 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004273
Glenn Kasten4f993392014-05-14 07:30:48 -07004274 char value[PROPERTY_VALUE_MAX];
4275 int trial;
4276 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4277 trial = atoi(value);
4278 if (period_size_is_plausible_for_low_latency(trial)) {
4279 pcm_config_low_latency.period_size = trial;
4280 pcm_config_low_latency.start_threshold = trial / 4;
4281 pcm_config_low_latency.avail_min = trial / 4;
4282 configured_low_latency_capture_period_size = trial;
4283 }
4284 }
4285 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4286 trial = atoi(value);
4287 if (period_size_is_plausible_for_low_latency(trial)) {
4288 configured_low_latency_capture_period_size = trial;
4289 }
4290 }
4291
Yamit Mehtae3b99562016-09-16 22:44:00 +05304292 audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004293 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004294
4295 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4296 af_period_multiplier = atoi(value);
4297 if (af_period_multiplier < 0) {
4298 af_period_multiplier = 2;
4299 } else if (af_period_multiplier > 4) {
4300 af_period_multiplier = 4;
4301 }
4302 ALOGV("new period_multiplier = %d", af_period_multiplier);
4303 }
4304
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004305 audio_extn_tfa_98xx_init(adev);
4306
vivek mehta1a9b7c02015-06-25 11:49:38 -07004307 pthread_mutex_unlock(&adev_init_lock);
4308
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004309 if (adev->adm_init)
4310 adev->adm_data = adev->adm_init();
4311
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004312 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004313 audio_extn_snd_mon_init();
4314 pthread_mutex_lock(&adev->lock);
4315 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
4316 adev->card_status = CARD_STATUS_ONLINE;
4317 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004318
Eric Laurent2bafff12016-03-17 12:17:23 -07004319 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004320 return 0;
4321}
4322
4323static struct hw_module_methods_t hal_module_methods = {
4324 .open = adev_open,
4325};
4326
4327struct audio_module HAL_MODULE_INFO_SYM = {
4328 .common = {
4329 .tag = HARDWARE_MODULE_TAG,
4330 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4331 .hal_api_version = HARDWARE_HAL_API_VERSION,
4332 .id = AUDIO_HARDWARE_MODULE_ID,
4333 .name = "QCOM Audio HAL",
4334 .author = "Code Aurora Forum",
4335 .methods = &hal_module_methods,
4336 },
4337};