blob: ba2d9099d6123c6b726ffd04ec5bc3bd6050faaa [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",
vivek mehta781065c2017-04-04 12:55:01 -0700256
257 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
258 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
259 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
260
Eric Laurentb23d5282013-05-14 15:27:20 -0700261};
262
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800263
264#define STRING_TO_ENUM(string) { #string, string }
265
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800266struct string_to_enum {
267 const char *name;
268 uint32_t value;
269};
270
271static const struct string_to_enum out_channels_name_to_enum_table[] = {
272 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
273 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
274 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
275};
276
Haynes Mathew George5191a852013-09-11 14:19:36 -0700277static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700278static struct audio_device *adev = NULL;
279static pthread_mutex_t adev_init_lock;
280static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700281//cache last MBDRC cal step level
282static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700283
Haynes Mathew George03c40102016-01-29 17:57:48 -0800284static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
285 int flags __unused)
286{
287 int dir = 0;
288 switch (uc_id) {
289 case USECASE_AUDIO_RECORD_LOW_LATENCY:
290 dir = 1;
291 case USECASE_AUDIO_PLAYBACK_ULL:
292 break;
293 default:
294 return false;
295 }
296
297 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
298 PCM_PLAYBACK : PCM_CAPTURE);
299 if (adev->adm_is_noirq_avail)
300 return adev->adm_is_noirq_avail(adev->adm_data,
301 adev->snd_card, dev_id, dir);
302 return false;
303}
304
305static void register_out_stream(struct stream_out *out)
306{
307 struct audio_device *adev = out->dev;
308 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
309 return;
310
311 if (!adev->adm_register_output_stream)
312 return;
313
314 adev->adm_register_output_stream(adev->adm_data,
315 out->handle,
316 out->flags);
317
318 if (!adev->adm_set_config)
319 return;
320
321 if (out->realtime) {
322 adev->adm_set_config(adev->adm_data,
323 out->handle,
324 out->pcm, &out->config);
325 }
326}
327
328static void register_in_stream(struct stream_in *in)
329{
330 struct audio_device *adev = in->dev;
331 if (!adev->adm_register_input_stream)
332 return;
333
334 adev->adm_register_input_stream(adev->adm_data,
335 in->capture_handle,
336 in->flags);
337
338 if (!adev->adm_set_config)
339 return;
340
341 if (in->realtime) {
342 adev->adm_set_config(adev->adm_data,
343 in->capture_handle,
344 in->pcm,
345 &in->config);
346 }
347}
348
349static void request_out_focus(struct stream_out *out, long ns)
350{
351 struct audio_device *adev = out->dev;
352
353 if (out->routing_change) {
354 out->routing_change = false;
355 if (adev->adm_on_routing_change)
356 adev->adm_on_routing_change(adev->adm_data, out->handle);
357 }
358
359 if (adev->adm_request_focus_v2) {
360 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
361 } else if (adev->adm_request_focus) {
362 adev->adm_request_focus(adev->adm_data, out->handle);
363 }
364}
365
366static void request_in_focus(struct stream_in *in, long ns)
367{
368 struct audio_device *adev = in->dev;
369
370 if (in->routing_change) {
371 in->routing_change = false;
372 if (adev->adm_on_routing_change)
373 adev->adm_on_routing_change(adev->adm_data, in->capture_handle);
374 }
375
376 if (adev->adm_request_focus_v2) {
377 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
378 } else if (adev->adm_request_focus) {
379 adev->adm_request_focus(adev->adm_data, in->capture_handle);
380 }
381}
382
383static void release_out_focus(struct stream_out *out, long ns __unused)
384{
385 struct audio_device *adev = out->dev;
386
387 if (adev->adm_abandon_focus)
388 adev->adm_abandon_focus(adev->adm_data, out->handle);
389}
390
391static void release_in_focus(struct stream_in *in, long ns __unused)
392{
393 struct audio_device *adev = in->dev;
394 if (adev->adm_abandon_focus)
395 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
396}
397
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700398static int parse_snd_card_status(struct str_parms * parms, int * card,
399 card_status_t * status)
400{
401 char value[32]={0};
402 char state[32]={0};
403
404 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
405
406 if (ret < 0)
407 return -1;
408
409 // sscanf should be okay as value is of max length 32.
410 // same as sizeof state.
411 if (sscanf(value, "%d,%s", card, state) < 2)
412 return -1;
413
414 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
415 CARD_STATUS_OFFLINE;
416 return 0;
417}
418
vivek mehta1a9b7c02015-06-25 11:49:38 -0700419__attribute__ ((visibility ("default")))
420bool audio_hw_send_gain_dep_calibration(int level) {
421 bool ret_val = false;
422 ALOGV("%s: enter ... ", __func__);
423
424 pthread_mutex_lock(&adev_init_lock);
425
426 if (adev != NULL && adev->platform != NULL) {
427 pthread_mutex_lock(&adev->lock);
428 ret_val = platform_send_gain_dep_cal(adev->platform, level);
429 pthread_mutex_unlock(&adev->lock);
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700430
431 // if cal set fails, cache level info
432 // if cal set succeds, reset known last cal set
433 if (!ret_val)
434 last_known_cal_step = level;
435 else if (last_known_cal_step != -1)
436 last_known_cal_step = -1;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700437 } else {
438 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
439 }
440
441 pthread_mutex_unlock(&adev_init_lock);
442
443 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
444 return ret_val;
445}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700446
vivek mehtaa8d7c922016-05-25 14:40:44 -0700447__attribute__ ((visibility ("default")))
448int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
449 int table_size) {
450 int ret_val = 0;
451 ALOGV("%s: enter ... ", __func__);
452
453 pthread_mutex_lock(&adev_init_lock);
454 if (adev == NULL) {
455 ALOGW("%s: adev is NULL .... ", __func__);
456 goto done;
457 }
458
459 pthread_mutex_lock(&adev->lock);
460 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
461 pthread_mutex_unlock(&adev->lock);
462done:
463 pthread_mutex_unlock(&adev_init_lock);
464 ALOGV("%s: exit ... ", __func__);
465 return ret_val;
466}
467
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700468static bool is_supported_format(audio_format_t format)
469{
Eric Laurent8251ac82014-07-23 11:00:25 -0700470 switch (format) {
471 case AUDIO_FORMAT_MP3:
472 case AUDIO_FORMAT_AAC_LC:
473 case AUDIO_FORMAT_AAC_HE_V1:
474 case AUDIO_FORMAT_AAC_HE_V2:
475 return true;
476 default:
477 break;
478 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700479 return false;
480}
481
Haynes Mathew George03c40102016-01-29 17:57:48 -0800482static inline bool is_mmap_usecase(audio_usecase_t uc_id)
483{
484 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
485 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
486}
487
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700488static int get_snd_codec_id(audio_format_t format)
489{
490 int id = 0;
491
Eric Laurent8251ac82014-07-23 11:00:25 -0700492 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700493 case AUDIO_FORMAT_MP3:
494 id = SND_AUDIOCODEC_MP3;
495 break;
496 case AUDIO_FORMAT_AAC:
497 id = SND_AUDIOCODEC_AAC;
498 break;
499 default:
500 ALOGE("%s: Unsupported audio format", __func__);
501 }
502
503 return id;
504}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800505
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800506static int audio_ssr_status(struct audio_device *adev)
507{
508 int ret = 0;
509 struct mixer_ctl *ctl;
510 const char *mixer_ctl_name = "Audio SSR Status";
511
512 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
513 ret = mixer_ctl_get_value(ctl, 0);
514 ALOGD("%s: value: %d", __func__, ret);
515 return ret;
516}
517
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800518int enable_audio_route(struct audio_device *adev,
519 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800520{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700521 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800522 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800523
524 if (usecase == NULL)
525 return -EINVAL;
526
527 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
528
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800529 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700530 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800531 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700532 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800533
Yamit Mehtae3b99562016-09-16 22:44:00 +0530534 audio_extn_utils_send_app_type_cfg(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800535 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500536 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700537 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700538 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800539
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800540 ALOGV("%s: exit", __func__);
541 return 0;
542}
543
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800544int disable_audio_route(struct audio_device *adev,
545 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800546{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700547 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800548 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800549
550 if (usecase == NULL)
551 return -EINVAL;
552
553 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700554 if (usecase->type == PCM_CAPTURE)
555 snd_device = usecase->in_snd_device;
556 else
557 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800558 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500559 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700560 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700561 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800562
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800563 ALOGV("%s: exit", __func__);
564 return 0;
565}
566
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800567int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700568 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800569{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700570 int i, num_devices = 0;
571 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800572 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800573 if (snd_device < SND_DEVICE_MIN ||
574 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800575 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800576 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800577 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700578
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700579 platform_send_audio_calibration(adev->platform, snd_device);
580
vivek mehtade4849c2016-03-03 17:23:38 -0800581 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700582 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700583 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800584 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700585 }
586
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700587 /* due to the possibility of calibration overwrite between listen
588 and audio, notify sound trigger hal before audio calibration is sent */
589 audio_extn_sound_trigger_update_device_status(snd_device,
590 ST_EVENT_SND_DEVICE_BUSY);
591
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700592 if (audio_extn_spkr_prot_is_enabled())
593 audio_extn_spkr_prot_calib_cancel(adev);
594
zhaoyang yin4211fad2015-06-04 21:13:25 +0800595 audio_extn_dsm_feedback_enable(adev, snd_device, true);
596
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700597 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
598 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
599 audio_extn_spkr_prot_is_enabled()) {
600 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800601 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700602 }
603 if (audio_extn_spkr_prot_start_processing(snd_device)) {
604 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800605 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700606 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700607 } else if (platform_can_split_snd_device(snd_device,
608 &num_devices,
609 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700610 for (i = 0; i < num_devices; i++) {
611 enable_snd_device(adev, new_snd_devices[i]);
612 }
vivek mehtab6506412015-08-07 16:55:17 -0700613 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700614 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800615 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
616 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
617 ALOGE(" %s: Invalid sound device returned", __func__);
618 goto on_error;
619 }
Ed Tam70b5c142016-03-21 19:14:29 -0700620
Eric Laurent2e140aa2016-06-30 17:14:46 -0700621 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800622 audio_route_apply_and_update_path(adev->audio_route, device_name);
623 }
624on_success:
625 adev->snd_dev_ref_cnt[snd_device]++;
626 ret_val = 0;
627on_error:
628 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800629}
630
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800631int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700632 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800633{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700634 int i, num_devices = 0;
635 snd_device_t new_snd_devices[2];
636
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800637 if (snd_device < SND_DEVICE_MIN ||
638 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800639 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800640 return -EINVAL;
641 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700642 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
643 ALOGE("%s: device ref cnt is already 0", __func__);
644 return -EINVAL;
645 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800646 audio_extn_tfa_98xx_disable_speaker(snd_device);
647
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700648 adev->snd_dev_ref_cnt[snd_device]--;
649 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800650 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700651 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
652 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
653 audio_extn_spkr_prot_is_enabled()) {
654 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700655 } else if (platform_can_split_snd_device(snd_device,
656 &num_devices,
657 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700658 for (i = 0; i < num_devices; i++) {
659 disable_snd_device(adev, new_snd_devices[i]);
660 }
vivek mehtab6506412015-08-07 16:55:17 -0700661 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700662 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800663 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
664 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
665 ALOGE(" %s: Invalid sound device returned", __func__);
666 return -EINVAL;
667 }
668
Eric Laurent2e140aa2016-06-30 17:14:46 -0700669 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800670 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700671 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700672 audio_extn_sound_trigger_update_device_status(snd_device,
673 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700674 }
vivek mehtab6506412015-08-07 16:55:17 -0700675
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800676 return 0;
677}
678
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700679/*
680 legend:
681 uc - existing usecase
682 new_uc - new usecase
683 d1, d11, d2 - SND_DEVICE enums
684 a1, a2 - corresponding ANDROID device enums
685 B, B1, B2 - backend strings
686
687case 1
688 uc->dev d1 (a1) B1
689 new_uc->dev d1 (a1), d2 (a2) B1, B2
690
691 resolution: disable and enable uc->dev on d1
692
693case 2
694 uc->dev d1 (a1) B1
695 new_uc->dev d11 (a1) B1
696
697 resolution: need to switch uc since d1 and d11 are related
698 (e.g. speaker and voice-speaker)
699 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
700
701case 3
702 uc->dev d1 (a1) B1
703 new_uc->dev d2 (a2) B2
704
705 resolution: no need to switch uc
706
707case 4
708 uc->dev d1 (a1) B
709 new_uc->dev d2 (a2) B
710
711 resolution: disable enable uc-dev on d2 since backends match
712 we cannot enable two streams on two different devices if they
713 share the same backend. e.g. if offload is on speaker device using
714 QUAD_MI2S backend and a low-latency stream is started on voice-handset
715 using the same backend, offload must also be switched to voice-handset.
716
717case 5
718 uc->dev d1 (a1) B
719 new_uc->dev d1 (a1), d2 (a2) B
720
721 resolution: disable enable uc-dev on d2 since backends match
722 we cannot enable two streams on two different devices if they
723 share the same backend.
724
725case 6
726 uc->dev d1 a1 B1
727 new_uc->dev d2 a1 B2
728
729 resolution: no need to switch
730
731case 7
732
733 uc->dev d1 (a1), d2 (a2) B1, B2
734 new_uc->dev d1 B1
735
736 resolution: no need to switch
737
738*/
739static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
740 struct audio_usecase *new_uc,
741 snd_device_t new_snd_device)
742{
743 audio_devices_t a1 = uc->stream.out->devices;
744 audio_devices_t a2 = new_uc->stream.out->devices;
745
746 snd_device_t d1 = uc->out_snd_device;
747 snd_device_t d2 = new_snd_device;
748
749 // Treat as a special case when a1 and a2 are not disjoint
750 if ((a1 != a2) && (a1 & a2)) {
751 snd_device_t d3[2];
752 int num_devices = 0;
753 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
754 &num_devices,
755 d3);
756 if (ret < 0) {
757 if (ret != -ENOSYS) {
758 ALOGW("%s failed to split snd_device %d",
759 __func__,
760 popcount(a1) > 1 ? d1 : d2);
761 }
762 goto end;
763 }
764
765 // NB: case 7 is hypothetical and isn't a practical usecase yet.
766 // But if it does happen, we need to give priority to d2 if
767 // the combo devices active on the existing usecase share a backend.
768 // This is because we cannot have a usecase active on a combo device
769 // and a new usecase requests one device in this combo pair.
770 if (platform_check_backends_match(d3[0], d3[1])) {
771 return d2; // case 5
772 } else {
773 return d1; // case 1
774 }
775 } else {
776 if (platform_check_backends_match(d1, d2)) {
777 return d2; // case 2, 4
778 } else {
779 return d1; // case 6, 3
780 }
781 }
782
783end:
784 return d2; // return whatever was calculated before.
785}
786
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700787static void check_and_route_playback_usecases(struct audio_device *adev,
788 struct audio_usecase *uc_info,
789 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700790{
791 struct listnode *node;
792 struct audio_usecase *usecase;
793 bool switch_device[AUDIO_USECASE_MAX];
794 int i, num_uc_to_switch = 0;
795
David Linee3fe402017-03-13 10:00:42 -0700796 platform_check_and_set_playback_backend_cfg(adev, uc_info, snd_device);
797
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700798 /*
799 * This function is to make sure that all the usecases that are active on
800 * the hardware codec backend are always routed to any one device that is
801 * handled by the hardware codec.
802 * For example, if low-latency and deep-buffer usecases are currently active
803 * on speaker and out_set_parameters(headset) is received on low-latency
804 * output, then we have to make sure deep-buffer is also switched to headset,
805 * because of the limitation that both the devices cannot be enabled
806 * at the same time as they share the same backend.
807 */
808 /* Disable all the usecases on the shared backend other than the
809 specified usecase */
810 for (i = 0; i < AUDIO_USECASE_MAX; i++)
811 switch_device[i] = false;
812
813 list_for_each(node, &adev->usecase_list) {
814 usecase = node_to_item(node, struct audio_usecase, list);
815 if (usecase->type != PCM_CAPTURE &&
816 usecase != uc_info &&
817 usecase->out_snd_device != snd_device &&
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700818 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
819 platform_check_backends_match(snd_device, usecase->out_snd_device)) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700820 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
821 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700822 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700823 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700824 switch_device[usecase->id] = true;
825 num_uc_to_switch++;
826 }
827 }
828
829 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700830 list_for_each(node, &adev->usecase_list) {
831 usecase = node_to_item(node, struct audio_usecase, list);
832 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700833 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900834 }
835 }
836
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700837 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900838 list_for_each(node, &adev->usecase_list) {
839 usecase = node_to_item(node, struct audio_usecase, list);
840 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700841 d_device = derive_playback_snd_device(usecase, uc_info,
842 snd_device);
843 enable_snd_device(adev, d_device);
844 /* Update the out_snd_device before enabling the audio route */
845 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700846 }
847 }
848
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700849 /* Re-route all the usecases on the shared backend other than the
850 specified usecase to new snd devices */
851 list_for_each(node, &adev->usecase_list) {
852 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700853 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700854 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700855 }
856 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700857 }
858}
859
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700860static void check_and_route_capture_usecases(struct audio_device *adev,
861 struct audio_usecase *uc_info,
862 snd_device_t snd_device)
863{
864 struct listnode *node;
865 struct audio_usecase *usecase;
866 bool switch_device[AUDIO_USECASE_MAX];
867 int i, num_uc_to_switch = 0;
868
vivek mehta4ed66e62016-04-15 23:33:34 -0700869 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
870
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700871 /*
872 * This function is to make sure that all the active capture usecases
873 * are always routed to the same input sound device.
874 * For example, if audio-record and voice-call usecases are currently
875 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
876 * is received for voice call then we have to make sure that audio-record
877 * usecase is also switched to earpiece i.e. voice-dmic-ef,
878 * because of the limitation that two devices cannot be enabled
879 * at the same time if they share the same backend.
880 */
881 for (i = 0; i < AUDIO_USECASE_MAX; i++)
882 switch_device[i] = false;
883
884 list_for_each(node, &adev->usecase_list) {
885 usecase = node_to_item(node, struct audio_usecase, list);
886 if (usecase->type != PCM_PLAYBACK &&
887 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700888 usecase->in_snd_device != snd_device &&
889 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700890 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
891 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700892 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700893 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700894 switch_device[usecase->id] = true;
895 num_uc_to_switch++;
896 }
897 }
898
899 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700900 list_for_each(node, &adev->usecase_list) {
901 usecase = node_to_item(node, struct audio_usecase, list);
902 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700903 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700904 }
905 }
906
907 list_for_each(node, &adev->usecase_list) {
908 usecase = node_to_item(node, struct audio_usecase, list);
909 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700910 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700911 }
912 }
913
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700914 /* Re-route all the usecases on the shared backend other than the
915 specified usecase to new snd devices */
916 list_for_each(node, &adev->usecase_list) {
917 usecase = node_to_item(node, struct audio_usecase, list);
918 /* Update the in_snd_device only before enabling the audio route */
919 if (switch_device[usecase->id] ) {
920 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700921 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700922 }
923 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700924 }
925}
926
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800927/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700928static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800929{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700930 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700931 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800932
933 switch (channels) {
934 /*
935 * Do not handle stereo output in Multi-channel cases
936 * Stereo case is handled in normal playback path
937 */
938 case 6:
939 ALOGV("%s: HDMI supports 5.1", __func__);
940 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
941 break;
942 case 8:
943 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
944 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
945 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
946 break;
947 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700948 ALOGE("HDMI does not support multi channel playback");
949 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800950 break;
951 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700952 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800953}
954
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -0700955static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
956{
957 struct audio_usecase *usecase;
958 struct listnode *node;
959
960 list_for_each(node, &adev->usecase_list) {
961 usecase = node_to_item(node, struct audio_usecase, list);
962 if (usecase->type == VOICE_CALL) {
963 ALOGV("%s: usecase id %d", __func__, usecase->id);
964 return usecase->id;
965 }
966 }
967 return USECASE_INVALID;
968}
969
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800970struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
971 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700972{
973 struct audio_usecase *usecase;
974 struct listnode *node;
975
976 list_for_each(node, &adev->usecase_list) {
977 usecase = node_to_item(node, struct audio_usecase, list);
978 if (usecase->id == uc_id)
979 return usecase;
980 }
981 return NULL;
982}
983
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800984int select_devices(struct audio_device *adev,
985 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800986{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800987 snd_device_t out_snd_device = SND_DEVICE_NONE;
988 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700989 struct audio_usecase *usecase = NULL;
990 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800991 struct audio_usecase *hfp_usecase = NULL;
992 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800993 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700994 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800995
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700996 usecase = get_usecase_from_list(adev, uc_id);
997 if (usecase == NULL) {
998 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
999 return -EINVAL;
1000 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001001
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001002 if ((usecase->type == VOICE_CALL) ||
1003 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001004 out_snd_device = platform_get_output_snd_device(adev->platform,
1005 usecase->stream.out->devices);
1006 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001007 usecase->devices = usecase->stream.out->devices;
1008 } else {
1009 /*
1010 * If the voice call is active, use the sound devices of voice call usecase
1011 * so that it would not result any device switch. All the usecases will
1012 * be switched to new device when select_devices() is called for voice call
1013 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001014 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001015 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001016 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001017 vc_usecase = get_usecase_from_list(adev,
1018 get_voice_usecase_id_from_list(adev));
1019 if ((vc_usecase != NULL) &&
1020 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1021 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001022 in_snd_device = vc_usecase->in_snd_device;
1023 out_snd_device = vc_usecase->out_snd_device;
1024 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001025 } else if (audio_extn_hfp_is_active(adev)) {
1026 hfp_ucid = audio_extn_hfp_get_usecase();
1027 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1028 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1029 in_snd_device = hfp_usecase->in_snd_device;
1030 out_snd_device = hfp_usecase->out_snd_device;
1031 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001032 }
1033 if (usecase->type == PCM_PLAYBACK) {
1034 usecase->devices = usecase->stream.out->devices;
1035 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001036 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001037 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001038 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001039 if (usecase->stream.out == adev->primary_output &&
1040 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001041 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1042 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001043 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001044 select_devices(adev, adev->active_input->usecase);
1045 }
1046 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001047 } else if (usecase->type == PCM_CAPTURE) {
1048 usecase->devices = usecase->stream.in->device;
1049 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001050 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001051 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001052 if (adev->active_input &&
1053 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1054 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001055 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001056 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1057 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
1058 } else if (adev->primary_output) {
1059 out_device = adev->primary_output->devices;
1060 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001061 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001062 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001063 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001064 }
1065 }
1066
1067 if (out_snd_device == usecase->out_snd_device &&
1068 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001069 return 0;
1070 }
1071
Eric Laurent2bafff12016-03-17 12:17:23 -07001072 if (out_snd_device != SND_DEVICE_NONE &&
1073 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1074 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1075 __func__,
1076 use_case_table[uc_id],
1077 adev->last_logged_snd_device[uc_id][0],
1078 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1079 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1080 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1081 -1,
1082 out_snd_device,
1083 platform_get_snd_device_name(out_snd_device),
1084 platform_get_snd_device_acdb_id(out_snd_device));
1085 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1086 }
1087 if (in_snd_device != SND_DEVICE_NONE &&
1088 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1089 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1090 __func__,
1091 use_case_table[uc_id],
1092 adev->last_logged_snd_device[uc_id][1],
1093 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1094 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1095 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1096 -1,
1097 in_snd_device,
1098 platform_get_snd_device_name(in_snd_device),
1099 platform_get_snd_device_acdb_id(in_snd_device));
1100 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1101 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001102
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001103 /*
1104 * Limitation: While in call, to do a device switch we need to disable
1105 * and enable both RX and TX devices though one of them is same as current
1106 * device.
1107 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001108 if ((usecase->type == VOICE_CALL) &&
1109 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1110 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001111 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001112 /* Disable sidetone only if voice call already exists */
1113 if (voice_is_call_state_active(adev))
1114 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001115 }
1116
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001117 /* Disable current sound devices */
1118 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001119 disable_audio_route(adev, usecase);
1120 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001121 }
1122
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001123 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001124 disable_audio_route(adev, usecase);
1125 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001126 }
1127
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001128 /* Applicable only on the targets that has external modem.
1129 * New device information should be sent to modem before enabling
1130 * the devices to reduce in-call device switch time.
1131 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001132 if ((usecase->type == VOICE_CALL) &&
1133 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1134 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001135 status = platform_switch_voice_call_enable_device_config(adev->platform,
1136 out_snd_device,
1137 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001138 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001139
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001140 /* Enable new sound devices */
1141 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001142 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1143 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001144 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001145 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001146 }
1147
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001148 if (in_snd_device != SND_DEVICE_NONE) {
1149 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001150 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001151 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001152
Eric Laurentb23d5282013-05-14 15:27:20 -07001153 if (usecase->type == VOICE_CALL)
1154 status = platform_switch_voice_call_device_post(adev->platform,
1155 out_snd_device,
1156 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001157
sangwoo170731f2013-06-08 15:36:36 +09001158 usecase->in_snd_device = in_snd_device;
1159 usecase->out_snd_device = out_snd_device;
1160
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001161 audio_extn_tfa_98xx_set_mode();
1162
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001163 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001164
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001165 /* Applicable only on the targets that has external modem.
1166 * Enable device command should be sent to modem only after
1167 * enabling voice call mixer controls
1168 */
vivek mehta765eb642015-08-07 19:46:06 -07001169 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001170 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1171 out_snd_device,
1172 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001173 /* Enable sidetone only if voice call already exists */
1174 if (voice_is_call_state_active(adev))
1175 voice_set_sidetone(adev, out_snd_device, true);
1176 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001177
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001178 return status;
1179}
1180
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001181static int stop_input_stream(struct stream_in *in)
1182{
1183 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001184 struct audio_usecase *uc_info;
1185 struct audio_device *adev = in->dev;
1186
Eric Laurentc8400632013-02-14 19:04:54 -08001187 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001188
Eric Laurent994a6932013-07-17 11:51:42 -07001189 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001190 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001191 uc_info = get_usecase_from_list(adev, in->usecase);
1192 if (uc_info == NULL) {
1193 ALOGE("%s: Could not find the usecase (%d) in the list",
1194 __func__, in->usecase);
1195 return -EINVAL;
1196 }
1197
vivek mehta781065c2017-04-04 12:55:01 -07001198 /* Close in-call recording streams */
1199 voice_check_and_stop_incall_rec_usecase(adev, in);
1200
Eric Laurent150dbfe2013-02-27 14:31:02 -08001201 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001202 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001203
1204 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001205 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001206
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001207 list_remove(&uc_info->list);
1208 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001209
Eric Laurent994a6932013-07-17 11:51:42 -07001210 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001211 return ret;
1212}
1213
1214int start_input_stream(struct stream_in *in)
1215{
1216 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001217 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001218 struct audio_usecase *uc_info;
1219 struct audio_device *adev = in->dev;
1220
Eric Laurent994a6932013-07-17 11:51:42 -07001221 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001222
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001223 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1224 return -EIO;
1225
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001226 if (in->card_status == CARD_STATUS_OFFLINE ||
1227 adev->card_status == CARD_STATUS_OFFLINE) {
1228 ALOGW("in->card_status or adev->card_status offline, try again");
1229 ret = -EAGAIN;
1230 goto error_config;
1231 }
1232
vivek mehta781065c2017-04-04 12:55:01 -07001233 /* Check if source matches incall recording usecase criteria */
1234 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1235 if (ret)
1236 goto error_config;
1237 else
1238 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1239
Eric Laurentb23d5282013-05-14 15:27:20 -07001240 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001241 if (in->pcm_device_id < 0) {
1242 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1243 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001244 ret = -EINVAL;
1245 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001246 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001247
1248 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001249 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1250 uc_info->id = in->usecase;
1251 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001252 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001253 uc_info->devices = in->device;
1254 uc_info->in_snd_device = SND_DEVICE_NONE;
1255 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001256
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001257 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001258
1259 audio_extn_perf_lock_acquire();
1260
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001261 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001262
Eric Laurent0e46adf2016-12-16 12:49:24 -08001263 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001264 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001265 ALOGE("%s: pcm stream not ready", __func__);
1266 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001267 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001268 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001269 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001270 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1271 goto error_open;
1272 }
1273 } else {
1274 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1275 unsigned int pcm_open_retry_count = 0;
1276
1277 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1278 flags |= PCM_MMAP | PCM_NOIRQ;
1279 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1280 } else if (in->realtime) {
1281 flags |= PCM_MMAP | PCM_NOIRQ;
1282 }
1283
1284 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1285 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1286
1287 while (1) {
1288 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1289 flags, &in->config);
1290 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1291 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1292 if (in->pcm != NULL) {
1293 pcm_close(in->pcm);
1294 in->pcm = NULL;
1295 }
1296 if (pcm_open_retry_count-- == 0) {
1297 ret = -EIO;
1298 goto error_open;
1299 }
1300 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1301 continue;
1302 }
1303 break;
1304 }
1305
1306 ALOGV("%s: pcm_prepare", __func__);
1307 ret = pcm_prepare(in->pcm);
1308 if (ret < 0) {
1309 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001310 pcm_close(in->pcm);
1311 in->pcm = NULL;
1312 goto error_open;
1313 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001314 if (in->realtime) {
1315 ret = pcm_start(in->pcm);
1316 if (ret < 0) {
1317 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1318 pcm_close(in->pcm);
1319 in->pcm = NULL;
1320 goto error_open;
1321 }
1322 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001323 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001324 register_in_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001325 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001326 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001327
Eric Laurent0e46adf2016-12-16 12:49:24 -08001328 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001329
1330error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001331 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001332 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001333
1334error_config:
1335 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001336 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001337
1338 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001339}
1340
Eric Laurenta1478072015-09-21 17:21:52 -07001341void lock_input_stream(struct stream_in *in)
1342{
1343 pthread_mutex_lock(&in->pre_lock);
1344 pthread_mutex_lock(&in->lock);
1345 pthread_mutex_unlock(&in->pre_lock);
1346}
1347
1348void lock_output_stream(struct stream_out *out)
1349{
1350 pthread_mutex_lock(&out->pre_lock);
1351 pthread_mutex_lock(&out->lock);
1352 pthread_mutex_unlock(&out->pre_lock);
1353}
1354
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001355/* must be called with out->lock locked */
1356static int send_offload_cmd_l(struct stream_out* out, int command)
1357{
1358 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1359
1360 ALOGVV("%s %d", __func__, command);
1361
1362 cmd->cmd = command;
1363 list_add_tail(&out->offload_cmd_list, &cmd->node);
1364 pthread_cond_signal(&out->offload_cond);
1365 return 0;
1366}
1367
1368/* must be called iwth out->lock locked */
1369static void stop_compressed_output_l(struct stream_out *out)
1370{
1371 out->offload_state = OFFLOAD_STATE_IDLE;
1372 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001373 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001374 if (out->compr != NULL) {
1375 compress_stop(out->compr);
1376 while (out->offload_thread_blocked) {
1377 pthread_cond_wait(&out->cond, &out->lock);
1378 }
1379 }
1380}
1381
1382static void *offload_thread_loop(void *context)
1383{
1384 struct stream_out *out = (struct stream_out *) context;
1385 struct listnode *item;
1386
1387 out->offload_state = OFFLOAD_STATE_IDLE;
1388 out->playback_started = 0;
1389
1390 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1391 set_sched_policy(0, SP_FOREGROUND);
1392 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1393
1394 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001395 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001396 for (;;) {
1397 struct offload_cmd *cmd = NULL;
1398 stream_callback_event_t event;
1399 bool send_callback = false;
1400
1401 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1402 __func__, list_empty(&out->offload_cmd_list),
1403 out->offload_state);
1404 if (list_empty(&out->offload_cmd_list)) {
1405 ALOGV("%s SLEEPING", __func__);
1406 pthread_cond_wait(&out->offload_cond, &out->lock);
1407 ALOGV("%s RUNNING", __func__);
1408 continue;
1409 }
1410
1411 item = list_head(&out->offload_cmd_list);
1412 cmd = node_to_item(item, struct offload_cmd, node);
1413 list_remove(item);
1414
1415 ALOGVV("%s STATE %d CMD %d out->compr %p",
1416 __func__, out->offload_state, cmd->cmd, out->compr);
1417
1418 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1419 free(cmd);
1420 break;
1421 }
1422
1423 if (out->compr == NULL) {
1424 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001425 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001426 pthread_cond_signal(&out->cond);
1427 continue;
1428 }
1429 out->offload_thread_blocked = true;
1430 pthread_mutex_unlock(&out->lock);
1431 send_callback = false;
1432 switch(cmd->cmd) {
1433 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1434 compress_wait(out->compr, -1);
1435 send_callback = true;
1436 event = STREAM_CBK_EVENT_WRITE_READY;
1437 break;
1438 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001439 compress_next_track(out->compr);
1440 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001441 send_callback = true;
1442 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001443 /* Resend the metadata for next iteration */
1444 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001445 break;
1446 case OFFLOAD_CMD_DRAIN:
1447 compress_drain(out->compr);
1448 send_callback = true;
1449 event = STREAM_CBK_EVENT_DRAIN_READY;
1450 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001451 case OFFLOAD_CMD_ERROR:
1452 send_callback = true;
1453 event = STREAM_CBK_EVENT_ERROR;
1454 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001455 default:
1456 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1457 break;
1458 }
Eric Laurenta1478072015-09-21 17:21:52 -07001459 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001460 out->offload_thread_blocked = false;
1461 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001462 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001463 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001464 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001465 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001466 free(cmd);
1467 }
1468
1469 pthread_cond_signal(&out->cond);
1470 while (!list_empty(&out->offload_cmd_list)) {
1471 item = list_head(&out->offload_cmd_list);
1472 list_remove(item);
1473 free(node_to_item(item, struct offload_cmd, node));
1474 }
1475 pthread_mutex_unlock(&out->lock);
1476
1477 return NULL;
1478}
1479
1480static int create_offload_callback_thread(struct stream_out *out)
1481{
1482 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1483 list_init(&out->offload_cmd_list);
1484 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1485 offload_thread_loop, out);
1486 return 0;
1487}
1488
1489static int destroy_offload_callback_thread(struct stream_out *out)
1490{
Eric Laurenta1478072015-09-21 17:21:52 -07001491 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001492 stop_compressed_output_l(out);
1493 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1494
1495 pthread_mutex_unlock(&out->lock);
1496 pthread_join(out->offload_thread, (void **) NULL);
1497 pthread_cond_destroy(&out->offload_cond);
1498
1499 return 0;
1500}
1501
Eric Laurent07eeafd2013-10-06 12:52:49 -07001502static bool allow_hdmi_channel_config(struct audio_device *adev)
1503{
1504 struct listnode *node;
1505 struct audio_usecase *usecase;
1506 bool ret = true;
1507
1508 list_for_each(node, &adev->usecase_list) {
1509 usecase = node_to_item(node, struct audio_usecase, list);
1510 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1511 /*
1512 * If voice call is already existing, do not proceed further to avoid
1513 * disabling/enabling both RX and TX devices, CSD calls, etc.
1514 * Once the voice call done, the HDMI channels can be configured to
1515 * max channels of remaining use cases.
1516 */
1517 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001518 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001519 __func__);
1520 ret = false;
1521 break;
1522 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
Joe Onorato188b6222016-03-01 11:02:27 -08001523 ALOGV("%s: multi channel playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001524 "no change in HDMI channels", __func__);
1525 ret = false;
1526 break;
1527 }
1528 }
1529 }
1530 return ret;
1531}
1532
1533static int check_and_set_hdmi_channels(struct audio_device *adev,
1534 unsigned int channels)
1535{
1536 struct listnode *node;
1537 struct audio_usecase *usecase;
1538
1539 /* Check if change in HDMI channel config is allowed */
1540 if (!allow_hdmi_channel_config(adev))
1541 return 0;
1542
1543 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001544 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001545 return 0;
1546 }
1547
1548 platform_set_hdmi_channels(adev->platform, channels);
1549 adev->cur_hdmi_channels = channels;
1550
1551 /*
1552 * Deroute all the playback streams routed to HDMI so that
1553 * the back end is deactivated. Note that backend will not
1554 * be deactivated if any one stream is connected to it.
1555 */
1556 list_for_each(node, &adev->usecase_list) {
1557 usecase = node_to_item(node, struct audio_usecase, list);
1558 if (usecase->type == PCM_PLAYBACK &&
1559 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001560 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001561 }
1562 }
1563
1564 /*
1565 * Enable all the streams disabled above. Now the HDMI backend
1566 * will be activated with new channel configuration
1567 */
1568 list_for_each(node, &adev->usecase_list) {
1569 usecase = node_to_item(node, struct audio_usecase, list);
1570 if (usecase->type == PCM_PLAYBACK &&
1571 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001572 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001573 }
1574 }
1575
1576 return 0;
1577}
1578
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001579static int stop_output_stream(struct stream_out *out)
1580{
1581 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001582 struct audio_usecase *uc_info;
1583 struct audio_device *adev = out->dev;
1584
Eric Laurent994a6932013-07-17 11:51:42 -07001585 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001586 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001587 uc_info = get_usecase_from_list(adev, out->usecase);
1588 if (uc_info == NULL) {
1589 ALOGE("%s: Could not find the usecase (%d) in the list",
1590 __func__, out->usecase);
1591 return -EINVAL;
1592 }
1593
Haynes Mathew George41f86652014-06-17 14:22:15 -07001594 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1595 if (adev->visualizer_stop_output != NULL)
1596 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1597 if (adev->offload_effects_stop_output != NULL)
1598 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1599 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001600
Eric Laurent150dbfe2013-02-27 14:31:02 -08001601 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001602 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001603
1604 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001605 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001606
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001607 list_remove(&uc_info->list);
1608 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001609
Eric Laurent0499d4f2014-08-25 22:39:29 -05001610 audio_extn_extspk_update(adev->extspk);
1611
Eric Laurent07eeafd2013-10-06 12:52:49 -07001612 /* Must be called after removing the usecase from list */
1613 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1614 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1615
Eric Laurent994a6932013-07-17 11:51:42 -07001616 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001617 return ret;
1618}
1619
1620int start_output_stream(struct stream_out *out)
1621{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001622 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001623 struct audio_usecase *uc_info;
1624 struct audio_device *adev = out->dev;
1625
Eric Laurent994a6932013-07-17 11:51:42 -07001626 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001627 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001628
1629 if (out->card_status == CARD_STATUS_OFFLINE ||
1630 adev->card_status == CARD_STATUS_OFFLINE) {
1631 ALOGW("out->card_status or adev->card_status offline, try again");
1632 ret = -EAGAIN;
1633 goto error_config;
1634 }
1635
Eric Laurentb23d5282013-05-14 15:27:20 -07001636 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001637 if (out->pcm_device_id < 0) {
1638 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1639 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001640 ret = -EINVAL;
1641 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001642 }
1643
1644 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1645 uc_info->id = out->usecase;
1646 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001647 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001648 uc_info->devices = out->devices;
1649 uc_info->in_snd_device = SND_DEVICE_NONE;
1650 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001651
Eric Laurent07eeafd2013-10-06 12:52:49 -07001652 /* This must be called before adding this usecase to the list */
1653 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1654 check_and_set_hdmi_channels(adev, out->config.channels);
1655
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001656 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001657
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001658 audio_extn_perf_lock_acquire();
1659
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001660 select_devices(adev, out->usecase);
1661
Eric Laurent0499d4f2014-08-25 22:39:29 -05001662 audio_extn_extspk_update(adev->extspk);
1663
Andy Hung31aca912014-03-20 17:14:59 -07001664 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001665 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001666 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1667 out->pcm = NULL;
1668 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1669 COMPRESS_IN, &out->compr_config);
1670 if (out->compr && !is_compress_ready(out->compr)) {
1671 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1672 compress_close(out->compr);
1673 out->compr = NULL;
1674 ret = -EIO;
1675 goto error_open;
1676 }
1677 if (out->offload_callback)
1678 compress_nonblock(out->compr, out->non_blocking);
1679
1680 if (adev->visualizer_start_output != NULL)
1681 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1682 if (adev->offload_effects_start_output != NULL)
1683 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
1684 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001685 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001686 ALOGE("%s: pcm stream not ready", __func__);
1687 goto error_open;
1688 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001689 ret = pcm_start(out->pcm);
1690 if (ret < 0) {
1691 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1692 goto error_open;
1693 }
1694 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001695 unsigned int flags = PCM_OUT;
1696 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001697
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001698 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1699 flags |= PCM_MMAP | PCM_NOIRQ;
1700 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001701 } else if (out->realtime) {
1702 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001703 } else
1704 flags |= PCM_MONOTONIC;
1705
1706 while (1) {
1707 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1708 flags, &out->config);
1709 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1710 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1711 if (out->pcm != NULL) {
1712 pcm_close(out->pcm);
1713 out->pcm = NULL;
1714 }
1715 if (pcm_open_retry_count-- == 0) {
1716 ret = -EIO;
1717 goto error_open;
1718 }
1719 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1720 continue;
1721 }
1722 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001723 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001724 ALOGV("%s: pcm_prepare", __func__);
1725 if (pcm_is_ready(out->pcm)) {
1726 ret = pcm_prepare(out->pcm);
1727 if (ret < 0) {
1728 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1729 pcm_close(out->pcm);
1730 out->pcm = NULL;
1731 goto error_open;
1732 }
1733 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001734 if (out->realtime) {
1735 ret = pcm_start(out->pcm);
1736 if (ret < 0) {
1737 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1738 pcm_close(out->pcm);
1739 out->pcm = NULL;
1740 goto error_open;
1741 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001742 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001743 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001744 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001745 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001746 audio_extn_tfa_98xx_enable_speaker();
1747
Eric Laurent994a6932013-07-17 11:51:42 -07001748 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001749 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001750error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001751 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001752 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001753error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001754 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001755}
1756
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001757static int check_input_parameters(uint32_t sample_rate,
1758 audio_format_t format,
1759 int channel_count)
1760{
vivek mehta4ed66e62016-04-15 23:33:34 -07001761 if ((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT)) {
vivek mehtadae44712015-07-27 14:13:18 -07001762 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1763 return -EINVAL;
1764 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001765
vivek mehtadae44712015-07-27 14:13:18 -07001766 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > MAX_CHANNEL_COUNT)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001767 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
vivek mehtadae44712015-07-27 14:13:18 -07001768 channel_count, MIN_CHANNEL_COUNT, MAX_CHANNEL_COUNT);
1769 return -EINVAL;
1770 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001771
1772 switch (sample_rate) {
1773 case 8000:
1774 case 11025:
1775 case 12000:
1776 case 16000:
1777 case 22050:
1778 case 24000:
1779 case 32000:
1780 case 44100:
1781 case 48000:
1782 break;
1783 default:
vivek mehtadae44712015-07-27 14:13:18 -07001784 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001785 return -EINVAL;
1786 }
1787
1788 return 0;
1789}
1790
1791static size_t get_input_buffer_size(uint32_t sample_rate,
1792 audio_format_t format,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001793 int channel_count,
1794 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001795{
1796 size_t size = 0;
1797
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001798 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1799 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001800
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001801 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001802 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001803 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07001804
1805 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001806
Glenn Kasten4f993392014-05-14 07:30:48 -07001807 /* make sure the size is multiple of 32 bytes
1808 * At 48 kHz mono 16-bit PCM:
1809 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1810 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1811 */
1812 size += 0x1f;
1813 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001814
1815 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001816}
1817
1818static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1819{
1820 struct stream_out *out = (struct stream_out *)stream;
1821
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001822 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001823}
1824
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001825static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001826{
1827 return -ENOSYS;
1828}
1829
1830static size_t out_get_buffer_size(const struct audio_stream *stream)
1831{
1832 struct stream_out *out = (struct stream_out *)stream;
1833
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001834 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1835 return out->compr_config.fragment_size;
1836 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001837 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07001838 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001839}
1840
1841static uint32_t out_get_channels(const struct audio_stream *stream)
1842{
1843 struct stream_out *out = (struct stream_out *)stream;
1844
1845 return out->channel_mask;
1846}
1847
1848static audio_format_t out_get_format(const struct audio_stream *stream)
1849{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001850 struct stream_out *out = (struct stream_out *)stream;
1851
1852 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001853}
1854
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001855static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001856{
1857 return -ENOSYS;
1858}
1859
1860static int out_standby(struct audio_stream *stream)
1861{
1862 struct stream_out *out = (struct stream_out *)stream;
1863 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08001864 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001865
Eric Laurent994a6932013-07-17 11:51:42 -07001866 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001867 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001868
Eric Laurenta1478072015-09-21 17:21:52 -07001869 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001870 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001871 if (adev->adm_deregister_stream)
1872 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001873 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001874 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001875 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1876 if (out->pcm) {
1877 pcm_close(out->pcm);
1878 out->pcm = NULL;
1879 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001880 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001881 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08001882 out->playback_started = false;
1883 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001884 } else {
1885 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001886 out->gapless_mdata.encoder_delay = 0;
1887 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001888 if (out->compr != NULL) {
1889 compress_close(out->compr);
1890 out->compr = NULL;
1891 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001892 }
Phil Burkbc991042017-02-24 08:06:44 -08001893 if (do_stop) {
1894 stop_output_stream(out);
1895 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001896 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001897 }
1898 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001899 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001900 return 0;
1901}
1902
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001903static int out_on_error(struct audio_stream *stream)
1904{
1905 struct stream_out *out = (struct stream_out *)stream;
1906 struct audio_device *adev = out->dev;
1907 bool do_standby = false;
1908
1909 lock_output_stream(out);
1910 if (!out->standby) {
1911 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1912 stop_compressed_output_l(out);
1913 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
1914 } else
1915 do_standby = true;
1916 }
1917 pthread_mutex_unlock(&out->lock);
1918
1919 if (do_standby)
1920 return out_standby(&out->stream.common);
1921
1922 return 0;
1923}
1924
Andy Hung7401c7c2016-09-21 12:41:21 -07001925static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001926{
Andy Hung7401c7c2016-09-21 12:41:21 -07001927 struct stream_out *out = (struct stream_out *)stream;
1928
1929 // We try to get the lock for consistency,
1930 // but it isn't necessary for these variables.
1931 // If we're not in standby, we may be blocked on a write.
1932 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
1933 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
1934 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
1935
1936 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07001937 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07001938 }
Andy Hunga452b0a2017-03-15 14:51:15 -07001939
1940 // dump error info
1941 (void)error_log_dump(
1942 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hungfc044e12017-03-20 09:24:22 -07001943 // dump power info (out->power_log may be null)
Andy Hung62c9b882017-03-22 16:43:42 -07001944 (void)power_log_dump(
1945 out->power_log, fd, " " /* prefix */, POWER_LOG_LINES, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001946 return 0;
1947}
1948
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001949static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1950{
1951 int ret = 0;
1952 char value[32];
1953 struct compr_gapless_mdata tmp_mdata;
1954
1955 if (!out || !parms) {
1956 return -EINVAL;
1957 }
1958
1959 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1960 if (ret >= 0) {
1961 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
1962 } else {
1963 return -EINVAL;
1964 }
1965
1966 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1967 if (ret >= 0) {
1968 tmp_mdata.encoder_padding = atoi(value);
1969 } else {
1970 return -EINVAL;
1971 }
1972
1973 out->gapless_mdata = tmp_mdata;
1974 out->send_new_metadata = 1;
1975 ALOGV("%s new encoder delay %u and padding %u", __func__,
1976 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1977
1978 return 0;
1979}
1980
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001981static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1982{
1983 return out == adev->primary_output || out == adev->voice_tx_output;
1984}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001985
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001986static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1987{
1988 struct stream_out *out = (struct stream_out *)stream;
1989 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001990 struct audio_usecase *usecase;
1991 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001992 struct str_parms *parms;
1993 char value[32];
1994 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001995 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07001996 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001997
Eric Laurent2e140aa2016-06-30 17:14:46 -07001998 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001999 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002000 parms = str_parms_create_str(kvpairs);
2001 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2002 if (ret >= 0) {
2003 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07002004 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002005 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002006
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002007 /*
2008 * When HDMI cable is unplugged the music playback is paused and
2009 * the policy manager sends routing=0. But the audioflinger
2010 * continues to write data until standby time (3sec).
2011 * As the HDMI core is turned off, the write gets blocked.
2012 * Avoid this by routing audio to speaker until standby.
2013 */
2014 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2015 val == AUDIO_DEVICE_NONE) {
2016 val = AUDIO_DEVICE_OUT_SPEAKER;
2017 }
2018
2019 /*
2020 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002021 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002022 * the select_devices(). But how do we undo this?
2023 *
2024 * For example, music playback is active on headset (deep-buffer usecase)
2025 * and if we go to ringtones and select a ringtone, low-latency usecase
2026 * will be started on headset+speaker. As we can't enable headset+speaker
2027 * and headset devices at the same time, select_devices() switches the music
2028 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2029 * So when the ringtone playback is completed, how do we undo the same?
2030 *
2031 * We are relying on the out_set_parameters() call on deep-buffer output,
2032 * once the ringtone playback is ended.
2033 * NOTE: We should not check if the current devices are same as new devices.
2034 * Because select_devices() must be called to switch back the music
2035 * playback to headset.
2036 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002037 audio_devices_t new_dev = val;
2038 if (new_dev != AUDIO_DEVICE_NONE) {
2039 bool same_dev = out->devices == new_dev;
2040 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002041
Eric Laurenta7657192014-10-09 21:09:33 -07002042 if (output_drives_call(adev, out)) {
2043 if (!voice_is_in_call(adev)) {
2044 if (adev->mode == AUDIO_MODE_IN_CALL) {
2045 adev->current_call_output = out;
2046 ret = voice_start_call(adev);
2047 }
2048 } else {
2049 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002050 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002051 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002052 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002053
2054 if (!out->standby) {
2055 if (!same_dev) {
2056 ALOGV("update routing change");
2057 out->routing_change = true;
2058 }
2059 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002060 audio_extn_tfa_98xx_update();
vivek mehta0d3637a2016-07-24 09:32:02 -07002061 }
2062
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002063 }
2064
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002065 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002066 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002067
2068 /*handles device and call state changes*/
2069 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002070 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002071
2072 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2073 parse_compress_metadata(out, parms);
2074 }
2075
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002076 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002077 ALOGV("%s: exit: code(%d)", __func__, status);
2078 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002079}
2080
2081static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2082{
2083 struct stream_out *out = (struct stream_out *)stream;
2084 struct str_parms *query = str_parms_create_str(keys);
2085 char *str;
2086 char value[256];
2087 struct str_parms *reply = str_parms_create();
2088 size_t i, j;
2089 int ret;
2090 bool first = true;
Eric Laurent994a6932013-07-17 11:51:42 -07002091 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002092 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2093 if (ret >= 0) {
2094 value[0] = '\0';
2095 i = 0;
2096 while (out->supported_channel_masks[i] != 0) {
2097 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2098 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2099 if (!first) {
2100 strcat(value, "|");
2101 }
2102 strcat(value, out_channels_name_to_enum_table[j].name);
2103 first = false;
2104 break;
2105 }
2106 }
2107 i++;
2108 }
2109 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2110 str = str_parms_to_str(reply);
2111 } else {
2112 str = strdup(keys);
2113 }
2114 str_parms_destroy(query);
2115 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002116 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002117 return str;
2118}
2119
2120static uint32_t out_get_latency(const struct audio_stream_out *stream)
2121{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002122 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002123 struct stream_out *out = (struct stream_out *)stream;
2124
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002125 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2126 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002127 else if ((out->realtime) ||
2128 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002129 // since the buffer won't be filled up faster than realtime,
2130 // return a smaller number
2131 period_ms = (out->af_period_multiplier * out->config.period_size *
2132 1000) / (out->config.rate);
2133 hw_delay = platform_render_latency(out->usecase)/1000;
2134 return period_ms + hw_delay;
2135 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002136
2137 return (out->config.period_count * out->config.period_size * 1000) /
2138 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002139}
2140
2141static int out_set_volume(struct audio_stream_out *stream, float left,
2142 float right)
2143{
Eric Laurenta9024de2013-04-04 09:19:12 -07002144 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002145 int volume[2];
2146
Eric Laurenta9024de2013-04-04 09:19:12 -07002147 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2148 /* only take left channel into account: the API is for stereo anyway */
2149 out->muted = (left == 0.0f);
2150 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002151 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2152 const char *mixer_ctl_name = "Compress Playback Volume";
2153 struct audio_device *adev = out->dev;
2154 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002155 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2156 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002157 /* try with the control based on device id */
2158 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2159 PCM_PLAYBACK);
2160 char ctl_name[128] = {0};
2161 snprintf(ctl_name, sizeof(ctl_name),
2162 "Compress Playback %d Volume", pcm_device_id);
2163 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2164 if (!ctl) {
2165 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2166 return -EINVAL;
2167 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002168 }
2169 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2170 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2171 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2172 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002173 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002174
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002175 return -ENOSYS;
2176}
2177
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002178// note: this call is safe only if the stream_cb is
2179// removed first in close_output_stream (as is done now).
2180static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2181{
2182 if (!stream || !parms)
2183 return;
2184
2185 struct stream_out *out = (struct stream_out *)stream;
2186 struct audio_device *adev = out->dev;
2187
2188 card_status_t status;
2189 int card;
2190 if (parse_snd_card_status(parms, &card, &status) < 0)
2191 return;
2192
2193 pthread_mutex_lock(&adev->lock);
2194 bool valid_cb = (card == adev->snd_card);
2195 pthread_mutex_unlock(&adev->lock);
2196
2197 if (!valid_cb)
2198 return;
2199
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002200 lock_output_stream(out);
2201 if (out->card_status != status)
2202 out->card_status = status;
2203 pthread_mutex_unlock(&out->lock);
2204
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002205 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2206 use_case_table[out->usecase],
2207 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2208
2209 if (status == CARD_STATUS_OFFLINE)
2210 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002211
2212 return;
2213}
2214
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002215#ifdef NO_AUDIO_OUT
2216static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002217 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002218{
2219 struct stream_out *out = (struct stream_out *)stream;
2220
2221 /* No Output device supported other than BT for playback.
2222 * Sleep for the amount of buffer duration
2223 */
Eric Laurenta1478072015-09-21 17:21:52 -07002224 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002225 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2226 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002227 out_get_sample_rate(&out->stream.common));
2228 pthread_mutex_unlock(&out->lock);
2229 return bytes;
2230}
2231#endif
2232
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002233static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2234 size_t bytes)
2235{
2236 struct stream_out *out = (struct stream_out *)stream;
2237 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002238 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002239 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002240
Eric Laurenta1478072015-09-21 17:21:52 -07002241 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002242 // this is always nonzero
2243 const int frame_size = audio_stream_out_frame_size(stream);
2244
Eric Laurent0e46adf2016-12-16 12:49:24 -08002245 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2246 error_code = ERROR_CODE_WRITE;
2247 goto exit;
2248 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002249 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002250 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002251 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002252 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002253 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002254 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002255 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002256 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002257 goto exit;
2258 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002259
2260 if (last_known_cal_step != -1) {
2261 ALOGD("%s: retry previous failed cal level set", __func__);
2262 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2263 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002264 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002265
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002266 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002267 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002268 if (out->send_new_metadata) {
2269 ALOGVV("send new gapless metadata");
2270 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2271 out->send_new_metadata = 0;
2272 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002273 unsigned int avail;
2274 struct timespec tstamp;
2275 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2276 /* Do not limit write size if the available frames count is unknown */
2277 if (ret != 0) {
2278 avail = bytes;
2279 }
2280 if (avail == 0) {
2281 ret = 0;
2282 } else {
2283 if (avail > bytes) {
2284 avail = bytes;
2285 }
2286 ret = compress_write(out->compr, buffer, avail);
2287 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2288 __func__, avail, ret);
2289 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002290
Eric Laurent6e895242013-09-05 16:10:57 -07002291 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002292 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2293 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002294 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002295 compress_start(out->compr);
2296 out->playback_started = 1;
2297 out->offload_state = OFFLOAD_STATE_PLAYING;
2298 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002299 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002300 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002301 } else {
2302 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002303 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002304 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002305 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002306 return ret;
2307 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002308 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002309 if (out->pcm) {
2310 if (out->muted)
2311 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002312
Eric Laurent0e46adf2016-12-16 12:49:24 -08002313 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002314
Haynes Mathew George03c40102016-01-29 17:57:48 -08002315 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2316 out->config.rate;
2317 request_out_focus(out, ns);
2318
2319 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2320 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002321 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002322 else
2323 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002324
Haynes Mathew George03c40102016-01-29 17:57:48 -08002325 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002326 } else {
2327 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002328 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002329 }
2330
2331exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002332 // For PCM we always consume the buffer and return #bytes regardless of ret.
2333 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2334 out->written += bytes / (out->config.channels * sizeof(short));
2335 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002336 long long sleeptime_us = 0;
Andy Hungfc044e12017-03-20 09:24:22 -07002337 const int64_t now_ns = audio_utils_get_real_time_ns();
2338
Andy Hung7401c7c2016-09-21 12:41:21 -07002339 if (ret != 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002340 error_log_log(out->error_log, error_code, now_ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002341 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2342 ALOGE_IF(out->pcm != NULL,
2343 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hungfc044e12017-03-20 09:24:22 -07002344 sleeptime_us = bytes * 1000000LL / frame_size /
Andy Hung7401c7c2016-09-21 12:41:21 -07002345 out_get_sample_rate(&out->stream.common);
2346 // usleep not guaranteed for values over 1 second but we don't limit here.
2347 }
2348 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002349
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002350 pthread_mutex_unlock(&out->lock);
2351
2352 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002353 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002354 if (sleeptime_us != 0)
2355 usleep(sleeptime_us);
Andy Hungfc044e12017-03-20 09:24:22 -07002356 } else {
2357 // only log if the data is properly written (out->power_log may be null)
2358 power_log_log(out->power_log, buffer, bytes / frame_size, now_ns);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002359 }
2360 return bytes;
2361}
2362
2363static int out_get_render_position(const struct audio_stream_out *stream,
2364 uint32_t *dsp_frames)
2365{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002366 struct stream_out *out = (struct stream_out *)stream;
2367 *dsp_frames = 0;
2368 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002369 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002370 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002371 unsigned long frames = 0;
2372 // TODO: check return value
2373 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2374 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002375 ALOGVV("%s rendered frames %d sample_rate %d",
2376 __func__, *dsp_frames, out->sample_rate);
2377 }
2378 pthread_mutex_unlock(&out->lock);
2379 return 0;
2380 } else
2381 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002382}
2383
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002384static int out_add_audio_effect(const struct audio_stream *stream __unused,
2385 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002386{
2387 return 0;
2388}
2389
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002390static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2391 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002392{
2393 return 0;
2394}
2395
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002396static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2397 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002398{
2399 return -EINVAL;
2400}
2401
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002402static int out_get_presentation_position(const struct audio_stream_out *stream,
2403 uint64_t *frames, struct timespec *timestamp)
2404{
2405 struct stream_out *out = (struct stream_out *)stream;
Andy Hung7171da22016-03-08 16:58:42 -08002406 int ret = -EINVAL;
Eric Laurent949a0892013-09-20 09:20:13 -07002407 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002408
Eric Laurenta1478072015-09-21 17:21:52 -07002409 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002410
Eric Laurent949a0892013-09-20 09:20:13 -07002411 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2412 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002413 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002414 compress_get_tstamp(out->compr, &dsp_frames,
2415 &out->sample_rate);
2416 ALOGVV("%s rendered frames %ld sample_rate %d",
2417 __func__, dsp_frames, out->sample_rate);
2418 *frames = dsp_frames;
2419 ret = 0;
2420 /* this is the best we can do */
2421 clock_gettime(CLOCK_MONOTONIC, timestamp);
2422 }
2423 } else {
2424 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002425 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002426 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2427 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002428 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002429 // This adjustment accounts for buffering after app processor.
2430 // It is based on estimated DSP latency per use case, rather than exact.
2431 signed_frames -=
2432 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2433
Eric Laurent949a0892013-09-20 09:20:13 -07002434 // It would be unusual for this value to be negative, but check just in case ...
2435 if (signed_frames >= 0) {
2436 *frames = signed_frames;
2437 ret = 0;
2438 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002439 }
2440 }
2441 }
2442
2443 pthread_mutex_unlock(&out->lock);
2444
2445 return ret;
2446}
2447
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002448static int out_set_callback(struct audio_stream_out *stream,
2449 stream_callback_t callback, void *cookie)
2450{
2451 struct stream_out *out = (struct stream_out *)stream;
2452
2453 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002454 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002455 out->offload_callback = callback;
2456 out->offload_cookie = cookie;
2457 pthread_mutex_unlock(&out->lock);
2458 return 0;
2459}
2460
2461static int out_pause(struct audio_stream_out* stream)
2462{
2463 struct stream_out *out = (struct stream_out *)stream;
2464 int status = -ENOSYS;
2465 ALOGV("%s", __func__);
2466 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002467 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002468 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2469 status = compress_pause(out->compr);
2470 out->offload_state = OFFLOAD_STATE_PAUSED;
2471 }
2472 pthread_mutex_unlock(&out->lock);
2473 }
2474 return status;
2475}
2476
2477static int out_resume(struct audio_stream_out* stream)
2478{
2479 struct stream_out *out = (struct stream_out *)stream;
2480 int status = -ENOSYS;
2481 ALOGV("%s", __func__);
2482 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2483 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002484 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002485 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2486 status = compress_resume(out->compr);
2487 out->offload_state = OFFLOAD_STATE_PLAYING;
2488 }
2489 pthread_mutex_unlock(&out->lock);
2490 }
2491 return status;
2492}
2493
2494static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2495{
2496 struct stream_out *out = (struct stream_out *)stream;
2497 int status = -ENOSYS;
2498 ALOGV("%s", __func__);
2499 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002500 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002501 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2502 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2503 else
2504 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2505 pthread_mutex_unlock(&out->lock);
2506 }
2507 return status;
2508}
2509
2510static int out_flush(struct audio_stream_out* stream)
2511{
2512 struct stream_out *out = (struct stream_out *)stream;
2513 ALOGV("%s", __func__);
2514 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002515 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002516 stop_compressed_output_l(out);
2517 pthread_mutex_unlock(&out->lock);
2518 return 0;
2519 }
2520 return -ENOSYS;
2521}
2522
Eric Laurent0e46adf2016-12-16 12:49:24 -08002523static int out_stop(const struct audio_stream_out* stream)
2524{
2525 struct stream_out *out = (struct stream_out *)stream;
2526 struct audio_device *adev = out->dev;
2527 int ret = -ENOSYS;
2528
2529 ALOGV("%s", __func__);
2530 pthread_mutex_lock(&adev->lock);
2531 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2532 out->playback_started && out->pcm != NULL) {
2533 pcm_stop(out->pcm);
2534 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08002535 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002536 }
2537 pthread_mutex_unlock(&adev->lock);
2538 return ret;
2539}
2540
2541static int out_start(const struct audio_stream_out* stream)
2542{
2543 struct stream_out *out = (struct stream_out *)stream;
2544 struct audio_device *adev = out->dev;
2545 int ret = -ENOSYS;
2546
2547 ALOGV("%s", __func__);
2548 pthread_mutex_lock(&adev->lock);
2549 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2550 !out->playback_started && out->pcm != NULL) {
2551 ret = start_output_stream(out);
2552 if (ret == 0) {
2553 out->playback_started = true;
2554 }
2555 }
2556 pthread_mutex_unlock(&adev->lock);
2557 return ret;
2558}
2559
Phil Burkbc991042017-02-24 08:06:44 -08002560/*
2561 * Modify config->period_count based on min_size_frames
2562 */
2563static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
2564{
2565 int periodCountRequested = (min_size_frames + config->period_size - 1)
2566 / config->period_size;
2567 int periodCount = MMAP_PERIOD_COUNT_MIN;
2568
2569 ALOGV("%s original config.period_size = %d config.period_count = %d",
2570 __func__, config->period_size, config->period_count);
2571
2572 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
2573 periodCount *= 2;
2574 }
2575 config->period_count = periodCount;
2576
2577 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
2578}
2579
Eric Laurent0e46adf2016-12-16 12:49:24 -08002580static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2581 int32_t min_size_frames,
2582 struct audio_mmap_buffer_info *info)
2583{
2584 struct stream_out *out = (struct stream_out *)stream;
2585 struct audio_device *adev = out->dev;
2586 int ret = 0;
2587 unsigned int offset1;
2588 unsigned int frames1;
2589 const char *step = "";
2590
2591 ALOGV("%s", __func__);
2592 pthread_mutex_lock(&adev->lock);
2593
2594 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002595 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002596 ret = -EINVAL;
2597 goto exit;
2598 }
2599 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08002600 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002601 ret = -ENOSYS;
2602 goto exit;
2603 }
2604 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
2605 if (out->pcm_device_id < 0) {
2606 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2607 __func__, out->pcm_device_id, out->usecase);
2608 ret = -EINVAL;
2609 goto exit;
2610 }
Phil Burkbc991042017-02-24 08:06:44 -08002611
2612 adjust_mmap_period_count(&out->config, min_size_frames);
2613
Eric Laurent0e46adf2016-12-16 12:49:24 -08002614 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2615 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
2616 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2617 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
2618 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2619 step = "open";
2620 ret = -ENODEV;
2621 goto exit;
2622 }
2623 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
2624 if (ret < 0) {
2625 step = "begin";
2626 goto exit;
2627 }
2628 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
2629 info->burst_size_frames = out->config.period_size;
2630 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
2631
2632 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
2633 info->buffer_size_frames));
2634
2635 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
2636 if (ret < 0) {
2637 step = "commit";
2638 goto exit;
2639 }
Phil Burkbc991042017-02-24 08:06:44 -08002640
2641 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002642 ret = 0;
2643
2644 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
2645 __func__, info->shared_memory_address, info->buffer_size_frames);
2646
2647exit:
2648 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002649 if (out->pcm == NULL) {
2650 ALOGE("%s: %s - %d", __func__, step, ret);
2651 } else {
2652 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08002653 pcm_close(out->pcm);
2654 out->pcm = NULL;
2655 }
2656 }
2657 pthread_mutex_unlock(&adev->lock);
2658 return ret;
2659}
2660
2661static int out_get_mmap_position(const struct audio_stream_out *stream,
2662 struct audio_mmap_position *position)
2663{
2664 struct stream_out *out = (struct stream_out *)stream;
2665 ALOGVV("%s", __func__);
2666 if (position == NULL) {
2667 return -EINVAL;
2668 }
2669 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
2670 return -ENOSYS;
2671 }
2672 if (out->pcm == NULL) {
2673 return -ENOSYS;
2674 }
2675
2676 struct timespec ts = { 0, 0 };
2677 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
2678 if (ret < 0) {
2679 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2680 return ret;
2681 }
Andy Hungfc044e12017-03-20 09:24:22 -07002682 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002683 return 0;
2684}
2685
2686
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002687/** audio_stream_in implementation **/
2688static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2689{
2690 struct stream_in *in = (struct stream_in *)stream;
2691
2692 return in->config.rate;
2693}
2694
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002695static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002696{
2697 return -ENOSYS;
2698}
2699
2700static size_t in_get_buffer_size(const struct audio_stream *stream)
2701{
2702 struct stream_in *in = (struct stream_in *)stream;
2703
Haynes Mathew George03c40102016-01-29 17:57:48 -08002704 return in->config.period_size * in->af_period_multiplier *
2705 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002706}
2707
2708static uint32_t in_get_channels(const struct audio_stream *stream)
2709{
2710 struct stream_in *in = (struct stream_in *)stream;
2711
2712 return in->channel_mask;
2713}
2714
vivek mehta4ed66e62016-04-15 23:33:34 -07002715static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002716{
vivek mehta4ed66e62016-04-15 23:33:34 -07002717 struct stream_in *in = (struct stream_in *)stream;
2718 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002719}
2720
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002721static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002722{
2723 return -ENOSYS;
2724}
2725
2726static int in_standby(struct audio_stream *stream)
2727{
2728 struct stream_in *in = (struct stream_in *)stream;
2729 struct audio_device *adev = in->dev;
2730 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08002731 bool do_stop = true;
2732
Eric Laurent994a6932013-07-17 11:51:42 -07002733 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002734
2735 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002736
2737 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08002738 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002739 audio_extn_sound_trigger_stop_lab(in);
2740 in->standby = true;
2741 }
2742
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002743 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002744 if (adev->adm_deregister_stream)
2745 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2746
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002747 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002748 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002749 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002750 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002751 in->capture_started = false;
2752 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002753 if (in->pcm) {
2754 pcm_close(in->pcm);
2755 in->pcm = NULL;
2756 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002757 adev->enable_voicerx = false;
2758 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08002759 if (do_stop) {
2760 status = stop_input_stream(in);
2761 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002762 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002763 }
2764 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002765 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002766 return status;
2767}
2768
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002769static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002770{
2771 return 0;
2772}
2773
2774static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2775{
2776 struct stream_in *in = (struct stream_in *)stream;
2777 struct audio_device *adev = in->dev;
2778 struct str_parms *parms;
2779 char *str;
2780 char value[32];
2781 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07002782 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002783
Eric Laurent994a6932013-07-17 11:51:42 -07002784 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002785 parms = str_parms_create_str(kvpairs);
2786
2787 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2788
Eric Laurenta1478072015-09-21 17:21:52 -07002789 lock_input_stream(in);
2790
Eric Laurent150dbfe2013-02-27 14:31:02 -08002791 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002792 if (ret >= 0) {
2793 val = atoi(value);
2794 /* no audio source uses val == 0 */
2795 if ((in->source != val) && (val != 0)) {
2796 in->source = val;
2797 }
2798 }
2799
2800 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07002801
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002802 if (ret >= 0) {
2803 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002804 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002805 in->device = val;
2806 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002807 if (!in->standby) {
2808 ALOGV("update input routing change");
2809 in->routing_change = true;
2810 select_devices(adev, in->usecase);
2811 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002812 }
2813 }
2814
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002815 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002816 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002817
2818 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002819 ALOGV("%s: exit: status(%d)", __func__, status);
2820 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002821}
2822
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002823static char* in_get_parameters(const struct audio_stream *stream __unused,
2824 const char *keys __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002825{
2826 return strdup("");
2827}
2828
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002829static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002830{
2831 return 0;
2832}
2833
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002834static void in_snd_mon_cb(void * stream, struct str_parms * parms)
2835{
2836 if (!stream || !parms)
2837 return;
2838
2839 struct stream_in *in = (struct stream_in *)stream;
2840 struct audio_device *adev = in->dev;
2841
2842 card_status_t status;
2843 int card;
2844 if (parse_snd_card_status(parms, &card, &status) < 0)
2845 return;
2846
2847 pthread_mutex_lock(&adev->lock);
2848 bool valid_cb = (card == adev->snd_card);
2849 pthread_mutex_unlock(&adev->lock);
2850
2851 if (!valid_cb)
2852 return;
2853
2854 lock_input_stream(in);
2855 if (in->card_status != status)
2856 in->card_status = status;
2857 pthread_mutex_unlock(&in->lock);
2858
2859 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
2860 use_case_table[in->usecase],
2861 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2862
2863 // a better solution would be to report error back to AF and let
2864 // it put the stream to standby
2865 if (status == CARD_STATUS_OFFLINE)
2866 in_standby(&in->stream.common);
2867
2868 return;
2869}
2870
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002871static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2872 size_t bytes)
2873{
2874 struct stream_in *in = (struct stream_in *)stream;
2875 struct audio_device *adev = in->dev;
2876 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07002877 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002878
Eric Laurenta1478072015-09-21 17:21:52 -07002879 lock_input_stream(in);
2880
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002881 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002882 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002883 /* Read from sound trigger HAL */
2884 audio_extn_sound_trigger_read(in, buffer, bytes);
2885 pthread_mutex_unlock(&in->lock);
2886 return bytes;
2887 }
2888
Eric Laurent0e46adf2016-12-16 12:49:24 -08002889 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
2890 ret = -ENOSYS;
2891 goto exit;
2892 }
2893
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002894 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002895 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002896 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002897 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002898 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002899 goto exit;
2900 }
2901 in->standby = 0;
2902 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002903
Haynes Mathew George03c40102016-01-29 17:57:48 -08002904 //what's the duration requested by the client?
2905 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
2906 in->config.rate;
2907 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002908
Haynes Mathew George03c40102016-01-29 17:57:48 -08002909 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002910 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002911 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002912 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07002913 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002914 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002915 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002916 if (ret < 0) {
2917 ALOGE("Failed to read w/err %s", strerror(errno));
2918 ret = -errno;
2919 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002920 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
2921 if (bytes % 4 == 0) {
2922 /* data from DSP comes in 24_8 format, convert it to 8_24 */
2923 int_buf_stream = buffer;
2924 for (size_t itt=0; itt < bytes/4 ; itt++) {
2925 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07002926 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002927 } else {
2928 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
2929 ret = -EINVAL;
2930 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07002931 }
2932 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002933 }
2934
Haynes Mathew George03c40102016-01-29 17:57:48 -08002935 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002936
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002937 /*
2938 * Instead of writing zeroes here, we could trust the hardware
2939 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002940 * 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 -08002941 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002942 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002943 memset(buffer, 0, bytes);
2944
2945exit:
2946 pthread_mutex_unlock(&in->lock);
2947
2948 if (ret != 0) {
2949 in_standby(&in->stream.common);
2950 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Eric Laurentfdf296a2014-07-03 16:41:51 -07002951 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002952 in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08002953 memset(buffer, 0, bytes); // clear return data
2954 }
2955 if (bytes > 0) {
Andy Hung6ebe5962016-01-15 17:46:57 -08002956 in->frames_read += bytes / audio_stream_in_frame_size(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002957 }
2958 return bytes;
2959}
2960
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002961static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002962{
2963 return 0;
2964}
2965
Andy Hung6ebe5962016-01-15 17:46:57 -08002966static int in_get_capture_position(const struct audio_stream_in *stream,
2967 int64_t *frames, int64_t *time)
2968{
2969 if (stream == NULL || frames == NULL || time == NULL) {
2970 return -EINVAL;
2971 }
2972 struct stream_in *in = (struct stream_in *)stream;
2973 int ret = -ENOSYS;
2974
2975 lock_input_stream(in);
2976 if (in->pcm) {
2977 struct timespec timestamp;
2978 unsigned int avail;
2979 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
2980 *frames = in->frames_read + avail;
2981 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
2982 ret = 0;
2983 }
2984 }
2985 pthread_mutex_unlock(&in->lock);
2986 return ret;
2987}
2988
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002989static int add_remove_audio_effect(const struct audio_stream *stream,
2990 effect_handle_t effect,
2991 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002992{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002993 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002994 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002995 int status = 0;
2996 effect_descriptor_t desc;
2997
2998 status = (*effect)->get_descriptor(effect, &desc);
2999 if (status != 0)
3000 return status;
3001
Eric Laurenta1478072015-09-21 17:21:52 -07003002 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003003 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003004 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003005 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003006 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003007 in->enable_aec != enable &&
3008 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3009 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003010 if (!enable)
3011 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003012 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3013 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3014 adev->enable_voicerx = enable;
3015 struct audio_usecase *usecase;
3016 struct listnode *node;
3017 list_for_each(node, &adev->usecase_list) {
3018 usecase = node_to_item(node, struct audio_usecase, list);
3019 if (usecase->type == PCM_PLAYBACK) {
3020 select_devices(adev, usecase->id);
3021 break;
3022 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003023 }
3024 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003025 if (!in->standby)
3026 select_devices(in->dev, in->usecase);
3027 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003028 if (in->enable_ns != enable &&
3029 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3030 in->enable_ns = enable;
3031 if (!in->standby)
3032 select_devices(in->dev, in->usecase);
3033 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003034 pthread_mutex_unlock(&in->dev->lock);
3035 pthread_mutex_unlock(&in->lock);
3036
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003037 return 0;
3038}
3039
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003040static int in_add_audio_effect(const struct audio_stream *stream,
3041 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003042{
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, true);
3045}
3046
3047static int in_remove_audio_effect(const struct audio_stream *stream,
3048 effect_handle_t effect)
3049{
Eric Laurent994a6932013-07-17 11:51:42 -07003050 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003051 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003052}
3053
Eric Laurent0e46adf2016-12-16 12:49:24 -08003054static int in_stop(const struct audio_stream_in* stream)
3055{
3056 struct stream_in *in = (struct stream_in *)stream;
3057 struct audio_device *adev = in->dev;
3058
3059 int ret = -ENOSYS;
3060 ALOGV("%s", __func__);
3061 pthread_mutex_lock(&adev->lock);
3062 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3063 in->capture_started && in->pcm != NULL) {
3064 pcm_stop(in->pcm);
3065 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003066 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003067 }
3068 pthread_mutex_unlock(&adev->lock);
3069 return ret;
3070}
3071
3072static int in_start(const struct audio_stream_in* stream)
3073{
3074 struct stream_in *in = (struct stream_in *)stream;
3075 struct audio_device *adev = in->dev;
3076 int ret = -ENOSYS;
3077
3078 ALOGV("%s in %p", __func__, in);
3079 pthread_mutex_lock(&adev->lock);
3080 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3081 !in->capture_started && in->pcm != NULL) {
3082 if (!in->capture_started) {
3083 ret = start_input_stream(in);
3084 if (ret == 0) {
3085 in->capture_started = true;
3086 }
3087 }
3088 }
3089 pthread_mutex_unlock(&adev->lock);
3090 return ret;
3091}
3092
3093static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3094 int32_t min_size_frames,
3095 struct audio_mmap_buffer_info *info)
3096{
3097 struct stream_in *in = (struct stream_in *)stream;
3098 struct audio_device *adev = in->dev;
3099 int ret = 0;
3100 unsigned int offset1;
3101 unsigned int frames1;
3102 const char *step = "";
3103
3104 pthread_mutex_lock(&adev->lock);
3105 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003106
Eric Laurent0e46adf2016-12-16 12:49:24 -08003107 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003108 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003109 ret = -EINVAL;
3110 goto exit;
3111 }
3112 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003113 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003114 ALOGV("%s in %p", __func__, in);
3115 ret = -ENOSYS;
3116 goto exit;
3117 }
3118 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3119 if (in->pcm_device_id < 0) {
3120 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3121 __func__, in->pcm_device_id, in->usecase);
3122 ret = -EINVAL;
3123 goto exit;
3124 }
Phil Burkbc991042017-02-24 08:06:44 -08003125
3126 adjust_mmap_period_count(&in->config, min_size_frames);
3127
Eric Laurent0e46adf2016-12-16 12:49:24 -08003128 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3129 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3130 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3131 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3132 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3133 step = "open";
3134 ret = -ENODEV;
3135 goto exit;
3136 }
3137
3138 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3139 if (ret < 0) {
3140 step = "begin";
3141 goto exit;
3142 }
3143 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
3144 info->burst_size_frames = in->config.period_size;
3145 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3146
3147 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(in->pcm,
3148 info->buffer_size_frames));
3149
3150 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3151 if (ret < 0) {
3152 step = "commit";
3153 goto exit;
3154 }
3155
Phil Burkbc991042017-02-24 08:06:44 -08003156 in->standby = false;
3157 ret = 0;
3158
Eric Laurent0e46adf2016-12-16 12:49:24 -08003159 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3160 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003161
3162exit:
3163 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003164 if (in->pcm == NULL) {
3165 ALOGE("%s: %s - %d", __func__, step, ret);
3166 } else {
3167 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003168 pcm_close(in->pcm);
3169 in->pcm = NULL;
3170 }
3171 }
3172 pthread_mutex_unlock(&adev->lock);
3173 return ret;
3174}
3175
3176static int in_get_mmap_position(const struct audio_stream_in *stream,
3177 struct audio_mmap_position *position)
3178{
3179 struct stream_in *in = (struct stream_in *)stream;
3180 ALOGVV("%s", __func__);
3181 if (position == NULL) {
3182 return -EINVAL;
3183 }
3184 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
3185 return -ENOSYS;
3186 }
3187 if (in->pcm == NULL) {
3188 return -ENOSYS;
3189 }
3190 struct timespec ts = { 0, 0 };
3191 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
3192 if (ret < 0) {
3193 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3194 return ret;
3195 }
Andy Hungfc044e12017-03-20 09:24:22 -07003196 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003197 return 0;
3198}
3199
3200
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003201static int adev_open_output_stream(struct audio_hw_device *dev,
3202 audio_io_handle_t handle,
3203 audio_devices_t devices,
3204 audio_output_flags_t flags,
3205 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003206 struct audio_stream_out **stream_out,
3207 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003208{
3209 struct audio_device *adev = (struct audio_device *)dev;
3210 struct stream_out *out;
3211 int i, ret;
3212
Eric Laurent994a6932013-07-17 11:51:42 -07003213 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003214 __func__, config->sample_rate, config->channel_mask, devices, flags);
3215 *stream_out = NULL;
3216 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3217
3218 if (devices == AUDIO_DEVICE_NONE)
3219 devices = AUDIO_DEVICE_OUT_SPEAKER;
3220
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003221 out->flags = flags;
3222 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003223 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003224 out->format = config->format;
3225 out->sample_rate = config->sample_rate;
3226 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3227 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003228 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003229
3230 /* Init use case and pcm_config */
3231 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
Eric Laurent7f245042013-09-30 19:22:50 -07003232 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003233 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003234 pthread_mutex_lock(&adev->lock);
3235 ret = read_hdmi_channel_masks(out);
3236 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003237 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003238 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003239
3240 if (config->sample_rate == 0)
3241 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3242 if (config->channel_mask == 0)
3243 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Eric Laurentad1cec22015-12-16 10:12:27 -08003244 if (config->format == AUDIO_FORMAT_DEFAULT)
3245 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003246
3247 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003248 out->sample_rate = config->sample_rate;
Eric Laurentad1cec22015-12-16 10:12:27 -08003249 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003250 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3251 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003252 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003253 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003254 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003255 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003256 pthread_mutex_lock(&adev->lock);
3257 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3258 pthread_mutex_unlock(&adev->lock);
3259
3260 // reject offload during card offline to allow
3261 // fallback to s/w paths
3262 if (offline) {
3263 ret = -ENODEV;
3264 goto error_open;
3265 }
3266
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003267 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3268 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3269 ALOGE("%s: Unsupported Offload information", __func__);
3270 ret = -EINVAL;
3271 goto error_open;
3272 }
3273 if (!is_supported_format(config->offload_info.format)) {
3274 ALOGE("%s: Unsupported audio format", __func__);
3275 ret = -EINVAL;
3276 goto error_open;
3277 }
3278
3279 out->compr_config.codec = (struct snd_codec *)
3280 calloc(1, sizeof(struct snd_codec));
3281
3282 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3283 if (config->offload_info.channel_mask)
3284 out->channel_mask = config->offload_info.channel_mask;
3285 else if (config->channel_mask)
3286 out->channel_mask = config->channel_mask;
3287 out->format = config->offload_info.format;
3288 out->sample_rate = config->offload_info.sample_rate;
3289
3290 out->stream.set_callback = out_set_callback;
3291 out->stream.pause = out_pause;
3292 out->stream.resume = out_resume;
3293 out->stream.drain = out_drain;
3294 out->stream.flush = out_flush;
3295
3296 out->compr_config.codec->id =
3297 get_snd_codec_id(config->offload_info.format);
3298 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3299 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07003300 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003301 out->compr_config.codec->bit_rate =
3302 config->offload_info.bit_rate;
3303 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003304 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003305 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3306
3307 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3308 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003309
3310 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003311 create_offload_callback_thread(out);
3312 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3313 __func__, config->offload_info.version,
3314 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003315 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3316 if (config->sample_rate == 0)
3317 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3318 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3319 config->sample_rate != 8000) {
3320 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3321 ret = -EINVAL;
3322 goto error_open;
3323 }
3324 out->sample_rate = config->sample_rate;
3325 out->config.rate = config->sample_rate;
3326 if (config->format == AUDIO_FORMAT_DEFAULT)
3327 config->format = AUDIO_FORMAT_PCM_16_BIT;
3328 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3329 config->format = AUDIO_FORMAT_PCM_16_BIT;
3330 ret = -EINVAL;
3331 goto error_open;
3332 }
3333 out->format = config->format;
3334 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3335 out->config = pcm_config_afe_proxy_playback;
3336 adev->voice_tx_output = out;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003337 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003338 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3339 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3340 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003341 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
3342 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3343 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003344 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3345 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003346 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003347 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003348 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3349 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3350 out->config = pcm_config_mmap_playback;
3351 out->stream.start = out_start;
3352 out->stream.stop = out_stop;
3353 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3354 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003355 } else {
3356 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3357 out->config = pcm_config_low_latency;
3358 }
3359 if (config->format != audio_format_from_pcm_format(out->config.format)) {
3360 if (k_enable_extended_precision
3361 && pcm_params_format_test(adev->use_case_table[out->usecase],
3362 pcm_format_from_audio_format(config->format))) {
3363 out->config.format = pcm_format_from_audio_format(config->format);
3364 /* out->format already set to config->format */
3365 } else {
3366 /* deny the externally proposed config format
3367 * and use the one specified in audio_hw layer configuration.
3368 * Note: out->format is returned by out->stream.common.get_format()
3369 * and is used to set config->format in the code several lines below.
3370 */
3371 out->format = audio_format_from_pcm_format(out->config.format);
3372 }
3373 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003374 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003375 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07003376 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3377 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003378
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003379 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003380 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003381 adev->primary_output = out;
3382 else {
3383 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003384 ret = -EEXIST;
3385 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003386 }
3387 }
3388
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003389 /* Check if this usecase is already existing */
3390 pthread_mutex_lock(&adev->lock);
3391 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3392 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003393 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003394 ret = -EEXIST;
3395 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003396 }
3397 pthread_mutex_unlock(&adev->lock);
3398
3399 out->stream.common.get_sample_rate = out_get_sample_rate;
3400 out->stream.common.set_sample_rate = out_set_sample_rate;
3401 out->stream.common.get_buffer_size = out_get_buffer_size;
3402 out->stream.common.get_channels = out_get_channels;
3403 out->stream.common.get_format = out_get_format;
3404 out->stream.common.set_format = out_set_format;
3405 out->stream.common.standby = out_standby;
3406 out->stream.common.dump = out_dump;
3407 out->stream.common.set_parameters = out_set_parameters;
3408 out->stream.common.get_parameters = out_get_parameters;
3409 out->stream.common.add_audio_effect = out_add_audio_effect;
3410 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3411 out->stream.get_latency = out_get_latency;
3412 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003413#ifdef NO_AUDIO_OUT
3414 out->stream.write = out_write_for_no_output;
3415#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003416 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003417#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003418 out->stream.get_render_position = out_get_render_position;
3419 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003420 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003421
Eric Laurent0e46adf2016-12-16 12:49:24 -08003422 if (out->realtime)
3423 out->af_period_multiplier = af_period_multiplier;
3424 else
3425 out->af_period_multiplier = 1;
3426
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003427 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003428 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003429 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003430
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003431 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003432 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003433 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3434
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003435 config->format = out->stream.common.get_format(&out->stream.common);
3436 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3437 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3438
Andy Hunga452b0a2017-03-15 14:51:15 -07003439 out->error_log = error_log_create(
3440 ERROR_LOG_ENTRIES,
3441 1000000000 /* aggregate consecutive identical errors within one second in ns */);
3442
Andy Hungfc044e12017-03-20 09:24:22 -07003443 const size_t POWER_LOG_FRAMES_PER_ENTRY =
3444 config->sample_rate * POWER_LOG_SAMPLING_INTERVAL_MS / 1000;
3445 // power_log may be null if the format is not supported
3446 out->power_log = power_log_create(
3447 config->sample_rate,
3448 audio_channel_count_from_out_mask(config->channel_mask),
3449 config->format,
3450 POWER_LOG_ENTRIES,
3451 POWER_LOG_FRAMES_PER_ENTRY);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003452
3453 /*
3454 By locking output stream before registering, we allow the callback
3455 to update stream's state only after stream's initial state is set to
3456 adev state.
3457 */
3458 lock_output_stream(out);
3459 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3460 pthread_mutex_lock(&adev->lock);
3461 out->card_status = adev->card_status;
3462 pthread_mutex_unlock(&adev->lock);
3463 pthread_mutex_unlock(&out->lock);
3464
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003465 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003466
Eric Laurent994a6932013-07-17 11:51:42 -07003467 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003468 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003469
3470error_open:
3471 free(out);
3472 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003473 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003474 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003475}
3476
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003477static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003478 struct audio_stream_out *stream)
3479{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003480 struct stream_out *out = (struct stream_out *)stream;
3481 struct audio_device *adev = out->dev;
3482
Eric Laurent994a6932013-07-17 11:51:42 -07003483 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003484
3485 // must deregister from sndmonitor first to prevent races
3486 // between the callback and close_stream
3487 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003488 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003489 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3490 destroy_offload_callback_thread(out);
3491
3492 if (out->compr_config.codec != NULL)
3493 free(out->compr_config.codec);
3494 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003495
3496 if (adev->voice_tx_output == out)
3497 adev->voice_tx_output = NULL;
3498
Andy Hungfc044e12017-03-20 09:24:22 -07003499 power_log_destroy(out->power_log);
3500 out->power_log = NULL;
3501
Andy Hunga452b0a2017-03-15 14:51:15 -07003502 error_log_destroy(out->error_log);
3503 out->error_log = NULL;
3504
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003505 pthread_cond_destroy(&out->cond);
3506 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003507 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003508 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003509}
3510
3511static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3512{
3513 struct audio_device *adev = (struct audio_device *)dev;
3514 struct str_parms *parms;
3515 char *str;
3516 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003517 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003518 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003519 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003520
Joe Onorato188b6222016-03-01 11:02:27 -08003521 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003522
3523 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003524
3525 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003526 status = voice_set_parameters(adev, parms);
3527 if (status != 0) {
3528 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003529 }
3530
3531 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3532 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003533 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003534 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3535 adev->bluetooth_nrec = true;
3536 else
3537 adev->bluetooth_nrec = false;
3538 }
3539
3540 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3541 if (ret >= 0) {
3542 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3543 adev->screen_off = false;
3544 else
3545 adev->screen_off = true;
3546 }
3547
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003548 ret = str_parms_get_int(parms, "rotation", &val);
3549 if (ret >= 0) {
3550 bool reverse_speakers = false;
3551 switch(val) {
3552 // FIXME: note that the code below assumes that the speakers are in the correct placement
3553 // relative to the user when the device is rotated 90deg from its default rotation. This
3554 // assumption is device-specific, not platform-specific like this code.
3555 case 270:
3556 reverse_speakers = true;
3557 break;
3558 case 0:
3559 case 90:
3560 case 180:
3561 break;
3562 default:
3563 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003564 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003565 }
Eric Laurent03f09432014-03-25 18:09:11 -07003566 if (status == 0) {
Ravi Kumar Alamanda1f60cf82015-04-23 19:45:17 -07003567 platform_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003568 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003569 }
3570
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003571 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3572 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003573 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003574 }
3575
David Linee3fe402017-03-13 10:00:42 -07003576 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3577 if (ret >= 0) {
3578 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
3579 if (device == AUDIO_DEVICE_OUT_USB_DEVICE) {
3580 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3581 if (ret >= 0) {
3582 const int card = atoi(value);
3583 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, card);
3584 }
3585 } else if (device == AUDIO_DEVICE_IN_USB_DEVICE) {
3586 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3587 if (ret >= 0) {
3588 const int card = atoi(value);
3589 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, card);
3590 }
3591 }
3592 }
3593
3594 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3595 if (ret >= 0) {
3596 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
3597 if (device == AUDIO_DEVICE_OUT_USB_DEVICE) {
3598 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3599 if (ret >= 0) {
3600 const int card = atoi(value);
3601
3602 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, card);
3603 }
3604 } else if (device == AUDIO_DEVICE_IN_USB_DEVICE) {
3605 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3606 if (ret >= 0) {
3607 const int card = atoi(value);
3608 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, card);
3609 }
3610 }
3611 }
3612
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08003613 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003614done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003615 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003616 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07003617 ALOGV("%s: exit with code(%d)", __func__, status);
3618 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003619}
3620
3621static char* adev_get_parameters(const struct audio_hw_device *dev,
3622 const char *keys)
3623{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003624 struct audio_device *adev = (struct audio_device *)dev;
3625 struct str_parms *reply = str_parms_create();
3626 struct str_parms *query = str_parms_create_str(keys);
3627 char *str;
3628
3629 pthread_mutex_lock(&adev->lock);
3630
3631 voice_get_parameters(adev, query, reply);
3632 str = str_parms_to_str(reply);
3633 str_parms_destroy(query);
3634 str_parms_destroy(reply);
3635
3636 pthread_mutex_unlock(&adev->lock);
3637 ALOGV("%s: exit: returns - %s", __func__, str);
3638 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003639}
3640
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003641static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003642{
3643 return 0;
3644}
3645
Haynes Mathew George5191a852013-09-11 14:19:36 -07003646static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3647{
3648 int ret;
3649 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003650
Eric Laurent4cc4ce12014-09-10 13:21:01 -05003651 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
3652
Haynes Mathew George5191a852013-09-11 14:19:36 -07003653 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003654 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003655 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003656
Haynes Mathew George5191a852013-09-11 14:19:36 -07003657 return ret;
3658}
3659
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003660static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003661{
3662 return -ENOSYS;
3663}
3664
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003665static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3666 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003667{
3668 return -ENOSYS;
3669}
3670
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003671static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003672{
3673 return -ENOSYS;
3674}
3675
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003676static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003677{
3678 return -ENOSYS;
3679}
3680
3681static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3682{
3683 struct audio_device *adev = (struct audio_device *)dev;
3684
3685 pthread_mutex_lock(&adev->lock);
3686 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07003687 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003688 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07003689 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3690 voice_is_in_call(adev)) {
3691 voice_stop_call(adev);
3692 adev->current_call_output = NULL;
3693 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003694 }
3695 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003696
3697 audio_extn_extspk_set_mode(adev->extspk, mode);
3698
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003699 return 0;
3700}
3701
3702static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3703{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003704 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003705 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003706
Eric Laurent2bafff12016-03-17 12:17:23 -07003707 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003708 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08003709 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
3710 ret = audio_extn_hfp_set_mic_mute(adev, state);
3711 } else {
3712 ret = voice_set_mic_mute(adev, state);
3713 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003714 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00003715 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003716
3717 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003718}
3719
3720static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3721{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003722 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003723 return 0;
3724}
3725
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003726static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003727 const struct audio_config *config)
3728{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003729 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003730
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003731 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3732 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003733}
3734
3735static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003736 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003737 audio_devices_t devices,
3738 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003739 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07003740 audio_input_flags_t flags,
3741 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05003742 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003743{
3744 struct audio_device *adev = (struct audio_device *)dev;
3745 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003746 int ret = 0, buffer_size, frame_size;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003747 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003748 bool is_low_latency = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003749
Eric Laurent994a6932013-07-17 11:51:42 -07003750 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003751 *stream_in = NULL;
3752 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3753 return -EINVAL;
3754
Zheng Zhang6185d572016-12-01 20:35:17 +08003755 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 -08003756 return -EINVAL;
3757
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003758 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
3759
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003760 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003761 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003762
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003763 in->stream.common.get_sample_rate = in_get_sample_rate;
3764 in->stream.common.set_sample_rate = in_set_sample_rate;
3765 in->stream.common.get_buffer_size = in_get_buffer_size;
3766 in->stream.common.get_channels = in_get_channels;
3767 in->stream.common.get_format = in_get_format;
3768 in->stream.common.set_format = in_set_format;
3769 in->stream.common.standby = in_standby;
3770 in->stream.common.dump = in_dump;
3771 in->stream.common.set_parameters = in_set_parameters;
3772 in->stream.common.get_parameters = in_get_parameters;
3773 in->stream.common.add_audio_effect = in_add_audio_effect;
3774 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3775 in->stream.set_gain = in_set_gain;
3776 in->stream.read = in_read;
3777 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08003778 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003779
3780 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003781 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003782 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003783 in->standby = 1;
3784 in->channel_mask = config->channel_mask;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003785 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003786 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003787
vivek mehta57ff9b52016-04-28 14:13:08 -07003788 // restrict 24 bit capture for unprocessed source only
3789 // for other sources if 24 bit requested reject 24 and set 16 bit capture only
3790 if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07003791 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07003792 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
3793 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
3794 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
3795 bool ret_error = false;
3796 /* 24 bit is restricted to UNPROCESSED source only,also format supported
3797 from HAL is 8_24
3798 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
3799 8_24 return error indicating supported format is 8_24
3800 *> In case of any other source requesting 24 bit or float return error
3801 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07003802
vivek mehta57ff9b52016-04-28 14:13:08 -07003803 on error flinger will retry with supported format passed
3804 */
3805 if (source != AUDIO_SOURCE_UNPROCESSED) {
3806 config->format = AUDIO_FORMAT_PCM_16_BIT;
3807 ret_error = true;
3808 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
3809 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
3810 ret_error = true;
3811 }
3812
3813 if (ret_error) {
3814 ret = -EINVAL;
3815 goto err_open;
3816 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003817 }
3818
vivek mehta57ff9b52016-04-28 14:13:08 -07003819 in->format = config->format;
3820
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003821 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003822 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
3823 if (config->sample_rate == 0)
3824 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3825 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3826 config->sample_rate != 8000) {
3827 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3828 ret = -EINVAL;
3829 goto err_open;
3830 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003831
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003832 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3833 config->format = AUDIO_FORMAT_PCM_16_BIT;
3834 ret = -EINVAL;
3835 goto err_open;
3836 }
3837
3838 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3839 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07003840 in->af_period_multiplier = 1;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003841 } else {
3842 in->usecase = USECASE_AUDIO_RECORD;
3843 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08003844 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003845 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07003846#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003847 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07003848#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08003849 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003850 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08003851 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003852 frame_size = audio_stream_in_frame_size(&in->stream);
3853 buffer_size = get_input_buffer_size(config->sample_rate,
3854 config->format,
3855 channel_count,
3856 is_low_latency);
3857 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003858 in->config.rate = config->sample_rate;
3859 in->af_period_multiplier = 1;
3860 } else {
3861 // period size is left untouched for rt mode playback
3862 in->config = pcm_config_audio_capture_rt;
3863 in->af_period_multiplier = af_period_multiplier;
3864 }
3865 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
3866 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
3867 in->usecase = USECASE_AUDIO_RECORD_MMAP;
3868 in->config = pcm_config_mmap_capture;
3869 in->stream.start = in_start;
3870 in->stream.stop = in_stop;
3871 in->stream.create_mmap_buffer = in_create_mmap_buffer;
3872 in->stream.get_mmap_position = in_get_mmap_position;
3873 in->af_period_multiplier = 1;
3874 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
3875 } else {
3876 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003877 frame_size = audio_stream_in_frame_size(&in->stream);
3878 buffer_size = get_input_buffer_size(config->sample_rate,
3879 config->format,
3880 channel_count,
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003881 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003882 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003883 in->config.rate = config->sample_rate;
3884 in->af_period_multiplier = 1;
3885 }
3886 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
3887 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003888 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003889
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003890 in->config.channels = channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003891
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003892 /* This stream could be for sound trigger lab,
3893 get sound trigger pcm if present */
3894 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003895
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003896 lock_input_stream(in);
3897 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
3898 pthread_mutex_lock(&adev->lock);
3899 in->card_status = adev->card_status;
3900 pthread_mutex_unlock(&adev->lock);
3901 pthread_mutex_unlock(&in->lock);
3902
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003903 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003904 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003905 return 0;
3906
3907err_open:
3908 free(in);
3909 *stream_in = NULL;
3910 return ret;
3911}
3912
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003913static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003914 struct audio_stream_in *stream)
3915{
Eric Laurent994a6932013-07-17 11:51:42 -07003916 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003917
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003918 // must deregister from sndmonitor first to prevent races
3919 // between the callback and close_stream
3920 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003921 in_standby(&stream->common);
3922 free(stream);
3923
3924 return;
3925}
3926
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003927static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003928{
3929 return 0;
3930}
3931
Andy Hung31aca912014-03-20 17:14:59 -07003932/* verifies input and output devices and their capabilities.
3933 *
3934 * This verification is required when enabling extended bit-depth or
3935 * sampling rates, as not all qcom products support it.
3936 *
3937 * Suitable for calling only on initialization such as adev_open().
3938 * It fills the audio_device use_case_table[] array.
3939 *
3940 * Has a side-effect that it needs to configure audio routing / devices
3941 * in order to power up the devices and read the device parameters.
3942 * It does not acquire any hw device lock. Should restore the devices
3943 * back to "normal state" upon completion.
3944 */
3945static int adev_verify_devices(struct audio_device *adev)
3946{
3947 /* enumeration is a bit difficult because one really wants to pull
3948 * the use_case, device id, etc from the hidden pcm_device_table[].
3949 * In this case there are the following use cases and device ids.
3950 *
3951 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
3952 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
3953 * [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
3954 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
3955 * [USECASE_AUDIO_RECORD] = {0, 0},
3956 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
3957 * [USECASE_VOICE_CALL] = {2, 2},
3958 *
3959 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_MULTI_CH omitted.
3960 * USECASE_VOICE_CALL omitted, but possible for either input or output.
3961 */
3962
3963 /* should be the usecases enabled in adev_open_input_stream() */
3964 static const int test_in_usecases[] = {
3965 USECASE_AUDIO_RECORD,
3966 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
3967 };
3968 /* should be the usecases enabled in adev_open_output_stream()*/
3969 static const int test_out_usecases[] = {
3970 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
3971 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
3972 };
3973 static const usecase_type_t usecase_type_by_dir[] = {
3974 PCM_PLAYBACK,
3975 PCM_CAPTURE,
3976 };
3977 static const unsigned flags_by_dir[] = {
3978 PCM_OUT,
3979 PCM_IN,
3980 };
3981
3982 size_t i;
3983 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003984 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07003985 char info[512]; /* for possible debug info */
3986
3987 for (dir = 0; dir < 2; ++dir) {
3988 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
3989 const unsigned flags_dir = flags_by_dir[dir];
3990 const size_t testsize =
3991 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
3992 const int *testcases =
3993 dir ? test_in_usecases : test_out_usecases;
3994 const audio_devices_t audio_device =
3995 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
3996
3997 for (i = 0; i < testsize; ++i) {
3998 const audio_usecase_t audio_usecase = testcases[i];
3999 int device_id;
4000 snd_device_t snd_device;
4001 struct pcm_params **pparams;
4002 struct stream_out out;
4003 struct stream_in in;
4004 struct audio_usecase uc_info;
4005 int retval;
4006
4007 pparams = &adev->use_case_table[audio_usecase];
4008 pcm_params_free(*pparams); /* can accept null input */
4009 *pparams = NULL;
4010
4011 /* find the device ID for the use case (signed, for error) */
4012 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
4013 if (device_id < 0)
4014 continue;
4015
4016 /* prepare structures for device probing */
4017 memset(&uc_info, 0, sizeof(uc_info));
4018 uc_info.id = audio_usecase;
4019 uc_info.type = usecase_type;
4020 if (dir) {
4021 adev->active_input = &in;
4022 memset(&in, 0, sizeof(in));
4023 in.device = audio_device;
4024 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4025 uc_info.stream.in = &in;
4026 } else {
4027 adev->active_input = NULL;
4028 }
4029 memset(&out, 0, sizeof(out));
4030 out.devices = audio_device; /* only field needed in select_devices */
4031 uc_info.stream.out = &out;
4032 uc_info.devices = audio_device;
4033 uc_info.in_snd_device = SND_DEVICE_NONE;
4034 uc_info.out_snd_device = SND_DEVICE_NONE;
4035 list_add_tail(&adev->usecase_list, &uc_info.list);
4036
4037 /* select device - similar to start_(in/out)put_stream() */
4038 retval = select_devices(adev, audio_usecase);
4039 if (retval >= 0) {
4040 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4041#if LOG_NDEBUG == 0
4042 if (*pparams) {
4043 ALOGV("%s: (%s) card %d device %d", __func__,
4044 dir ? "input" : "output", card_id, device_id);
4045 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004046 } else {
4047 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4048 }
4049#endif
4050 }
4051
4052 /* deselect device - similar to stop_(in/out)put_stream() */
4053 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004054 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004055 /* 2. Disable the rx device */
4056 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004057 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004058 list_remove(&uc_info.list);
4059 }
4060 }
4061 adev->active_input = NULL; /* restore adev state */
4062 return 0;
4063}
4064
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004065static int adev_close(hw_device_t *device)
4066{
Andy Hung31aca912014-03-20 17:14:59 -07004067 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004068 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004069
4070 if (!adev)
4071 return 0;
4072
Kevin Rocarda5453442017-05-02 15:09:20 -07004073 audio_extn_snd_mon_unregister_listener(adev);
Kevin Rocard8342c2c2017-04-07 18:50:00 -07004074 audio_extn_snd_mon_deinit();
Kevin Rocarda5453442017-05-02 15:09:20 -07004075
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004076 audio_extn_tfa_98xx_deinit();
4077
vivek mehta1a9b7c02015-06-25 11:49:38 -07004078 pthread_mutex_lock(&adev_init_lock);
4079
4080 if ((--audio_device_ref_count) == 0) {
4081 audio_route_free(adev->audio_route);
4082 free(adev->snd_dev_ref_cnt);
4083 platform_deinit(adev->platform);
4084 audio_extn_extspk_deinit(adev->extspk);
4085 audio_extn_sound_trigger_deinit(adev);
4086 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4087 pcm_params_free(adev->use_case_table[i]);
4088 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004089 if (adev->adm_deinit)
4090 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004091 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004092 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004093
4094 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004095
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004096 return 0;
4097}
4098
Glenn Kasten4f993392014-05-14 07:30:48 -07004099/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4100 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4101 * just that it _might_ work.
4102 */
4103static int period_size_is_plausible_for_low_latency(int period_size)
4104{
4105 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004106 case 48:
4107 case 96:
4108 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004109 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004110 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004111 case 240:
4112 case 320:
4113 case 480:
4114 return 1;
4115 default:
4116 return 0;
4117 }
4118}
4119
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004120static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4121{
4122 int card;
4123 card_status_t status;
4124
4125 if (!parms)
4126 return;
4127
4128 if (parse_snd_card_status(parms, &card, &status) < 0)
4129 return;
4130
4131 pthread_mutex_lock(&adev->lock);
4132 bool valid_cb = (card == adev->snd_card);
4133 if (valid_cb) {
4134 if (adev->card_status != status) {
4135 adev->card_status = status;
4136 platform_snd_card_update(adev->platform, status);
4137 }
4138 }
4139 pthread_mutex_unlock(&adev->lock);
4140 return;
4141}
4142
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004143static int adev_open(const hw_module_t *module, const char *name,
4144 hw_device_t **device)
4145{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004146 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004147
Eric Laurent2bafff12016-03-17 12:17:23 -07004148 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004149 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004150 pthread_mutex_lock(&adev_init_lock);
4151 if (audio_device_ref_count != 0) {
4152 *device = &adev->device.common;
4153 audio_device_ref_count++;
4154 ALOGV("%s: returning existing instance of adev", __func__);
4155 ALOGV("%s: exit", __func__);
4156 pthread_mutex_unlock(&adev_init_lock);
4157 return 0;
4158 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004159 adev = calloc(1, sizeof(struct audio_device));
4160
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004161 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4162
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004163 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4164 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4165 adev->device.common.module = (struct hw_module_t *)module;
4166 adev->device.common.close = adev_close;
4167
4168 adev->device.init_check = adev_init_check;
4169 adev->device.set_voice_volume = adev_set_voice_volume;
4170 adev->device.set_master_volume = adev_set_master_volume;
4171 adev->device.get_master_volume = adev_get_master_volume;
4172 adev->device.set_master_mute = adev_set_master_mute;
4173 adev->device.get_master_mute = adev_get_master_mute;
4174 adev->device.set_mode = adev_set_mode;
4175 adev->device.set_mic_mute = adev_set_mic_mute;
4176 adev->device.get_mic_mute = adev_get_mic_mute;
4177 adev->device.set_parameters = adev_set_parameters;
4178 adev->device.get_parameters = adev_get_parameters;
4179 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4180 adev->device.open_output_stream = adev_open_output_stream;
4181 adev->device.close_output_stream = adev_close_output_stream;
4182 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004183
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004184 adev->device.close_input_stream = adev_close_input_stream;
4185 adev->device.dump = adev_dump;
4186
4187 /* Set the default route before the PCM stream is opened */
4188 pthread_mutex_lock(&adev->lock);
4189 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004190 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004191 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004192 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004193 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004194 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004195 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004196 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004197 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004198 pthread_mutex_unlock(&adev->lock);
4199
4200 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004201 adev->platform = platform_init(adev);
4202 if (!adev->platform) {
4203 free(adev->snd_dev_ref_cnt);
4204 free(adev);
4205 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4206 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004207 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004208 return -EINVAL;
4209 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05004210 adev->extspk = audio_extn_extspk_init(adev);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004211 audio_extn_sound_trigger_init(adev);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004212
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004213 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4214 if (adev->visualizer_lib == NULL) {
4215 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4216 } else {
4217 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4218 adev->visualizer_start_output =
4219 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4220 "visualizer_hal_start_output");
4221 adev->visualizer_stop_output =
4222 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4223 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07004224 }
4225
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004226 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4227 if (adev->offload_effects_lib == NULL) {
4228 ALOGW("%s: DLOPEN failed for %s", __func__,
4229 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4230 } else {
4231 ALOGV("%s: DLOPEN successful for %s", __func__,
4232 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4233 adev->offload_effects_start_output =
4234 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4235 "offload_effects_bundle_hal_start_output");
4236 adev->offload_effects_stop_output =
4237 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4238 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07004239 }
4240
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004241 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4242 if (adev->adm_lib == NULL) {
4243 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4244 } else {
4245 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4246 adev->adm_init = (adm_init_t)
4247 dlsym(adev->adm_lib, "adm_init");
4248 adev->adm_deinit = (adm_deinit_t)
4249 dlsym(adev->adm_lib, "adm_deinit");
4250 adev->adm_register_input_stream = (adm_register_input_stream_t)
4251 dlsym(adev->adm_lib, "adm_register_input_stream");
4252 adev->adm_register_output_stream = (adm_register_output_stream_t)
4253 dlsym(adev->adm_lib, "adm_register_output_stream");
4254 adev->adm_deregister_stream = (adm_deregister_stream_t)
4255 dlsym(adev->adm_lib, "adm_deregister_stream");
4256 adev->adm_request_focus = (adm_request_focus_t)
4257 dlsym(adev->adm_lib, "adm_request_focus");
4258 adev->adm_abandon_focus = (adm_abandon_focus_t)
4259 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08004260 adev->adm_set_config = (adm_set_config_t)
4261 dlsym(adev->adm_lib, "adm_set_config");
4262 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4263 dlsym(adev->adm_lib, "adm_request_focus_v2");
4264 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4265 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4266 adev->adm_on_routing_change = (adm_on_routing_change_t)
4267 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004268 }
4269
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004270 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004271 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004272
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004273 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004274
Andy Hung31aca912014-03-20 17:14:59 -07004275 if (k_enable_extended_precision)
4276 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004277
Glenn Kasten4f993392014-05-14 07:30:48 -07004278 char value[PROPERTY_VALUE_MAX];
4279 int trial;
4280 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4281 trial = atoi(value);
4282 if (period_size_is_plausible_for_low_latency(trial)) {
4283 pcm_config_low_latency.period_size = trial;
4284 pcm_config_low_latency.start_threshold = trial / 4;
4285 pcm_config_low_latency.avail_min = trial / 4;
4286 configured_low_latency_capture_period_size = trial;
4287 }
4288 }
4289 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4290 trial = atoi(value);
4291 if (period_size_is_plausible_for_low_latency(trial)) {
4292 configured_low_latency_capture_period_size = trial;
4293 }
4294 }
4295
Yamit Mehtae3b99562016-09-16 22:44:00 +05304296 audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004297 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004298
4299 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4300 af_period_multiplier = atoi(value);
4301 if (af_period_multiplier < 0) {
4302 af_period_multiplier = 2;
4303 } else if (af_period_multiplier > 4) {
4304 af_period_multiplier = 4;
4305 }
4306 ALOGV("new period_multiplier = %d", af_period_multiplier);
4307 }
4308
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004309 audio_extn_tfa_98xx_init(adev);
4310
vivek mehta1a9b7c02015-06-25 11:49:38 -07004311 pthread_mutex_unlock(&adev_init_lock);
4312
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004313 if (adev->adm_init)
4314 adev->adm_data = adev->adm_init();
4315
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004316 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004317 audio_extn_snd_mon_init();
4318 pthread_mutex_lock(&adev->lock);
4319 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
4320 adev->card_status = CARD_STATUS_ONLINE;
4321 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004322
Eric Laurent2bafff12016-03-17 12:17:23 -07004323 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004324 return 0;
4325}
4326
4327static struct hw_module_methods_t hal_module_methods = {
4328 .open = adev_open,
4329};
4330
4331struct audio_module HAL_MODULE_INFO_SYM = {
4332 .common = {
4333 .tag = HARDWARE_MODULE_TAG,
4334 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4335 .hal_api_version = HARDWARE_HAL_API_VERSION,
4336 .id = AUDIO_HARDWARE_MODULE_ID,
4337 .name = "QCOM Audio HAL",
4338 .author = "Code Aurora Forum",
4339 .methods = &hal_module_methods,
4340 },
4341};