blob: e7de4a9dac6ff3af265987739e0c1c2df49a8508 [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 {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001676 unsigned int flags = PCM_OUT;
1677 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;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001684 } else
1685 flags |= PCM_MONOTONIC;
1686
1687 while (1) {
1688 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1689 flags, &out->config);
1690 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1691 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1692 if (out->pcm != NULL) {
1693 pcm_close(out->pcm);
1694 out->pcm = NULL;
1695 }
1696 if (pcm_open_retry_count-- == 0) {
1697 ret = -EIO;
1698 goto error_open;
1699 }
1700 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1701 continue;
1702 }
1703 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001704 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001705 ALOGV("%s: pcm_prepare", __func__);
1706 if (pcm_is_ready(out->pcm)) {
1707 ret = pcm_prepare(out->pcm);
1708 if (ret < 0) {
1709 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1710 pcm_close(out->pcm);
1711 out->pcm = NULL;
1712 goto error_open;
1713 }
1714 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001715 if (out->realtime) {
1716 ret = pcm_start(out->pcm);
1717 if (ret < 0) {
1718 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1719 pcm_close(out->pcm);
1720 out->pcm = NULL;
1721 goto error_open;
1722 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001723 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001724 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001725 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001726 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001727 audio_extn_tfa_98xx_enable_speaker();
1728
Eric Laurent994a6932013-07-17 11:51:42 -07001729 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001730 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001731error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001732 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001733 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001734error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001735 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001736}
1737
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001738static int check_input_parameters(uint32_t sample_rate,
1739 audio_format_t format,
1740 int channel_count)
1741{
vivek mehta4ed66e62016-04-15 23:33:34 -07001742 if ((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT)) {
vivek mehtadae44712015-07-27 14:13:18 -07001743 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1744 return -EINVAL;
1745 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001746
vivek mehtadae44712015-07-27 14:13:18 -07001747 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > MAX_CHANNEL_COUNT)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001748 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
vivek mehtadae44712015-07-27 14:13:18 -07001749 channel_count, MIN_CHANNEL_COUNT, MAX_CHANNEL_COUNT);
1750 return -EINVAL;
1751 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001752
1753 switch (sample_rate) {
1754 case 8000:
1755 case 11025:
1756 case 12000:
1757 case 16000:
1758 case 22050:
1759 case 24000:
1760 case 32000:
1761 case 44100:
1762 case 48000:
1763 break;
1764 default:
vivek mehtadae44712015-07-27 14:13:18 -07001765 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001766 return -EINVAL;
1767 }
1768
1769 return 0;
1770}
1771
1772static size_t get_input_buffer_size(uint32_t sample_rate,
1773 audio_format_t format,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001774 int channel_count,
1775 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001776{
1777 size_t size = 0;
1778
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001779 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1780 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001781
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001782 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001783 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001784 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07001785
1786 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001787
Glenn Kasten4f993392014-05-14 07:30:48 -07001788 /* make sure the size is multiple of 32 bytes
1789 * At 48 kHz mono 16-bit PCM:
1790 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1791 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1792 */
1793 size += 0x1f;
1794 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001795
1796 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001797}
1798
1799static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1800{
1801 struct stream_out *out = (struct stream_out *)stream;
1802
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001803 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001804}
1805
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001806static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001807{
1808 return -ENOSYS;
1809}
1810
1811static size_t out_get_buffer_size(const struct audio_stream *stream)
1812{
1813 struct stream_out *out = (struct stream_out *)stream;
1814
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001815 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1816 return out->compr_config.fragment_size;
1817 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001818 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07001819 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001820}
1821
1822static uint32_t out_get_channels(const struct audio_stream *stream)
1823{
1824 struct stream_out *out = (struct stream_out *)stream;
1825
1826 return out->channel_mask;
1827}
1828
1829static audio_format_t out_get_format(const struct audio_stream *stream)
1830{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001831 struct stream_out *out = (struct stream_out *)stream;
1832
1833 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001834}
1835
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001836static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001837{
1838 return -ENOSYS;
1839}
1840
1841static int out_standby(struct audio_stream *stream)
1842{
1843 struct stream_out *out = (struct stream_out *)stream;
1844 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08001845 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001846
Eric Laurent994a6932013-07-17 11:51:42 -07001847 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001848 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001849
Eric Laurenta1478072015-09-21 17:21:52 -07001850 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001851 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001852 if (adev->adm_deregister_stream)
1853 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001854 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001855 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001856 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1857 if (out->pcm) {
1858 pcm_close(out->pcm);
1859 out->pcm = NULL;
1860 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001861 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001862 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08001863 out->playback_started = false;
1864 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001865 } else {
1866 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001867 out->gapless_mdata.encoder_delay = 0;
1868 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001869 if (out->compr != NULL) {
1870 compress_close(out->compr);
1871 out->compr = NULL;
1872 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001873 }
Phil Burkbc991042017-02-24 08:06:44 -08001874 if (do_stop) {
1875 stop_output_stream(out);
1876 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001877 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001878 }
1879 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001880 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001881 return 0;
1882}
1883
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001884static int out_on_error(struct audio_stream *stream)
1885{
1886 struct stream_out *out = (struct stream_out *)stream;
1887 struct audio_device *adev = out->dev;
1888 bool do_standby = false;
1889
1890 lock_output_stream(out);
1891 if (!out->standby) {
1892 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1893 stop_compressed_output_l(out);
1894 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
1895 } else
1896 do_standby = true;
1897 }
1898 pthread_mutex_unlock(&out->lock);
1899
1900 if (do_standby)
1901 return out_standby(&out->stream.common);
1902
1903 return 0;
1904}
1905
Andy Hung7401c7c2016-09-21 12:41:21 -07001906static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001907{
Andy Hung7401c7c2016-09-21 12:41:21 -07001908 struct stream_out *out = (struct stream_out *)stream;
1909
1910 // We try to get the lock for consistency,
1911 // but it isn't necessary for these variables.
1912 // If we're not in standby, we may be blocked on a write.
1913 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
1914 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
1915 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
1916
1917 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07001918 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07001919 }
Andy Hunga452b0a2017-03-15 14:51:15 -07001920
1921 // dump error info
1922 (void)error_log_dump(
1923 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hungfc044e12017-03-20 09:24:22 -07001924 // dump power info (out->power_log may be null)
Andy Hung62c9b882017-03-22 16:43:42 -07001925 (void)power_log_dump(
1926 out->power_log, fd, " " /* prefix */, POWER_LOG_LINES, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001927 return 0;
1928}
1929
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001930static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1931{
1932 int ret = 0;
1933 char value[32];
1934 struct compr_gapless_mdata tmp_mdata;
1935
1936 if (!out || !parms) {
1937 return -EINVAL;
1938 }
1939
1940 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1941 if (ret >= 0) {
1942 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
1943 } else {
1944 return -EINVAL;
1945 }
1946
1947 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1948 if (ret >= 0) {
1949 tmp_mdata.encoder_padding = atoi(value);
1950 } else {
1951 return -EINVAL;
1952 }
1953
1954 out->gapless_mdata = tmp_mdata;
1955 out->send_new_metadata = 1;
1956 ALOGV("%s new encoder delay %u and padding %u", __func__,
1957 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1958
1959 return 0;
1960}
1961
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001962static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1963{
1964 return out == adev->primary_output || out == adev->voice_tx_output;
1965}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001966
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001967static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1968{
1969 struct stream_out *out = (struct stream_out *)stream;
1970 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001971 struct audio_usecase *usecase;
1972 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001973 struct str_parms *parms;
1974 char value[32];
1975 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001976 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07001977 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001978
Eric Laurent2e140aa2016-06-30 17:14:46 -07001979 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001980 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001981 parms = str_parms_create_str(kvpairs);
1982 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1983 if (ret >= 0) {
1984 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07001985 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001986 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001987
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001988 /*
1989 * When HDMI cable is unplugged the music playback is paused and
1990 * the policy manager sends routing=0. But the audioflinger
1991 * continues to write data until standby time (3sec).
1992 * As the HDMI core is turned off, the write gets blocked.
1993 * Avoid this by routing audio to speaker until standby.
1994 */
1995 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
1996 val == AUDIO_DEVICE_NONE) {
1997 val = AUDIO_DEVICE_OUT_SPEAKER;
1998 }
1999
2000 /*
2001 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002002 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002003 * the select_devices(). But how do we undo this?
2004 *
2005 * For example, music playback is active on headset (deep-buffer usecase)
2006 * and if we go to ringtones and select a ringtone, low-latency usecase
2007 * will be started on headset+speaker. As we can't enable headset+speaker
2008 * and headset devices at the same time, select_devices() switches the music
2009 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2010 * So when the ringtone playback is completed, how do we undo the same?
2011 *
2012 * We are relying on the out_set_parameters() call on deep-buffer output,
2013 * once the ringtone playback is ended.
2014 * NOTE: We should not check if the current devices are same as new devices.
2015 * Because select_devices() must be called to switch back the music
2016 * playback to headset.
2017 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002018 audio_devices_t new_dev = val;
2019 if (new_dev != AUDIO_DEVICE_NONE) {
2020 bool same_dev = out->devices == new_dev;
2021 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002022
Eric Laurenta7657192014-10-09 21:09:33 -07002023 if (output_drives_call(adev, out)) {
2024 if (!voice_is_in_call(adev)) {
2025 if (adev->mode == AUDIO_MODE_IN_CALL) {
2026 adev->current_call_output = out;
2027 ret = voice_start_call(adev);
2028 }
2029 } else {
2030 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002031 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002032 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002033 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002034
2035 if (!out->standby) {
2036 if (!same_dev) {
2037 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002038 // inform adm before actual routing to prevent glitches.
2039 if (adev->adm_on_routing_change) {
2040 adev->adm_on_routing_change(adev->adm_data,
2041 out->handle);
2042 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002043 }
2044 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002045 audio_extn_tfa_98xx_update();
vivek mehta0d3637a2016-07-24 09:32:02 -07002046 }
2047
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002048 }
2049
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002050 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002051 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002052
2053 /*handles device and call state changes*/
2054 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002055 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002056
2057 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2058 parse_compress_metadata(out, parms);
2059 }
2060
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002061 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002062 ALOGV("%s: exit: code(%d)", __func__, status);
2063 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002064}
2065
2066static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2067{
2068 struct stream_out *out = (struct stream_out *)stream;
2069 struct str_parms *query = str_parms_create_str(keys);
2070 char *str;
2071 char value[256];
2072 struct str_parms *reply = str_parms_create();
2073 size_t i, j;
2074 int ret;
2075 bool first = true;
Eric Laurent994a6932013-07-17 11:51:42 -07002076 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002077 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2078 if (ret >= 0) {
2079 value[0] = '\0';
2080 i = 0;
2081 while (out->supported_channel_masks[i] != 0) {
2082 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2083 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2084 if (!first) {
2085 strcat(value, "|");
2086 }
2087 strcat(value, out_channels_name_to_enum_table[j].name);
2088 first = false;
2089 break;
2090 }
2091 }
2092 i++;
2093 }
2094 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2095 str = str_parms_to_str(reply);
2096 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002097 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002098 }
2099 str_parms_destroy(query);
2100 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002101 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002102 return str;
2103}
2104
2105static uint32_t out_get_latency(const struct audio_stream_out *stream)
2106{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002107 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002108 struct stream_out *out = (struct stream_out *)stream;
2109
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002110 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2111 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002112 else if ((out->realtime) ||
2113 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002114 // since the buffer won't be filled up faster than realtime,
2115 // return a smaller number
2116 period_ms = (out->af_period_multiplier * out->config.period_size *
2117 1000) / (out->config.rate);
2118 hw_delay = platform_render_latency(out->usecase)/1000;
2119 return period_ms + hw_delay;
2120 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002121
2122 return (out->config.period_count * out->config.period_size * 1000) /
2123 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002124}
2125
2126static int out_set_volume(struct audio_stream_out *stream, float left,
2127 float right)
2128{
Eric Laurenta9024de2013-04-04 09:19:12 -07002129 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002130 int volume[2];
2131
Eric Laurenta9024de2013-04-04 09:19:12 -07002132 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2133 /* only take left channel into account: the API is for stereo anyway */
2134 out->muted = (left == 0.0f);
2135 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002136 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2137 const char *mixer_ctl_name = "Compress Playback Volume";
2138 struct audio_device *adev = out->dev;
2139 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002140 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2141 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002142 /* try with the control based on device id */
2143 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2144 PCM_PLAYBACK);
2145 char ctl_name[128] = {0};
2146 snprintf(ctl_name, sizeof(ctl_name),
2147 "Compress Playback %d Volume", pcm_device_id);
2148 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2149 if (!ctl) {
2150 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2151 return -EINVAL;
2152 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002153 }
2154 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2155 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2156 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2157 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002158 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002159
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002160 return -ENOSYS;
2161}
2162
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002163// note: this call is safe only if the stream_cb is
2164// removed first in close_output_stream (as is done now).
2165static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2166{
2167 if (!stream || !parms)
2168 return;
2169
2170 struct stream_out *out = (struct stream_out *)stream;
2171 struct audio_device *adev = out->dev;
2172
2173 card_status_t status;
2174 int card;
2175 if (parse_snd_card_status(parms, &card, &status) < 0)
2176 return;
2177
2178 pthread_mutex_lock(&adev->lock);
2179 bool valid_cb = (card == adev->snd_card);
2180 pthread_mutex_unlock(&adev->lock);
2181
2182 if (!valid_cb)
2183 return;
2184
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002185 lock_output_stream(out);
2186 if (out->card_status != status)
2187 out->card_status = status;
2188 pthread_mutex_unlock(&out->lock);
2189
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002190 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2191 use_case_table[out->usecase],
2192 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2193
2194 if (status == CARD_STATUS_OFFLINE)
2195 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002196
2197 return;
2198}
2199
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002200#ifdef NO_AUDIO_OUT
2201static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002202 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002203{
2204 struct stream_out *out = (struct stream_out *)stream;
2205
2206 /* No Output device supported other than BT for playback.
2207 * Sleep for the amount of buffer duration
2208 */
Eric Laurenta1478072015-09-21 17:21:52 -07002209 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002210 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2211 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002212 out_get_sample_rate(&out->stream.common));
2213 pthread_mutex_unlock(&out->lock);
2214 return bytes;
2215}
2216#endif
2217
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002218static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2219 size_t bytes)
2220{
2221 struct stream_out *out = (struct stream_out *)stream;
2222 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002223 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002224 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002225
Eric Laurenta1478072015-09-21 17:21:52 -07002226 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002227 // this is always nonzero
2228 const int frame_size = audio_stream_out_frame_size(stream);
2229
Eric Laurent0e46adf2016-12-16 12:49:24 -08002230 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2231 error_code = ERROR_CODE_WRITE;
2232 goto exit;
2233 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002234 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002235 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002236 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002237 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002238 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002239 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002240 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002241 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002242 goto exit;
2243 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002244
2245 if (last_known_cal_step != -1) {
2246 ALOGD("%s: retry previous failed cal level set", __func__);
2247 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2248 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002249 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002250
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002251 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002252 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002253 if (out->send_new_metadata) {
2254 ALOGVV("send new gapless metadata");
2255 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2256 out->send_new_metadata = 0;
2257 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002258 unsigned int avail;
2259 struct timespec tstamp;
2260 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2261 /* Do not limit write size if the available frames count is unknown */
2262 if (ret != 0) {
2263 avail = bytes;
2264 }
2265 if (avail == 0) {
2266 ret = 0;
2267 } else {
2268 if (avail > bytes) {
2269 avail = bytes;
2270 }
2271 ret = compress_write(out->compr, buffer, avail);
2272 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2273 __func__, avail, ret);
2274 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002275
Eric Laurent6e895242013-09-05 16:10:57 -07002276 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002277 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2278 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002279 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002280 compress_start(out->compr);
2281 out->playback_started = 1;
2282 out->offload_state = OFFLOAD_STATE_PLAYING;
2283 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002284 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002285 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002286 } else {
2287 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002288 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002289 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002290 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002291 return ret;
2292 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002293 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002294 if (out->pcm) {
2295 if (out->muted)
2296 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002297
Eric Laurent0e46adf2016-12-16 12:49:24 -08002298 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002299
Haynes Mathew George03c40102016-01-29 17:57:48 -08002300 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2301 out->config.rate;
2302 request_out_focus(out, ns);
2303
2304 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2305 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002306 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002307 else
2308 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002309
Haynes Mathew George03c40102016-01-29 17:57:48 -08002310 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002311 } else {
2312 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002313 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002314 }
2315
2316exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002317 // For PCM we always consume the buffer and return #bytes regardless of ret.
2318 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2319 out->written += bytes / (out->config.channels * sizeof(short));
2320 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002321 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07002322
2323 // only get time if needed for logging, as it is a system call on 32 bit devices.
2324 // TODO: Consider always enabling for 64 bit vDSO using compile time check on __LP64__.
2325 const int64_t now_ns = out->power_log != 0 || (ret != 0 && out->error_log != 0)
2326 ? audio_utils_get_real_time_ns() : 0;
Andy Hungfc044e12017-03-20 09:24:22 -07002327
Andy Hung7401c7c2016-09-21 12:41:21 -07002328 if (ret != 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002329 error_log_log(out->error_log, error_code, now_ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002330 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2331 ALOGE_IF(out->pcm != NULL,
2332 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hungfc044e12017-03-20 09:24:22 -07002333 sleeptime_us = bytes * 1000000LL / frame_size /
Andy Hung7401c7c2016-09-21 12:41:21 -07002334 out_get_sample_rate(&out->stream.common);
2335 // usleep not guaranteed for values over 1 second but we don't limit here.
2336 }
2337 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002338
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002339 pthread_mutex_unlock(&out->lock);
2340
2341 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002342 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002343 if (sleeptime_us != 0)
2344 usleep(sleeptime_us);
Andy Hungfc044e12017-03-20 09:24:22 -07002345 } else {
2346 // only log if the data is properly written (out->power_log may be null)
2347 power_log_log(out->power_log, buffer, bytes / frame_size, now_ns);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002348 }
2349 return bytes;
2350}
2351
2352static int out_get_render_position(const struct audio_stream_out *stream,
2353 uint32_t *dsp_frames)
2354{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002355 struct stream_out *out = (struct stream_out *)stream;
2356 *dsp_frames = 0;
2357 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002358 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002359 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002360 unsigned long frames = 0;
2361 // TODO: check return value
2362 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2363 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002364 ALOGVV("%s rendered frames %d sample_rate %d",
2365 __func__, *dsp_frames, out->sample_rate);
2366 }
2367 pthread_mutex_unlock(&out->lock);
2368 return 0;
2369 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002370 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002371}
2372
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002373static int out_add_audio_effect(const struct audio_stream *stream __unused,
2374 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002375{
2376 return 0;
2377}
2378
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002379static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2380 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002381{
2382 return 0;
2383}
2384
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002385static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2386 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002387{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002388 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002389}
2390
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002391static int out_get_presentation_position(const struct audio_stream_out *stream,
2392 uint64_t *frames, struct timespec *timestamp)
2393{
2394 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002395 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07002396 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002397
Eric Laurenta1478072015-09-21 17:21:52 -07002398 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002399
Eric Laurent949a0892013-09-20 09:20:13 -07002400 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2401 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002402 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002403 compress_get_tstamp(out->compr, &dsp_frames,
2404 &out->sample_rate);
2405 ALOGVV("%s rendered frames %ld sample_rate %d",
2406 __func__, dsp_frames, out->sample_rate);
2407 *frames = dsp_frames;
2408 ret = 0;
2409 /* this is the best we can do */
2410 clock_gettime(CLOCK_MONOTONIC, timestamp);
2411 }
2412 } else {
2413 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002414 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002415 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2416 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002417 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002418 // This adjustment accounts for buffering after app processor.
2419 // It is based on estimated DSP latency per use case, rather than exact.
2420 signed_frames -=
2421 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2422
Eric Laurent949a0892013-09-20 09:20:13 -07002423 // It would be unusual for this value to be negative, but check just in case ...
2424 if (signed_frames >= 0) {
2425 *frames = signed_frames;
2426 ret = 0;
2427 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002428 }
2429 }
2430 }
2431
2432 pthread_mutex_unlock(&out->lock);
2433
2434 return ret;
2435}
2436
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002437static int out_set_callback(struct audio_stream_out *stream,
2438 stream_callback_t callback, void *cookie)
2439{
2440 struct stream_out *out = (struct stream_out *)stream;
2441
2442 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002443 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002444 out->offload_callback = callback;
2445 out->offload_cookie = cookie;
2446 pthread_mutex_unlock(&out->lock);
2447 return 0;
2448}
2449
2450static int out_pause(struct audio_stream_out* stream)
2451{
2452 struct stream_out *out = (struct stream_out *)stream;
2453 int status = -ENOSYS;
2454 ALOGV("%s", __func__);
2455 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002456 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002457 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2458 status = compress_pause(out->compr);
2459 out->offload_state = OFFLOAD_STATE_PAUSED;
2460 }
2461 pthread_mutex_unlock(&out->lock);
2462 }
2463 return status;
2464}
2465
2466static int out_resume(struct audio_stream_out* stream)
2467{
2468 struct stream_out *out = (struct stream_out *)stream;
2469 int status = -ENOSYS;
2470 ALOGV("%s", __func__);
2471 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2472 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002473 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002474 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2475 status = compress_resume(out->compr);
2476 out->offload_state = OFFLOAD_STATE_PLAYING;
2477 }
2478 pthread_mutex_unlock(&out->lock);
2479 }
2480 return status;
2481}
2482
2483static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2484{
2485 struct stream_out *out = (struct stream_out *)stream;
2486 int status = -ENOSYS;
2487 ALOGV("%s", __func__);
2488 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002489 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002490 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2491 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2492 else
2493 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2494 pthread_mutex_unlock(&out->lock);
2495 }
2496 return status;
2497}
2498
2499static int out_flush(struct audio_stream_out* stream)
2500{
2501 struct stream_out *out = (struct stream_out *)stream;
2502 ALOGV("%s", __func__);
2503 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002504 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002505 stop_compressed_output_l(out);
2506 pthread_mutex_unlock(&out->lock);
2507 return 0;
2508 }
2509 return -ENOSYS;
2510}
2511
Eric Laurent0e46adf2016-12-16 12:49:24 -08002512static int out_stop(const struct audio_stream_out* stream)
2513{
2514 struct stream_out *out = (struct stream_out *)stream;
2515 struct audio_device *adev = out->dev;
2516 int ret = -ENOSYS;
2517
2518 ALOGV("%s", __func__);
2519 pthread_mutex_lock(&adev->lock);
2520 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2521 out->playback_started && out->pcm != NULL) {
2522 pcm_stop(out->pcm);
2523 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08002524 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002525 }
2526 pthread_mutex_unlock(&adev->lock);
2527 return ret;
2528}
2529
2530static int out_start(const struct audio_stream_out* stream)
2531{
2532 struct stream_out *out = (struct stream_out *)stream;
2533 struct audio_device *adev = out->dev;
2534 int ret = -ENOSYS;
2535
2536 ALOGV("%s", __func__);
2537 pthread_mutex_lock(&adev->lock);
2538 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2539 !out->playback_started && out->pcm != NULL) {
2540 ret = start_output_stream(out);
2541 if (ret == 0) {
2542 out->playback_started = true;
2543 }
2544 }
2545 pthread_mutex_unlock(&adev->lock);
2546 return ret;
2547}
2548
Phil Burkbc991042017-02-24 08:06:44 -08002549/*
2550 * Modify config->period_count based on min_size_frames
2551 */
2552static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
2553{
2554 int periodCountRequested = (min_size_frames + config->period_size - 1)
2555 / config->period_size;
2556 int periodCount = MMAP_PERIOD_COUNT_MIN;
2557
2558 ALOGV("%s original config.period_size = %d config.period_count = %d",
2559 __func__, config->period_size, config->period_count);
2560
2561 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
2562 periodCount *= 2;
2563 }
2564 config->period_count = periodCount;
2565
2566 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
2567}
2568
Eric Laurent0e46adf2016-12-16 12:49:24 -08002569static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2570 int32_t min_size_frames,
2571 struct audio_mmap_buffer_info *info)
2572{
2573 struct stream_out *out = (struct stream_out *)stream;
2574 struct audio_device *adev = out->dev;
2575 int ret = 0;
2576 unsigned int offset1;
2577 unsigned int frames1;
2578 const char *step = "";
2579
2580 ALOGV("%s", __func__);
2581 pthread_mutex_lock(&adev->lock);
2582
2583 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002584 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002585 ret = -EINVAL;
2586 goto exit;
2587 }
2588 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08002589 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002590 ret = -ENOSYS;
2591 goto exit;
2592 }
2593 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
2594 if (out->pcm_device_id < 0) {
2595 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2596 __func__, out->pcm_device_id, out->usecase);
2597 ret = -EINVAL;
2598 goto exit;
2599 }
Phil Burkbc991042017-02-24 08:06:44 -08002600
2601 adjust_mmap_period_count(&out->config, min_size_frames);
2602
Eric Laurent0e46adf2016-12-16 12:49:24 -08002603 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2604 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
2605 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2606 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
2607 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2608 step = "open";
2609 ret = -ENODEV;
2610 goto exit;
2611 }
2612 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
2613 if (ret < 0) {
2614 step = "begin";
2615 goto exit;
2616 }
2617 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
2618 info->burst_size_frames = out->config.period_size;
2619 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
2620
2621 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
2622 info->buffer_size_frames));
2623
2624 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
2625 if (ret < 0) {
2626 step = "commit";
2627 goto exit;
2628 }
Phil Burkbc991042017-02-24 08:06:44 -08002629
2630 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002631 ret = 0;
2632
2633 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
2634 __func__, info->shared_memory_address, info->buffer_size_frames);
2635
2636exit:
2637 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002638 if (out->pcm == NULL) {
2639 ALOGE("%s: %s - %d", __func__, step, ret);
2640 } else {
2641 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08002642 pcm_close(out->pcm);
2643 out->pcm = NULL;
2644 }
2645 }
2646 pthread_mutex_unlock(&adev->lock);
2647 return ret;
2648}
2649
2650static int out_get_mmap_position(const struct audio_stream_out *stream,
2651 struct audio_mmap_position *position)
2652{
2653 struct stream_out *out = (struct stream_out *)stream;
2654 ALOGVV("%s", __func__);
2655 if (position == NULL) {
2656 return -EINVAL;
2657 }
2658 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
2659 return -ENOSYS;
2660 }
2661 if (out->pcm == NULL) {
2662 return -ENOSYS;
2663 }
2664
2665 struct timespec ts = { 0, 0 };
2666 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
2667 if (ret < 0) {
2668 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2669 return ret;
2670 }
Andy Hungfc044e12017-03-20 09:24:22 -07002671 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002672 return 0;
2673}
2674
2675
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002676/** audio_stream_in implementation **/
2677static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2678{
2679 struct stream_in *in = (struct stream_in *)stream;
2680
2681 return in->config.rate;
2682}
2683
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002684static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002685{
2686 return -ENOSYS;
2687}
2688
2689static size_t in_get_buffer_size(const struct audio_stream *stream)
2690{
2691 struct stream_in *in = (struct stream_in *)stream;
2692
Haynes Mathew George03c40102016-01-29 17:57:48 -08002693 return in->config.period_size * in->af_period_multiplier *
2694 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002695}
2696
2697static uint32_t in_get_channels(const struct audio_stream *stream)
2698{
2699 struct stream_in *in = (struct stream_in *)stream;
2700
2701 return in->channel_mask;
2702}
2703
vivek mehta4ed66e62016-04-15 23:33:34 -07002704static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002705{
vivek mehta4ed66e62016-04-15 23:33:34 -07002706 struct stream_in *in = (struct stream_in *)stream;
2707 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002708}
2709
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002710static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002711{
2712 return -ENOSYS;
2713}
2714
2715static int in_standby(struct audio_stream *stream)
2716{
2717 struct stream_in *in = (struct stream_in *)stream;
2718 struct audio_device *adev = in->dev;
2719 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08002720 bool do_stop = true;
2721
Eric Laurent994a6932013-07-17 11:51:42 -07002722 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002723
2724 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002725
2726 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08002727 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002728 audio_extn_sound_trigger_stop_lab(in);
2729 in->standby = true;
2730 }
2731
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002732 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002733 if (adev->adm_deregister_stream)
2734 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2735
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002736 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002737 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002738 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002739 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002740 in->capture_started = false;
2741 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002742 if (in->pcm) {
2743 pcm_close(in->pcm);
2744 in->pcm = NULL;
2745 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002746 adev->enable_voicerx = false;
2747 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08002748 if (do_stop) {
2749 status = stop_input_stream(in);
2750 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002751 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002752 }
2753 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002754 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002755 return status;
2756}
2757
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002758static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002759{
2760 return 0;
2761}
2762
2763static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2764{
2765 struct stream_in *in = (struct stream_in *)stream;
2766 struct audio_device *adev = in->dev;
2767 struct str_parms *parms;
2768 char *str;
2769 char value[32];
2770 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07002771 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002772
Eric Laurent994a6932013-07-17 11:51:42 -07002773 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002774 parms = str_parms_create_str(kvpairs);
2775
2776 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2777
Eric Laurenta1478072015-09-21 17:21:52 -07002778 lock_input_stream(in);
2779
Eric Laurent150dbfe2013-02-27 14:31:02 -08002780 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002781 if (ret >= 0) {
2782 val = atoi(value);
2783 /* no audio source uses val == 0 */
2784 if ((in->source != val) && (val != 0)) {
2785 in->source = val;
2786 }
2787 }
2788
2789 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07002790
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002791 if (ret >= 0) {
2792 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002793 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002794 in->device = val;
2795 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002796 if (!in->standby) {
2797 ALOGV("update input routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002798 // inform adm before actual routing to prevent glitches.
2799 if (adev->adm_on_routing_change) {
2800 adev->adm_on_routing_change(adev->adm_data,
2801 in->capture_handle);
2802 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002803 select_devices(adev, in->usecase);
2804 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002805 }
2806 }
2807
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002808 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002809 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002810
2811 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002812 ALOGV("%s: exit: status(%d)", __func__, status);
2813 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002814}
2815
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002816static char* in_get_parameters(const struct audio_stream *stream __unused,
2817 const char *keys __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002818{
2819 return strdup("");
2820}
2821
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002822static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002823{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002824 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002825}
2826
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002827static void in_snd_mon_cb(void * stream, struct str_parms * parms)
2828{
2829 if (!stream || !parms)
2830 return;
2831
2832 struct stream_in *in = (struct stream_in *)stream;
2833 struct audio_device *adev = in->dev;
2834
2835 card_status_t status;
2836 int card;
2837 if (parse_snd_card_status(parms, &card, &status) < 0)
2838 return;
2839
2840 pthread_mutex_lock(&adev->lock);
2841 bool valid_cb = (card == adev->snd_card);
2842 pthread_mutex_unlock(&adev->lock);
2843
2844 if (!valid_cb)
2845 return;
2846
2847 lock_input_stream(in);
2848 if (in->card_status != status)
2849 in->card_status = status;
2850 pthread_mutex_unlock(&in->lock);
2851
2852 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
2853 use_case_table[in->usecase],
2854 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2855
2856 // a better solution would be to report error back to AF and let
2857 // it put the stream to standby
2858 if (status == CARD_STATUS_OFFLINE)
2859 in_standby(&in->stream.common);
2860
2861 return;
2862}
2863
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002864static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2865 size_t bytes)
2866{
2867 struct stream_in *in = (struct stream_in *)stream;
2868 struct audio_device *adev = in->dev;
2869 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07002870 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002871
Eric Laurenta1478072015-09-21 17:21:52 -07002872 lock_input_stream(in);
2873
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002874 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002875 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002876 /* Read from sound trigger HAL */
2877 audio_extn_sound_trigger_read(in, buffer, bytes);
2878 pthread_mutex_unlock(&in->lock);
2879 return bytes;
2880 }
2881
Eric Laurent0e46adf2016-12-16 12:49:24 -08002882 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
2883 ret = -ENOSYS;
2884 goto exit;
2885 }
2886
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002887 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002888 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002889 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002890 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002891 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002892 goto exit;
2893 }
2894 in->standby = 0;
2895 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002896
Haynes Mathew George03c40102016-01-29 17:57:48 -08002897 //what's the duration requested by the client?
2898 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
2899 in->config.rate;
2900 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002901
Haynes Mathew George03c40102016-01-29 17:57:48 -08002902 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002903 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002904 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002905 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07002906 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002907 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002908 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002909 if (ret < 0) {
2910 ALOGE("Failed to read w/err %s", strerror(errno));
2911 ret = -errno;
2912 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002913 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
2914 if (bytes % 4 == 0) {
2915 /* data from DSP comes in 24_8 format, convert it to 8_24 */
2916 int_buf_stream = buffer;
2917 for (size_t itt=0; itt < bytes/4 ; itt++) {
2918 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07002919 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002920 } else {
2921 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
2922 ret = -EINVAL;
2923 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07002924 }
2925 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002926 }
2927
Haynes Mathew George03c40102016-01-29 17:57:48 -08002928 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002929
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002930 /*
2931 * Instead of writing zeroes here, we could trust the hardware
2932 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002933 * 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 -08002934 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002935 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002936 memset(buffer, 0, bytes);
2937
2938exit:
2939 pthread_mutex_unlock(&in->lock);
2940
2941 if (ret != 0) {
2942 in_standby(&in->stream.common);
2943 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Eric Laurentfdf296a2014-07-03 16:41:51 -07002944 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002945 in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08002946 memset(buffer, 0, bytes); // clear return data
2947 }
2948 if (bytes > 0) {
Andy Hung6ebe5962016-01-15 17:46:57 -08002949 in->frames_read += bytes / audio_stream_in_frame_size(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002950 }
2951 return bytes;
2952}
2953
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002954static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002955{
2956 return 0;
2957}
2958
Andy Hung6ebe5962016-01-15 17:46:57 -08002959static int in_get_capture_position(const struct audio_stream_in *stream,
2960 int64_t *frames, int64_t *time)
2961{
2962 if (stream == NULL || frames == NULL || time == NULL) {
2963 return -EINVAL;
2964 }
2965 struct stream_in *in = (struct stream_in *)stream;
2966 int ret = -ENOSYS;
2967
2968 lock_input_stream(in);
2969 if (in->pcm) {
2970 struct timespec timestamp;
2971 unsigned int avail;
2972 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
2973 *frames = in->frames_read + avail;
2974 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
2975 ret = 0;
2976 }
2977 }
2978 pthread_mutex_unlock(&in->lock);
2979 return ret;
2980}
2981
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002982static int add_remove_audio_effect(const struct audio_stream *stream,
2983 effect_handle_t effect,
2984 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002985{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002986 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002987 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002988 int status = 0;
2989 effect_descriptor_t desc;
2990
2991 status = (*effect)->get_descriptor(effect, &desc);
2992 if (status != 0)
2993 return status;
2994
Eric Laurenta1478072015-09-21 17:21:52 -07002995 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002996 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07002997 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07002998 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07002999 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003000 in->enable_aec != enable &&
3001 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3002 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003003 if (!enable)
3004 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003005 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3006 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3007 adev->enable_voicerx = enable;
3008 struct audio_usecase *usecase;
3009 struct listnode *node;
3010 list_for_each(node, &adev->usecase_list) {
3011 usecase = node_to_item(node, struct audio_usecase, list);
3012 if (usecase->type == PCM_PLAYBACK) {
3013 select_devices(adev, usecase->id);
3014 break;
3015 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003016 }
3017 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003018 if (!in->standby)
3019 select_devices(in->dev, in->usecase);
3020 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003021 if (in->enable_ns != enable &&
3022 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3023 in->enable_ns = enable;
3024 if (!in->standby)
3025 select_devices(in->dev, in->usecase);
3026 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003027 pthread_mutex_unlock(&in->dev->lock);
3028 pthread_mutex_unlock(&in->lock);
3029
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003030 return 0;
3031}
3032
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003033static int in_add_audio_effect(const struct audio_stream *stream,
3034 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003035{
Eric Laurent994a6932013-07-17 11:51:42 -07003036 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003037 return add_remove_audio_effect(stream, effect, true);
3038}
3039
3040static int in_remove_audio_effect(const struct audio_stream *stream,
3041 effect_handle_t effect)
3042{
Eric Laurent994a6932013-07-17 11:51:42 -07003043 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003044 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003045}
3046
Eric Laurent0e46adf2016-12-16 12:49:24 -08003047static int in_stop(const struct audio_stream_in* stream)
3048{
3049 struct stream_in *in = (struct stream_in *)stream;
3050 struct audio_device *adev = in->dev;
3051
3052 int ret = -ENOSYS;
3053 ALOGV("%s", __func__);
3054 pthread_mutex_lock(&adev->lock);
3055 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3056 in->capture_started && in->pcm != NULL) {
3057 pcm_stop(in->pcm);
3058 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003059 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003060 }
3061 pthread_mutex_unlock(&adev->lock);
3062 return ret;
3063}
3064
3065static int in_start(const struct audio_stream_in* stream)
3066{
3067 struct stream_in *in = (struct stream_in *)stream;
3068 struct audio_device *adev = in->dev;
3069 int ret = -ENOSYS;
3070
3071 ALOGV("%s in %p", __func__, in);
3072 pthread_mutex_lock(&adev->lock);
3073 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3074 !in->capture_started && in->pcm != NULL) {
3075 if (!in->capture_started) {
3076 ret = start_input_stream(in);
3077 if (ret == 0) {
3078 in->capture_started = true;
3079 }
3080 }
3081 }
3082 pthread_mutex_unlock(&adev->lock);
3083 return ret;
3084}
3085
3086static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3087 int32_t min_size_frames,
3088 struct audio_mmap_buffer_info *info)
3089{
3090 struct stream_in *in = (struct stream_in *)stream;
3091 struct audio_device *adev = in->dev;
3092 int ret = 0;
3093 unsigned int offset1;
3094 unsigned int frames1;
3095 const char *step = "";
3096
3097 pthread_mutex_lock(&adev->lock);
3098 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003099
Eric Laurent0e46adf2016-12-16 12:49:24 -08003100 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003101 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003102 ret = -EINVAL;
3103 goto exit;
3104 }
3105 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003106 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003107 ALOGV("%s in %p", __func__, in);
3108 ret = -ENOSYS;
3109 goto exit;
3110 }
3111 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3112 if (in->pcm_device_id < 0) {
3113 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3114 __func__, in->pcm_device_id, in->usecase);
3115 ret = -EINVAL;
3116 goto exit;
3117 }
Phil Burkbc991042017-02-24 08:06:44 -08003118
3119 adjust_mmap_period_count(&in->config, min_size_frames);
3120
Eric Laurent0e46adf2016-12-16 12:49:24 -08003121 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3122 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3123 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3124 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3125 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3126 step = "open";
3127 ret = -ENODEV;
3128 goto exit;
3129 }
3130
3131 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3132 if (ret < 0) {
3133 step = "begin";
3134 goto exit;
3135 }
3136 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
3137 info->burst_size_frames = in->config.period_size;
3138 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3139
3140 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(in->pcm,
3141 info->buffer_size_frames));
3142
3143 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3144 if (ret < 0) {
3145 step = "commit";
3146 goto exit;
3147 }
3148
Phil Burkbc991042017-02-24 08:06:44 -08003149 in->standby = false;
3150 ret = 0;
3151
Eric Laurent0e46adf2016-12-16 12:49:24 -08003152 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3153 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003154
3155exit:
3156 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003157 if (in->pcm == NULL) {
3158 ALOGE("%s: %s - %d", __func__, step, ret);
3159 } else {
3160 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003161 pcm_close(in->pcm);
3162 in->pcm = NULL;
3163 }
3164 }
3165 pthread_mutex_unlock(&adev->lock);
3166 return ret;
3167}
3168
3169static int in_get_mmap_position(const struct audio_stream_in *stream,
3170 struct audio_mmap_position *position)
3171{
3172 struct stream_in *in = (struct stream_in *)stream;
3173 ALOGVV("%s", __func__);
3174 if (position == NULL) {
3175 return -EINVAL;
3176 }
3177 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
3178 return -ENOSYS;
3179 }
3180 if (in->pcm == NULL) {
3181 return -ENOSYS;
3182 }
3183 struct timespec ts = { 0, 0 };
3184 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
3185 if (ret < 0) {
3186 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3187 return ret;
3188 }
Andy Hungfc044e12017-03-20 09:24:22 -07003189 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003190 return 0;
3191}
3192
3193
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003194static int adev_open_output_stream(struct audio_hw_device *dev,
3195 audio_io_handle_t handle,
3196 audio_devices_t devices,
3197 audio_output_flags_t flags,
3198 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003199 struct audio_stream_out **stream_out,
3200 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003201{
3202 struct audio_device *adev = (struct audio_device *)dev;
3203 struct stream_out *out;
3204 int i, ret;
3205
Eric Laurent994a6932013-07-17 11:51:42 -07003206 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003207 __func__, config->sample_rate, config->channel_mask, devices, flags);
3208 *stream_out = NULL;
3209 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3210
3211 if (devices == AUDIO_DEVICE_NONE)
3212 devices = AUDIO_DEVICE_OUT_SPEAKER;
3213
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003214 out->flags = flags;
3215 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003216 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003217 out->format = config->format;
3218 out->sample_rate = config->sample_rate;
3219 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3220 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003221 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003222
3223 /* Init use case and pcm_config */
3224 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
Eric Laurent7f245042013-09-30 19:22:50 -07003225 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003226 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003227 pthread_mutex_lock(&adev->lock);
3228 ret = read_hdmi_channel_masks(out);
3229 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003230 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003231 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003232
3233 if (config->sample_rate == 0)
3234 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3235 if (config->channel_mask == 0)
3236 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Eric Laurentad1cec22015-12-16 10:12:27 -08003237 if (config->format == AUDIO_FORMAT_DEFAULT)
3238 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003239
3240 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003241 out->sample_rate = config->sample_rate;
Eric Laurentad1cec22015-12-16 10:12:27 -08003242 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003243 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3244 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003245 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003246 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003247 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003248 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003249 pthread_mutex_lock(&adev->lock);
3250 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3251 pthread_mutex_unlock(&adev->lock);
3252
3253 // reject offload during card offline to allow
3254 // fallback to s/w paths
3255 if (offline) {
3256 ret = -ENODEV;
3257 goto error_open;
3258 }
3259
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003260 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3261 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3262 ALOGE("%s: Unsupported Offload information", __func__);
3263 ret = -EINVAL;
3264 goto error_open;
3265 }
3266 if (!is_supported_format(config->offload_info.format)) {
3267 ALOGE("%s: Unsupported audio format", __func__);
3268 ret = -EINVAL;
3269 goto error_open;
3270 }
3271
3272 out->compr_config.codec = (struct snd_codec *)
3273 calloc(1, sizeof(struct snd_codec));
3274
3275 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3276 if (config->offload_info.channel_mask)
3277 out->channel_mask = config->offload_info.channel_mask;
3278 else if (config->channel_mask)
3279 out->channel_mask = config->channel_mask;
3280 out->format = config->offload_info.format;
3281 out->sample_rate = config->offload_info.sample_rate;
3282
3283 out->stream.set_callback = out_set_callback;
3284 out->stream.pause = out_pause;
3285 out->stream.resume = out_resume;
3286 out->stream.drain = out_drain;
3287 out->stream.flush = out_flush;
3288
3289 out->compr_config.codec->id =
3290 get_snd_codec_id(config->offload_info.format);
3291 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3292 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07003293 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003294 out->compr_config.codec->bit_rate =
3295 config->offload_info.bit_rate;
3296 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003297 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003298 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3299
3300 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3301 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003302
3303 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003304 create_offload_callback_thread(out);
3305 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3306 __func__, config->offload_info.version,
3307 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003308 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3309 if (config->sample_rate == 0)
3310 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3311 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3312 config->sample_rate != 8000) {
3313 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3314 ret = -EINVAL;
3315 goto error_open;
3316 }
3317 out->sample_rate = config->sample_rate;
3318 out->config.rate = config->sample_rate;
3319 if (config->format == AUDIO_FORMAT_DEFAULT)
3320 config->format = AUDIO_FORMAT_PCM_16_BIT;
3321 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3322 config->format = AUDIO_FORMAT_PCM_16_BIT;
3323 ret = -EINVAL;
3324 goto error_open;
3325 }
3326 out->format = config->format;
3327 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3328 out->config = pcm_config_afe_proxy_playback;
3329 adev->voice_tx_output = out;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003330 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003331 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3332 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3333 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003334 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
3335 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3336 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003337 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3338 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003339 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003340 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003341 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3342 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3343 out->config = pcm_config_mmap_playback;
3344 out->stream.start = out_start;
3345 out->stream.stop = out_stop;
3346 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3347 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003348 } else {
3349 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3350 out->config = pcm_config_low_latency;
3351 }
3352 if (config->format != audio_format_from_pcm_format(out->config.format)) {
3353 if (k_enable_extended_precision
3354 && pcm_params_format_test(adev->use_case_table[out->usecase],
3355 pcm_format_from_audio_format(config->format))) {
3356 out->config.format = pcm_format_from_audio_format(config->format);
3357 /* out->format already set to config->format */
3358 } else {
3359 /* deny the externally proposed config format
3360 * and use the one specified in audio_hw layer configuration.
3361 * Note: out->format is returned by out->stream.common.get_format()
3362 * and is used to set config->format in the code several lines below.
3363 */
3364 out->format = audio_format_from_pcm_format(out->config.format);
3365 }
3366 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003367 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003368 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07003369 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3370 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003371
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003372 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003373 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003374 adev->primary_output = out;
3375 else {
3376 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003377 ret = -EEXIST;
3378 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003379 }
3380 }
3381
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003382 /* Check if this usecase is already existing */
3383 pthread_mutex_lock(&adev->lock);
3384 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3385 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003386 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003387 ret = -EEXIST;
3388 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003389 }
3390 pthread_mutex_unlock(&adev->lock);
3391
3392 out->stream.common.get_sample_rate = out_get_sample_rate;
3393 out->stream.common.set_sample_rate = out_set_sample_rate;
3394 out->stream.common.get_buffer_size = out_get_buffer_size;
3395 out->stream.common.get_channels = out_get_channels;
3396 out->stream.common.get_format = out_get_format;
3397 out->stream.common.set_format = out_set_format;
3398 out->stream.common.standby = out_standby;
3399 out->stream.common.dump = out_dump;
3400 out->stream.common.set_parameters = out_set_parameters;
3401 out->stream.common.get_parameters = out_get_parameters;
3402 out->stream.common.add_audio_effect = out_add_audio_effect;
3403 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3404 out->stream.get_latency = out_get_latency;
3405 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003406#ifdef NO_AUDIO_OUT
3407 out->stream.write = out_write_for_no_output;
3408#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003409 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003410#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003411 out->stream.get_render_position = out_get_render_position;
3412 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003413 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003414
Eric Laurent0e46adf2016-12-16 12:49:24 -08003415 if (out->realtime)
3416 out->af_period_multiplier = af_period_multiplier;
3417 else
3418 out->af_period_multiplier = 1;
3419
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003420 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003421 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003422 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003423
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003424 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003425 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003426 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3427
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003428 config->format = out->stream.common.get_format(&out->stream.common);
3429 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3430 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3431
Andy Hunga452b0a2017-03-15 14:51:15 -07003432 out->error_log = error_log_create(
3433 ERROR_LOG_ENTRIES,
3434 1000000000 /* aggregate consecutive identical errors within one second in ns */);
3435
Andy Hungfc044e12017-03-20 09:24:22 -07003436 // power_log may be null if the format is not supported
Andy Hung9e737de2017-05-22 10:51:22 -07003437 // or not a userdebug or eng build.
3438 if (is_userdebug_or_eng_build()) {
3439 const size_t POWER_LOG_FRAMES_PER_ENTRY =
3440 (long long)config->sample_rate * POWER_LOG_SAMPLING_INTERVAL_MS / 1000;
3441
3442 out->power_log = power_log_create(
3443 config->sample_rate,
3444 audio_channel_count_from_out_mask(config->channel_mask),
3445 config->format,
3446 POWER_LOG_ENTRIES,
3447 POWER_LOG_FRAMES_PER_ENTRY);
3448 }
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003449
3450 /*
3451 By locking output stream before registering, we allow the callback
3452 to update stream's state only after stream's initial state is set to
3453 adev state.
3454 */
3455 lock_output_stream(out);
3456 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3457 pthread_mutex_lock(&adev->lock);
3458 out->card_status = adev->card_status;
3459 pthread_mutex_unlock(&adev->lock);
3460 pthread_mutex_unlock(&out->lock);
3461
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003462 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003463
Eric Laurent994a6932013-07-17 11:51:42 -07003464 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003465 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003466
3467error_open:
3468 free(out);
3469 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003470 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003471 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003472}
3473
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003474static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003475 struct audio_stream_out *stream)
3476{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003477 struct stream_out *out = (struct stream_out *)stream;
3478 struct audio_device *adev = out->dev;
3479
Eric Laurent994a6932013-07-17 11:51:42 -07003480 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003481
3482 // must deregister from sndmonitor first to prevent races
3483 // between the callback and close_stream
3484 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003485 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003486 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3487 destroy_offload_callback_thread(out);
3488
3489 if (out->compr_config.codec != NULL)
3490 free(out->compr_config.codec);
3491 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003492
3493 if (adev->voice_tx_output == out)
3494 adev->voice_tx_output = NULL;
3495
Andy Hungfc044e12017-03-20 09:24:22 -07003496 power_log_destroy(out->power_log);
3497 out->power_log = NULL;
3498
Andy Hunga452b0a2017-03-15 14:51:15 -07003499 error_log_destroy(out->error_log);
3500 out->error_log = NULL;
3501
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003502 pthread_cond_destroy(&out->cond);
3503 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003504 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003505 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003506}
3507
3508static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3509{
3510 struct audio_device *adev = (struct audio_device *)dev;
3511 struct str_parms *parms;
3512 char *str;
3513 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003514 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003515 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003516 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003517
Joe Onorato188b6222016-03-01 11:02:27 -08003518 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003519
3520 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003521
3522 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003523 status = voice_set_parameters(adev, parms);
3524 if (status != 0) {
3525 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003526 }
3527
3528 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3529 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003530 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003531 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3532 adev->bluetooth_nrec = true;
3533 else
3534 adev->bluetooth_nrec = false;
3535 }
3536
3537 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3538 if (ret >= 0) {
3539 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3540 adev->screen_off = false;
3541 else
3542 adev->screen_off = true;
3543 }
3544
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003545 ret = str_parms_get_int(parms, "rotation", &val);
3546 if (ret >= 0) {
3547 bool reverse_speakers = false;
3548 switch(val) {
3549 // FIXME: note that the code below assumes that the speakers are in the correct placement
3550 // relative to the user when the device is rotated 90deg from its default rotation. This
3551 // assumption is device-specific, not platform-specific like this code.
3552 case 270:
3553 reverse_speakers = true;
3554 break;
3555 case 0:
3556 case 90:
3557 case 180:
3558 break;
3559 default:
3560 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003561 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003562 }
Eric Laurent03f09432014-03-25 18:09:11 -07003563 if (status == 0) {
Ravi Kumar Alamanda1f60cf82015-04-23 19:45:17 -07003564 platform_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003565 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003566 }
3567
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003568 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3569 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003570 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003571 }
3572
David Linee3fe402017-03-13 10:00:42 -07003573 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3574 if (ret >= 0) {
3575 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
3576 if (device == AUDIO_DEVICE_OUT_USB_DEVICE) {
3577 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3578 if (ret >= 0) {
3579 const int card = atoi(value);
3580 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, card);
3581 }
3582 } else if (device == AUDIO_DEVICE_IN_USB_DEVICE) {
3583 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3584 if (ret >= 0) {
3585 const int card = atoi(value);
3586 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, card);
3587 }
3588 }
3589 }
3590
3591 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3592 if (ret >= 0) {
3593 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
3594 if (device == AUDIO_DEVICE_OUT_USB_DEVICE) {
3595 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3596 if (ret >= 0) {
3597 const int card = atoi(value);
3598
3599 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, card);
3600 }
3601 } else if (device == AUDIO_DEVICE_IN_USB_DEVICE) {
3602 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3603 if (ret >= 0) {
3604 const int card = atoi(value);
3605 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, card);
3606 }
3607 }
3608 }
3609
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08003610 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003611done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003612 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003613 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07003614 ALOGV("%s: exit with code(%d)", __func__, status);
3615 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003616}
3617
3618static char* adev_get_parameters(const struct audio_hw_device *dev,
3619 const char *keys)
3620{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003621 struct audio_device *adev = (struct audio_device *)dev;
3622 struct str_parms *reply = str_parms_create();
3623 struct str_parms *query = str_parms_create_str(keys);
3624 char *str;
3625
3626 pthread_mutex_lock(&adev->lock);
3627
3628 voice_get_parameters(adev, query, reply);
3629 str = str_parms_to_str(reply);
3630 str_parms_destroy(query);
3631 str_parms_destroy(reply);
3632
3633 pthread_mutex_unlock(&adev->lock);
3634 ALOGV("%s: exit: returns - %s", __func__, str);
3635 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003636}
3637
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003638static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003639{
3640 return 0;
3641}
3642
Haynes Mathew George5191a852013-09-11 14:19:36 -07003643static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3644{
3645 int ret;
3646 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003647
Eric Laurent4cc4ce12014-09-10 13:21:01 -05003648 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
3649
Haynes Mathew George5191a852013-09-11 14:19:36 -07003650 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003651 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003652 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003653
Haynes Mathew George5191a852013-09-11 14:19:36 -07003654 return ret;
3655}
3656
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003657static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003658{
3659 return -ENOSYS;
3660}
3661
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003662static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3663 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003664{
3665 return -ENOSYS;
3666}
3667
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003668static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003669{
3670 return -ENOSYS;
3671}
3672
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003673static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003674{
3675 return -ENOSYS;
3676}
3677
3678static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3679{
3680 struct audio_device *adev = (struct audio_device *)dev;
3681
3682 pthread_mutex_lock(&adev->lock);
3683 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07003684 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003685 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07003686 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3687 voice_is_in_call(adev)) {
3688 voice_stop_call(adev);
3689 adev->current_call_output = NULL;
3690 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003691 }
3692 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003693
3694 audio_extn_extspk_set_mode(adev->extspk, mode);
3695
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003696 return 0;
3697}
3698
3699static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3700{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003701 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003702 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003703
Eric Laurent2bafff12016-03-17 12:17:23 -07003704 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003705 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08003706 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
3707 ret = audio_extn_hfp_set_mic_mute(adev, state);
3708 } else {
3709 ret = voice_set_mic_mute(adev, state);
3710 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003711 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00003712 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003713
3714 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003715}
3716
3717static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3718{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003719 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003720 return 0;
3721}
3722
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003723static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003724 const struct audio_config *config)
3725{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003726 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003727
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003728 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3729 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003730}
3731
3732static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003733 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003734 audio_devices_t devices,
3735 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003736 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07003737 audio_input_flags_t flags,
3738 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05003739 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003740{
3741 struct audio_device *adev = (struct audio_device *)dev;
3742 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003743 int ret = 0, buffer_size, frame_size;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003744 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003745 bool is_low_latency = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003746
Eric Laurent994a6932013-07-17 11:51:42 -07003747 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003748 *stream_in = NULL;
3749 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3750 return -EINVAL;
3751
Zheng Zhang6185d572016-12-01 20:35:17 +08003752 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 -08003753 return -EINVAL;
3754
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003755 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
3756
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003757 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003758 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003759
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003760 in->stream.common.get_sample_rate = in_get_sample_rate;
3761 in->stream.common.set_sample_rate = in_set_sample_rate;
3762 in->stream.common.get_buffer_size = in_get_buffer_size;
3763 in->stream.common.get_channels = in_get_channels;
3764 in->stream.common.get_format = in_get_format;
3765 in->stream.common.set_format = in_set_format;
3766 in->stream.common.standby = in_standby;
3767 in->stream.common.dump = in_dump;
3768 in->stream.common.set_parameters = in_set_parameters;
3769 in->stream.common.get_parameters = in_get_parameters;
3770 in->stream.common.add_audio_effect = in_add_audio_effect;
3771 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3772 in->stream.set_gain = in_set_gain;
3773 in->stream.read = in_read;
3774 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08003775 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003776
3777 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003778 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003779 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003780 in->standby = 1;
3781 in->channel_mask = config->channel_mask;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003782 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003783 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003784
vivek mehta57ff9b52016-04-28 14:13:08 -07003785 // restrict 24 bit capture for unprocessed source only
3786 // for other sources if 24 bit requested reject 24 and set 16 bit capture only
3787 if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07003788 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07003789 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
3790 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
3791 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
3792 bool ret_error = false;
3793 /* 24 bit is restricted to UNPROCESSED source only,also format supported
3794 from HAL is 8_24
3795 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
3796 8_24 return error indicating supported format is 8_24
3797 *> In case of any other source requesting 24 bit or float return error
3798 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07003799
vivek mehta57ff9b52016-04-28 14:13:08 -07003800 on error flinger will retry with supported format passed
3801 */
3802 if (source != AUDIO_SOURCE_UNPROCESSED) {
3803 config->format = AUDIO_FORMAT_PCM_16_BIT;
3804 ret_error = true;
3805 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
3806 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
3807 ret_error = true;
3808 }
3809
3810 if (ret_error) {
3811 ret = -EINVAL;
3812 goto err_open;
3813 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003814 }
3815
vivek mehta57ff9b52016-04-28 14:13:08 -07003816 in->format = config->format;
3817
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003818 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003819 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
3820 if (config->sample_rate == 0)
3821 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3822 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3823 config->sample_rate != 8000) {
3824 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3825 ret = -EINVAL;
3826 goto err_open;
3827 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003828
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003829 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3830 config->format = AUDIO_FORMAT_PCM_16_BIT;
3831 ret = -EINVAL;
3832 goto err_open;
3833 }
3834
3835 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3836 in->config = pcm_config_afe_proxy_record;
David Lin73f45252017-03-29 13:37:33 -07003837 in->af_period_multiplier = 1;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003838 } else {
3839 in->usecase = USECASE_AUDIO_RECORD;
3840 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08003841 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003842 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07003843#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003844 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07003845#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08003846 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003847 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08003848 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003849 frame_size = audio_stream_in_frame_size(&in->stream);
3850 buffer_size = get_input_buffer_size(config->sample_rate,
3851 config->format,
3852 channel_count,
3853 is_low_latency);
3854 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003855 in->config.rate = config->sample_rate;
3856 in->af_period_multiplier = 1;
3857 } else {
3858 // period size is left untouched for rt mode playback
3859 in->config = pcm_config_audio_capture_rt;
3860 in->af_period_multiplier = af_period_multiplier;
3861 }
3862 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
3863 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
3864 in->usecase = USECASE_AUDIO_RECORD_MMAP;
3865 in->config = pcm_config_mmap_capture;
3866 in->stream.start = in_start;
3867 in->stream.stop = in_stop;
3868 in->stream.create_mmap_buffer = in_create_mmap_buffer;
3869 in->stream.get_mmap_position = in_get_mmap_position;
3870 in->af_period_multiplier = 1;
3871 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
3872 } else {
3873 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003874 frame_size = audio_stream_in_frame_size(&in->stream);
3875 buffer_size = get_input_buffer_size(config->sample_rate,
3876 config->format,
3877 channel_count,
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003878 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003879 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003880 in->config.rate = config->sample_rate;
3881 in->af_period_multiplier = 1;
3882 }
3883 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
3884 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003885 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003886
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003887 in->config.channels = channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003888
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003889 /* This stream could be for sound trigger lab,
3890 get sound trigger pcm if present */
3891 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003892
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003893 lock_input_stream(in);
3894 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
3895 pthread_mutex_lock(&adev->lock);
3896 in->card_status = adev->card_status;
3897 pthread_mutex_unlock(&adev->lock);
3898 pthread_mutex_unlock(&in->lock);
3899
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003900 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003901 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003902 return 0;
3903
3904err_open:
3905 free(in);
3906 *stream_in = NULL;
3907 return ret;
3908}
3909
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003910static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003911 struct audio_stream_in *stream)
3912{
Eric Laurent994a6932013-07-17 11:51:42 -07003913 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003914
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003915 // must deregister from sndmonitor first to prevent races
3916 // between the callback and close_stream
3917 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003918 in_standby(&stream->common);
3919 free(stream);
3920
3921 return;
3922}
3923
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003924static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003925{
3926 return 0;
3927}
3928
Andy Hung31aca912014-03-20 17:14:59 -07003929/* verifies input and output devices and their capabilities.
3930 *
3931 * This verification is required when enabling extended bit-depth or
3932 * sampling rates, as not all qcom products support it.
3933 *
3934 * Suitable for calling only on initialization such as adev_open().
3935 * It fills the audio_device use_case_table[] array.
3936 *
3937 * Has a side-effect that it needs to configure audio routing / devices
3938 * in order to power up the devices and read the device parameters.
3939 * It does not acquire any hw device lock. Should restore the devices
3940 * back to "normal state" upon completion.
3941 */
3942static int adev_verify_devices(struct audio_device *adev)
3943{
3944 /* enumeration is a bit difficult because one really wants to pull
3945 * the use_case, device id, etc from the hidden pcm_device_table[].
3946 * In this case there are the following use cases and device ids.
3947 *
3948 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
3949 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
3950 * [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
3951 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
3952 * [USECASE_AUDIO_RECORD] = {0, 0},
3953 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
3954 * [USECASE_VOICE_CALL] = {2, 2},
3955 *
3956 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_MULTI_CH omitted.
3957 * USECASE_VOICE_CALL omitted, but possible for either input or output.
3958 */
3959
3960 /* should be the usecases enabled in adev_open_input_stream() */
3961 static const int test_in_usecases[] = {
3962 USECASE_AUDIO_RECORD,
3963 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
3964 };
3965 /* should be the usecases enabled in adev_open_output_stream()*/
3966 static const int test_out_usecases[] = {
3967 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
3968 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
3969 };
3970 static const usecase_type_t usecase_type_by_dir[] = {
3971 PCM_PLAYBACK,
3972 PCM_CAPTURE,
3973 };
3974 static const unsigned flags_by_dir[] = {
3975 PCM_OUT,
3976 PCM_IN,
3977 };
3978
3979 size_t i;
3980 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003981 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07003982 char info[512]; /* for possible debug info */
3983
3984 for (dir = 0; dir < 2; ++dir) {
3985 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
3986 const unsigned flags_dir = flags_by_dir[dir];
3987 const size_t testsize =
3988 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
3989 const int *testcases =
3990 dir ? test_in_usecases : test_out_usecases;
3991 const audio_devices_t audio_device =
3992 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
3993
3994 for (i = 0; i < testsize; ++i) {
3995 const audio_usecase_t audio_usecase = testcases[i];
3996 int device_id;
3997 snd_device_t snd_device;
3998 struct pcm_params **pparams;
3999 struct stream_out out;
4000 struct stream_in in;
4001 struct audio_usecase uc_info;
4002 int retval;
4003
4004 pparams = &adev->use_case_table[audio_usecase];
4005 pcm_params_free(*pparams); /* can accept null input */
4006 *pparams = NULL;
4007
4008 /* find the device ID for the use case (signed, for error) */
4009 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
4010 if (device_id < 0)
4011 continue;
4012
4013 /* prepare structures for device probing */
4014 memset(&uc_info, 0, sizeof(uc_info));
4015 uc_info.id = audio_usecase;
4016 uc_info.type = usecase_type;
4017 if (dir) {
4018 adev->active_input = &in;
4019 memset(&in, 0, sizeof(in));
4020 in.device = audio_device;
4021 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4022 uc_info.stream.in = &in;
4023 } else {
4024 adev->active_input = NULL;
4025 }
4026 memset(&out, 0, sizeof(out));
4027 out.devices = audio_device; /* only field needed in select_devices */
4028 uc_info.stream.out = &out;
4029 uc_info.devices = audio_device;
4030 uc_info.in_snd_device = SND_DEVICE_NONE;
4031 uc_info.out_snd_device = SND_DEVICE_NONE;
4032 list_add_tail(&adev->usecase_list, &uc_info.list);
4033
4034 /* select device - similar to start_(in/out)put_stream() */
4035 retval = select_devices(adev, audio_usecase);
4036 if (retval >= 0) {
4037 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4038#if LOG_NDEBUG == 0
4039 if (*pparams) {
4040 ALOGV("%s: (%s) card %d device %d", __func__,
4041 dir ? "input" : "output", card_id, device_id);
4042 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004043 } else {
4044 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4045 }
4046#endif
4047 }
4048
4049 /* deselect device - similar to stop_(in/out)put_stream() */
4050 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004051 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004052 /* 2. Disable the rx device */
4053 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004054 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004055 list_remove(&uc_info.list);
4056 }
4057 }
4058 adev->active_input = NULL; /* restore adev state */
4059 return 0;
4060}
4061
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004062static int adev_close(hw_device_t *device)
4063{
Andy Hung31aca912014-03-20 17:14:59 -07004064 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004065 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004066
4067 if (!adev)
4068 return 0;
4069
Kevin Rocarda5453442017-05-02 15:09:20 -07004070 audio_extn_snd_mon_unregister_listener(adev);
Kevin Rocard8342c2c2017-04-07 18:50:00 -07004071 audio_extn_snd_mon_deinit();
Kevin Rocarda5453442017-05-02 15:09:20 -07004072
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004073 audio_extn_tfa_98xx_deinit();
4074
vivek mehta1a9b7c02015-06-25 11:49:38 -07004075 pthread_mutex_lock(&adev_init_lock);
4076
4077 if ((--audio_device_ref_count) == 0) {
4078 audio_route_free(adev->audio_route);
4079 free(adev->snd_dev_ref_cnt);
4080 platform_deinit(adev->platform);
4081 audio_extn_extspk_deinit(adev->extspk);
4082 audio_extn_sound_trigger_deinit(adev);
4083 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4084 pcm_params_free(adev->use_case_table[i]);
4085 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004086 if (adev->adm_deinit)
4087 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004088 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004089 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004090
4091 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004092
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004093 return 0;
4094}
4095
Glenn Kasten4f993392014-05-14 07:30:48 -07004096/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4097 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4098 * just that it _might_ work.
4099 */
4100static int period_size_is_plausible_for_low_latency(int period_size)
4101{
4102 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004103 case 48:
4104 case 96:
4105 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004106 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004107 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004108 case 240:
4109 case 320:
4110 case 480:
4111 return 1;
4112 default:
4113 return 0;
4114 }
4115}
4116
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004117static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4118{
4119 int card;
4120 card_status_t status;
4121
4122 if (!parms)
4123 return;
4124
4125 if (parse_snd_card_status(parms, &card, &status) < 0)
4126 return;
4127
4128 pthread_mutex_lock(&adev->lock);
4129 bool valid_cb = (card == adev->snd_card);
4130 if (valid_cb) {
4131 if (adev->card_status != status) {
4132 adev->card_status = status;
4133 platform_snd_card_update(adev->platform, status);
4134 }
4135 }
4136 pthread_mutex_unlock(&adev->lock);
4137 return;
4138}
4139
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004140static int adev_open(const hw_module_t *module, const char *name,
4141 hw_device_t **device)
4142{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004143 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004144
Eric Laurent2bafff12016-03-17 12:17:23 -07004145 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004146 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004147 pthread_mutex_lock(&adev_init_lock);
4148 if (audio_device_ref_count != 0) {
4149 *device = &adev->device.common;
4150 audio_device_ref_count++;
4151 ALOGV("%s: returning existing instance of adev", __func__);
4152 ALOGV("%s: exit", __func__);
4153 pthread_mutex_unlock(&adev_init_lock);
4154 return 0;
4155 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004156 adev = calloc(1, sizeof(struct audio_device));
4157
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004158 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4159
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004160 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4161 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4162 adev->device.common.module = (struct hw_module_t *)module;
4163 adev->device.common.close = adev_close;
4164
4165 adev->device.init_check = adev_init_check;
4166 adev->device.set_voice_volume = adev_set_voice_volume;
4167 adev->device.set_master_volume = adev_set_master_volume;
4168 adev->device.get_master_volume = adev_get_master_volume;
4169 adev->device.set_master_mute = adev_set_master_mute;
4170 adev->device.get_master_mute = adev_get_master_mute;
4171 adev->device.set_mode = adev_set_mode;
4172 adev->device.set_mic_mute = adev_set_mic_mute;
4173 adev->device.get_mic_mute = adev_get_mic_mute;
4174 adev->device.set_parameters = adev_set_parameters;
4175 adev->device.get_parameters = adev_get_parameters;
4176 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4177 adev->device.open_output_stream = adev_open_output_stream;
4178 adev->device.close_output_stream = adev_close_output_stream;
4179 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004180
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004181 adev->device.close_input_stream = adev_close_input_stream;
4182 adev->device.dump = adev_dump;
4183
4184 /* Set the default route before the PCM stream is opened */
4185 pthread_mutex_lock(&adev->lock);
4186 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004187 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004188 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004189 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004190 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004191 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004192 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004193 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004194 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004195 pthread_mutex_unlock(&adev->lock);
4196
4197 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004198 adev->platform = platform_init(adev);
4199 if (!adev->platform) {
4200 free(adev->snd_dev_ref_cnt);
4201 free(adev);
4202 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4203 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004204 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004205 return -EINVAL;
4206 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05004207 adev->extspk = audio_extn_extspk_init(adev);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004208 audio_extn_sound_trigger_init(adev);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004209
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004210 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4211 if (adev->visualizer_lib == NULL) {
4212 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4213 } else {
4214 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4215 adev->visualizer_start_output =
4216 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4217 "visualizer_hal_start_output");
4218 adev->visualizer_stop_output =
4219 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4220 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07004221 }
4222
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004223 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4224 if (adev->offload_effects_lib == NULL) {
4225 ALOGW("%s: DLOPEN failed for %s", __func__,
4226 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4227 } else {
4228 ALOGV("%s: DLOPEN successful for %s", __func__,
4229 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4230 adev->offload_effects_start_output =
4231 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4232 "offload_effects_bundle_hal_start_output");
4233 adev->offload_effects_stop_output =
4234 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4235 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07004236 }
4237
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004238 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4239 if (adev->adm_lib == NULL) {
4240 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4241 } else {
4242 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4243 adev->adm_init = (adm_init_t)
4244 dlsym(adev->adm_lib, "adm_init");
4245 adev->adm_deinit = (adm_deinit_t)
4246 dlsym(adev->adm_lib, "adm_deinit");
4247 adev->adm_register_input_stream = (adm_register_input_stream_t)
4248 dlsym(adev->adm_lib, "adm_register_input_stream");
4249 adev->adm_register_output_stream = (adm_register_output_stream_t)
4250 dlsym(adev->adm_lib, "adm_register_output_stream");
4251 adev->adm_deregister_stream = (adm_deregister_stream_t)
4252 dlsym(adev->adm_lib, "adm_deregister_stream");
4253 adev->adm_request_focus = (adm_request_focus_t)
4254 dlsym(adev->adm_lib, "adm_request_focus");
4255 adev->adm_abandon_focus = (adm_abandon_focus_t)
4256 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08004257 adev->adm_set_config = (adm_set_config_t)
4258 dlsym(adev->adm_lib, "adm_set_config");
4259 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4260 dlsym(adev->adm_lib, "adm_request_focus_v2");
4261 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4262 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4263 adev->adm_on_routing_change = (adm_on_routing_change_t)
4264 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004265 }
4266
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004267 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004268 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004269
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004270 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004271
Andy Hung31aca912014-03-20 17:14:59 -07004272 if (k_enable_extended_precision)
4273 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004274
Glenn Kasten4f993392014-05-14 07:30:48 -07004275 char value[PROPERTY_VALUE_MAX];
4276 int trial;
4277 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4278 trial = atoi(value);
4279 if (period_size_is_plausible_for_low_latency(trial)) {
4280 pcm_config_low_latency.period_size = trial;
4281 pcm_config_low_latency.start_threshold = trial / 4;
4282 pcm_config_low_latency.avail_min = trial / 4;
4283 configured_low_latency_capture_period_size = trial;
4284 }
4285 }
4286 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4287 trial = atoi(value);
4288 if (period_size_is_plausible_for_low_latency(trial)) {
4289 configured_low_latency_capture_period_size = trial;
4290 }
4291 }
4292
Yamit Mehtae3b99562016-09-16 22:44:00 +05304293 audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004294 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004295
4296 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4297 af_period_multiplier = atoi(value);
4298 if (af_period_multiplier < 0) {
4299 af_period_multiplier = 2;
4300 } else if (af_period_multiplier > 4) {
4301 af_period_multiplier = 4;
4302 }
4303 ALOGV("new period_multiplier = %d", af_period_multiplier);
4304 }
4305
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004306 audio_extn_tfa_98xx_init(adev);
4307
vivek mehta1a9b7c02015-06-25 11:49:38 -07004308 pthread_mutex_unlock(&adev_init_lock);
4309
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004310 if (adev->adm_init)
4311 adev->adm_data = adev->adm_init();
4312
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004313 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004314 audio_extn_snd_mon_init();
4315 pthread_mutex_lock(&adev->lock);
4316 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
4317 adev->card_status = CARD_STATUS_ONLINE;
4318 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004319
Eric Laurent2bafff12016-03-17 12:17:23 -07004320 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004321 return 0;
4322}
4323
4324static struct hw_module_methods_t hal_module_methods = {
4325 .open = adev_open,
4326};
4327
4328struct audio_module HAL_MODULE_INFO_SYM = {
4329 .common = {
4330 .tag = HARDWARE_MODULE_TAG,
4331 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4332 .hal_api_version = HARDWARE_HAL_API_VERSION,
4333 .id = AUDIO_HARDWARE_MODULE_ID,
4334 .name = "QCOM Audio HAL",
4335 .author = "Code Aurora Forum",
4336 .methods = &hal_module_methods,
4337 },
4338};