blob: 411ee25fd2d35f98f9ab2c323d48656fcd1419e7 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
vivek mehtaa51fd402016-02-04 19:49:33 -08002 * Copyright (C) 2013-2016 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "audio_hw_primary"
Haynes Mathew George03c40102016-01-29 17:57:48 -080018#define ATRACE_TAG ATRACE_TAG_AUDIO
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080019/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070020/*#define VERY_VERY_VERBOSE_LOGGING*/
21#ifdef VERY_VERY_VERBOSE_LOGGING
22#define ALOGVV ALOGV
23#else
24#define ALOGVV(a...) do { } while(0)
25#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080026
27#include <errno.h>
28#include <pthread.h>
29#include <stdint.h>
30#include <sys/time.h>
31#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080032#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070033#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070034#include <sys/resource.h>
35#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036
37#include <cutils/log.h>
Haynes Mathew George03c40102016-01-29 17:57:48 -080038#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080039#include <cutils/str_parms.h>
40#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041#include <cutils/atomic.h>
42#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080043
Eric Laurentb23d5282013-05-14 15:27:20 -070044#include <hardware/audio_effect.h>
Andy Hung31aca912014-03-20 17:14:59 -070045#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070046#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070047#include <audio_effects/effect_aec.h>
48#include <audio_effects/effect_ns.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080049#include "audio_hw.h"
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -080050#include "audio_extn.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070051#include "platform_api.h"
52#include <platform.h>
Vineeta Srivastava4b89e372014-06-19 14:21:42 -070053#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080054
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include "sound/compress_params.h"
56
Eric Laurent397db572016-05-11 11:31:47 -070057/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
58 * COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
Marco Nelissen32093f52015-04-08 15:14:02 -070059#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070060// 2 buffers causes problems with high bitrate files
61#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062/* ToDo: Check and update a proper value in msec */
63#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
64#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
65
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070066#define PROXY_OPEN_RETRY_COUNT 100
67#define PROXY_OPEN_WAIT_TIME 20
68
vivek mehtadae44712015-07-27 14:13:18 -070069#define MIN_CHANNEL_COUNT 1
70#define DEFAULT_CHANNEL_COUNT 2
71
Jean-Michel Trivic0750692015-10-12 12:12:32 -070072#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
73#define MAX_CHANNEL_COUNT 1
74#else
vivek mehtadae44712015-07-27 14:13:18 -070075#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
76#define XSTR(x) STR(x)
77#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070078#endif
vivek mehtadae44712015-07-27 14:13:18 -070079
Haynes Mathew George03c40102016-01-29 17:57:48 -080080#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
81
Glenn Kasten4f993392014-05-14 07:30:48 -070082static unsigned int configured_low_latency_capture_period_size =
83 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
84
Andy Hung31aca912014-03-20 17:14:59 -070085/* This constant enables extended precision handling.
86 * TODO The flag is off until more testing is done.
87 */
88static const bool k_enable_extended_precision = false;
89
Eric Laurentb23d5282013-05-14 15:27:20 -070090struct pcm_config pcm_config_deep_buffer = {
vivek mehtadae44712015-07-27 14:13:18 -070091 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -070092 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
93 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
94 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
95 .format = PCM_FORMAT_S16_LE,
96 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
97 .stop_threshold = INT_MAX,
98 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
99};
100
101struct pcm_config pcm_config_low_latency = {
vivek mehtadae44712015-07-27 14:13:18 -0700102 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700103 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
104 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
105 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
106 .format = PCM_FORMAT_S16_LE,
107 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
108 .stop_threshold = INT_MAX,
109 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
110};
111
Haynes Mathew George03c40102016-01-29 17:57:48 -0800112static int af_period_multiplier = 4;
113struct pcm_config pcm_config_rt = {
114 .channels = DEFAULT_CHANNEL_COUNT,
115 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
116 .period_size = ULL_PERIOD_SIZE, //1 ms
117 .period_count = 512, //=> buffer size is 512ms
118 .format = PCM_FORMAT_S16_LE,
119 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
120 .stop_threshold = INT_MAX,
121 .silence_threshold = 0,
122 .silence_size = 0,
123 .avail_min = ULL_PERIOD_SIZE, //1 ms
124};
125
Eric Laurentb23d5282013-05-14 15:27:20 -0700126struct pcm_config pcm_config_hdmi_multi = {
127 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
128 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
129 .period_size = HDMI_MULTI_PERIOD_SIZE,
130 .period_count = HDMI_MULTI_PERIOD_COUNT,
131 .format = PCM_FORMAT_S16_LE,
132 .start_threshold = 0,
133 .stop_threshold = INT_MAX,
134 .avail_min = 0,
135};
136
137struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700138 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700139 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
140 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700141 .stop_threshold = INT_MAX,
142 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700143};
144
Haynes Mathew George03c40102016-01-29 17:57:48 -0800145struct pcm_config pcm_config_audio_capture_rt = {
146 .channels = DEFAULT_CHANNEL_COUNT,
147 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
148 .period_size = ULL_PERIOD_SIZE,
149 .period_count = 512,
150 .format = PCM_FORMAT_S16_LE,
151 .start_threshold = 0,
152 .stop_threshold = INT_MAX,
153 .silence_threshold = 0,
154 .silence_size = 0,
155 .avail_min = ULL_PERIOD_SIZE, //1 ms
156};
157
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700158#define AFE_PROXY_CHANNEL_COUNT 2
159#define AFE_PROXY_SAMPLING_RATE 48000
160
161#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
162#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
163
164struct pcm_config pcm_config_afe_proxy_playback = {
165 .channels = AFE_PROXY_CHANNEL_COUNT,
166 .rate = AFE_PROXY_SAMPLING_RATE,
167 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
168 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
169 .format = PCM_FORMAT_S16_LE,
170 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
171 .stop_threshold = INT_MAX,
172 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
173};
174
175#define AFE_PROXY_RECORD_PERIOD_SIZE 768
176#define AFE_PROXY_RECORD_PERIOD_COUNT 4
177
178struct pcm_config pcm_config_afe_proxy_record = {
179 .channels = AFE_PROXY_CHANNEL_COUNT,
180 .rate = AFE_PROXY_SAMPLING_RATE,
181 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
182 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
183 .format = PCM_FORMAT_S16_LE,
184 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
185 .stop_threshold = INT_MAX,
186 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
187};
188
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700189const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700190 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
191 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
192 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700193 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700194 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700195 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700196
Eric Laurentb23d5282013-05-14 15:27:20 -0700197 [USECASE_AUDIO_RECORD] = "audio-record",
198 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700199
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800200 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
201 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700202
Eric Laurentb23d5282013-05-14 15:27:20 -0700203 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700204 [USECASE_VOICE2_CALL] = "voice2-call",
205 [USECASE_VOLTE_CALL] = "volte-call",
206 [USECASE_QCHAT_CALL] = "qchat-call",
207 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800208 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
209 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700210
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700211 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
212 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
213
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700214 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
215 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700216};
217
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800218
219#define STRING_TO_ENUM(string) { #string, string }
220
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800221struct string_to_enum {
222 const char *name;
223 uint32_t value;
224};
225
226static const struct string_to_enum out_channels_name_to_enum_table[] = {
227 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
228 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
229 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
230};
231
Haynes Mathew George5191a852013-09-11 14:19:36 -0700232static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700233static struct audio_device *adev = NULL;
234static pthread_mutex_t adev_init_lock;
235static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700236//cache last MBDRC cal step level
237static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700238
Haynes Mathew George03c40102016-01-29 17:57:48 -0800239static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
240 int flags __unused)
241{
242 int dir = 0;
243 switch (uc_id) {
244 case USECASE_AUDIO_RECORD_LOW_LATENCY:
245 dir = 1;
246 case USECASE_AUDIO_PLAYBACK_ULL:
247 break;
248 default:
249 return false;
250 }
251
252 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
253 PCM_PLAYBACK : PCM_CAPTURE);
254 if (adev->adm_is_noirq_avail)
255 return adev->adm_is_noirq_avail(adev->adm_data,
256 adev->snd_card, dev_id, dir);
257 return false;
258}
259
260static void register_out_stream(struct stream_out *out)
261{
262 struct audio_device *adev = out->dev;
263 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
264 return;
265
266 if (!adev->adm_register_output_stream)
267 return;
268
269 adev->adm_register_output_stream(adev->adm_data,
270 out->handle,
271 out->flags);
272
273 if (!adev->adm_set_config)
274 return;
275
276 if (out->realtime) {
277 adev->adm_set_config(adev->adm_data,
278 out->handle,
279 out->pcm, &out->config);
280 }
281}
282
283static void register_in_stream(struct stream_in *in)
284{
285 struct audio_device *adev = in->dev;
286 if (!adev->adm_register_input_stream)
287 return;
288
289 adev->adm_register_input_stream(adev->adm_data,
290 in->capture_handle,
291 in->flags);
292
293 if (!adev->adm_set_config)
294 return;
295
296 if (in->realtime) {
297 adev->adm_set_config(adev->adm_data,
298 in->capture_handle,
299 in->pcm,
300 &in->config);
301 }
302}
303
304static void request_out_focus(struct stream_out *out, long ns)
305{
306 struct audio_device *adev = out->dev;
307
308 if (out->routing_change) {
309 out->routing_change = false;
310 if (adev->adm_on_routing_change)
311 adev->adm_on_routing_change(adev->adm_data, out->handle);
312 }
313
314 if (adev->adm_request_focus_v2) {
315 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
316 } else if (adev->adm_request_focus) {
317 adev->adm_request_focus(adev->adm_data, out->handle);
318 }
319}
320
321static void request_in_focus(struct stream_in *in, long ns)
322{
323 struct audio_device *adev = in->dev;
324
325 if (in->routing_change) {
326 in->routing_change = false;
327 if (adev->adm_on_routing_change)
328 adev->adm_on_routing_change(adev->adm_data, in->capture_handle);
329 }
330
331 if (adev->adm_request_focus_v2) {
332 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
333 } else if (adev->adm_request_focus) {
334 adev->adm_request_focus(adev->adm_data, in->capture_handle);
335 }
336}
337
338static void release_out_focus(struct stream_out *out, long ns __unused)
339{
340 struct audio_device *adev = out->dev;
341
342 if (adev->adm_abandon_focus)
343 adev->adm_abandon_focus(adev->adm_data, out->handle);
344}
345
346static void release_in_focus(struct stream_in *in, long ns __unused)
347{
348 struct audio_device *adev = in->dev;
349 if (adev->adm_abandon_focus)
350 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
351}
352
Andy Hung7401c7c2016-09-21 12:41:21 -0700353// Time string format similar to logcat, buffer_length must be >= 19 chars.
354static void ns2string(int64_t ns, char *buffer, int buffer_length)
355{
356 const int one_second = 1000000000;
357 const time_t sec = ns / one_second;
358 struct tm tm;
359 localtime_r(&sec, &tm);
360 snprintf(buffer, buffer_length, "%02d-%02d %02d:%02d:%02d.%03d",
361 tm.tm_mon + 1, // localtime_r uses months in 0 - 11 range
362 tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,
363 (int)(ns % one_second / 1000000));
364}
365
366// Convert timespec to nsec.
367static int64_t ts2ns(const struct timespec *ts)
368{
369 return ts->tv_sec * 1000000000LL + ts->tv_nsec;
370}
371
372// Log errors: consecutive errors with the same code will
373// be aggregated if they occur within one second.
374// A mutual exclusion lock must be held before calling.
375static void log_error_l(struct error_log *log, int code) {
376 ++log->errors;
377
378 struct timespec now_ts = { 0, 0 };
379 (void)clock_gettime(CLOCK_REALTIME, &now_ts);
380 const int64_t now = ts2ns(&now_ts);
381
382 // Within 1 second, cluster the same error codes together.
383 const int one_second = 1000000000;
384 if (code == log->entries[log->idx].code &&
385 now - log->entries[log->idx].last_time < one_second) {
386 log->entries[log->idx].count++;
387 log->entries[log->idx].last_time = now;
388 return;
389 }
390
391 // Add new error entry.
392 if (++log->idx >= ARRAY_SIZE(log->entries)) {
393 log->idx = 0;
394 }
395 log->entries[log->idx].count = 1;
396 log->entries[log->idx].code = code;
397 log->entries[log->idx].first_time = now;
398 log->entries[log->idx].last_time = now;
399}
400
401// Dump information in the error log. A mutual exclusion lock
402// should be held, but if that cannot be obtained, one should
403// make a copy of the error log before calling -- the call is
404// still safe, but there might be some misinterpreted data.
405static void log_dump_l(const struct error_log *log, int fd)
406{
407 dprintf(fd, " Errors: %u\n", log->errors);
408 if (log->errors == 0)
409 return;
410
411 dprintf(fd, " Index Code Freq First time Last time\n");
412 for (size_t i = 0; i < ARRAY_SIZE(log->entries); ++i) {
413 if (log->entries[i].count != 0) {
414 char first_time[32];
415 char last_time[32];
416 ns2string(log->entries[i].first_time, first_time, sizeof(first_time));
417 ns2string(log->entries[i].last_time, last_time, sizeof(last_time));
418 dprintf(fd, " %c%4zu %4d %5d %s %s\n",
419 i == log->idx ? '*' : ' ', // mark head position
420 i, log->entries[i].code, log->entries[i].count,
421 first_time, last_time);
422 }
423 }
424}
425
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700426static int parse_snd_card_status(struct str_parms * parms, int * card,
427 card_status_t * status)
428{
429 char value[32]={0};
430 char state[32]={0};
431
432 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
433
434 if (ret < 0)
435 return -1;
436
437 // sscanf should be okay as value is of max length 32.
438 // same as sizeof state.
439 if (sscanf(value, "%d,%s", card, state) < 2)
440 return -1;
441
442 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
443 CARD_STATUS_OFFLINE;
444 return 0;
445}
446
vivek mehta1a9b7c02015-06-25 11:49:38 -0700447__attribute__ ((visibility ("default")))
448bool audio_hw_send_gain_dep_calibration(int level) {
449 bool ret_val = false;
450 ALOGV("%s: enter ... ", __func__);
451
452 pthread_mutex_lock(&adev_init_lock);
453
454 if (adev != NULL && adev->platform != NULL) {
455 pthread_mutex_lock(&adev->lock);
456 ret_val = platform_send_gain_dep_cal(adev->platform, level);
457 pthread_mutex_unlock(&adev->lock);
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700458
459 // if cal set fails, cache level info
460 // if cal set succeds, reset known last cal set
461 if (!ret_val)
462 last_known_cal_step = level;
463 else if (last_known_cal_step != -1)
464 last_known_cal_step = -1;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700465 } else {
466 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
467 }
468
469 pthread_mutex_unlock(&adev_init_lock);
470
471 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
472 return ret_val;
473}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700474
vivek mehtaa8d7c922016-05-25 14:40:44 -0700475__attribute__ ((visibility ("default")))
476int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
477 int table_size) {
478 int ret_val = 0;
479 ALOGV("%s: enter ... ", __func__);
480
481 pthread_mutex_lock(&adev_init_lock);
482 if (adev == NULL) {
483 ALOGW("%s: adev is NULL .... ", __func__);
484 goto done;
485 }
486
487 pthread_mutex_lock(&adev->lock);
488 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
489 pthread_mutex_unlock(&adev->lock);
490done:
491 pthread_mutex_unlock(&adev_init_lock);
492 ALOGV("%s: exit ... ", __func__);
493 return ret_val;
494}
495
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700496static bool is_supported_format(audio_format_t format)
497{
Eric Laurent8251ac82014-07-23 11:00:25 -0700498 switch (format) {
499 case AUDIO_FORMAT_MP3:
500 case AUDIO_FORMAT_AAC_LC:
501 case AUDIO_FORMAT_AAC_HE_V1:
502 case AUDIO_FORMAT_AAC_HE_V2:
503 return true;
504 default:
505 break;
506 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700507 return false;
508}
509
Haynes Mathew George03c40102016-01-29 17:57:48 -0800510static inline bool is_mmap_usecase(audio_usecase_t uc_id)
511{
512 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
513 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
514}
515
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700516static int get_snd_codec_id(audio_format_t format)
517{
518 int id = 0;
519
Eric Laurent8251ac82014-07-23 11:00:25 -0700520 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700521 case AUDIO_FORMAT_MP3:
522 id = SND_AUDIOCODEC_MP3;
523 break;
524 case AUDIO_FORMAT_AAC:
525 id = SND_AUDIOCODEC_AAC;
526 break;
527 default:
528 ALOGE("%s: Unsupported audio format", __func__);
529 }
530
531 return id;
532}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800533
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800534int enable_audio_route(struct audio_device *adev,
535 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800536{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700537 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800538 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800539
540 if (usecase == NULL)
541 return -EINVAL;
542
543 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
544
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800545 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700546 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800547 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700548 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800549
Yamit Mehtae3b99562016-09-16 22:44:00 +0530550 audio_extn_utils_send_app_type_cfg(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800551 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500552 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700553 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700554 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800555
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800556 ALOGV("%s: exit", __func__);
557 return 0;
558}
559
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800560int disable_audio_route(struct audio_device *adev,
561 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800562{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700563 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800564 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800565
566 if (usecase == NULL)
567 return -EINVAL;
568
569 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700570 if (usecase->type == PCM_CAPTURE)
571 snd_device = usecase->in_snd_device;
572 else
573 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800574 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500575 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700576 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700577 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800578
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800579 ALOGV("%s: exit", __func__);
580 return 0;
581}
582
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800583int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700584 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800585{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700586 int i, num_devices = 0;
587 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800588 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800589 if (snd_device < SND_DEVICE_MIN ||
590 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800591 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800592 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800593 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700594
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700595 platform_send_audio_calibration(adev->platform, snd_device);
596
vivek mehtade4849c2016-03-03 17:23:38 -0800597 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700598 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700599 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800600 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700601 }
602
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700603 /* due to the possibility of calibration overwrite between listen
604 and audio, notify sound trigger hal before audio calibration is sent */
605 audio_extn_sound_trigger_update_device_status(snd_device,
606 ST_EVENT_SND_DEVICE_BUSY);
607
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700608 if (audio_extn_spkr_prot_is_enabled())
609 audio_extn_spkr_prot_calib_cancel(adev);
610
zhaoyang yin4211fad2015-06-04 21:13:25 +0800611 audio_extn_dsm_feedback_enable(adev, snd_device, true);
612
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700613 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
614 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
615 audio_extn_spkr_prot_is_enabled()) {
616 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800617 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700618 }
619 if (audio_extn_spkr_prot_start_processing(snd_device)) {
620 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800621 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700622 }
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700623 } else if (platform_can_split_snd_device(snd_device, &num_devices, new_snd_devices)) {
624 for (i = 0; i < num_devices; i++) {
625 enable_snd_device(adev, new_snd_devices[i]);
626 }
vivek mehtab6506412015-08-07 16:55:17 -0700627 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700628 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800629 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
630 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
631 ALOGE(" %s: Invalid sound device returned", __func__);
632 goto on_error;
633 }
Ed Tam70b5c142016-03-21 19:14:29 -0700634
Eric Laurent2e140aa2016-06-30 17:14:46 -0700635 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800636 audio_route_apply_and_update_path(adev->audio_route, device_name);
637 }
638on_success:
639 adev->snd_dev_ref_cnt[snd_device]++;
640 ret_val = 0;
641on_error:
642 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800643}
644
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800645int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700646 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800647{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700648 int i, num_devices = 0;
649 snd_device_t new_snd_devices[2];
650
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800651 if (snd_device < SND_DEVICE_MIN ||
652 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800653 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800654 return -EINVAL;
655 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700656 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
657 ALOGE("%s: device ref cnt is already 0", __func__);
658 return -EINVAL;
659 }
660 adev->snd_dev_ref_cnt[snd_device]--;
661 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800662 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700663 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
664 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
665 audio_extn_spkr_prot_is_enabled()) {
666 audio_extn_spkr_prot_stop_processing(snd_device);
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700667 } else if (platform_can_split_snd_device(snd_device, &num_devices, new_snd_devices)) {
668 for (i = 0; i < num_devices; i++) {
669 disable_snd_device(adev, new_snd_devices[i]);
670 }
vivek mehtab6506412015-08-07 16:55:17 -0700671 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700672 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800673 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
674 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
675 ALOGE(" %s: Invalid sound device returned", __func__);
676 return -EINVAL;
677 }
678
Eric Laurent2e140aa2016-06-30 17:14:46 -0700679 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800680 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700681 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700682 audio_extn_sound_trigger_update_device_status(snd_device,
683 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700684 }
vivek mehtab6506412015-08-07 16:55:17 -0700685
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800686 return 0;
687}
688
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700689static void check_and_route_playback_usecases(struct audio_device *adev,
690 struct audio_usecase *uc_info,
691 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700692{
693 struct listnode *node;
694 struct audio_usecase *usecase;
695 bool switch_device[AUDIO_USECASE_MAX];
696 int i, num_uc_to_switch = 0;
697
698 /*
699 * This function is to make sure that all the usecases that are active on
700 * the hardware codec backend are always routed to any one device that is
701 * handled by the hardware codec.
702 * For example, if low-latency and deep-buffer usecases are currently active
703 * on speaker and out_set_parameters(headset) is received on low-latency
704 * output, then we have to make sure deep-buffer is also switched to headset,
705 * because of the limitation that both the devices cannot be enabled
706 * at the same time as they share the same backend.
707 */
708 /* Disable all the usecases on the shared backend other than the
709 specified usecase */
710 for (i = 0; i < AUDIO_USECASE_MAX; i++)
711 switch_device[i] = false;
712
713 list_for_each(node, &adev->usecase_list) {
714 usecase = node_to_item(node, struct audio_usecase, list);
715 if (usecase->type != PCM_CAPTURE &&
716 usecase != uc_info &&
717 usecase->out_snd_device != snd_device &&
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700718 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
719 platform_check_backends_match(snd_device, usecase->out_snd_device)) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700720 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
721 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700722 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700723 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700724 switch_device[usecase->id] = true;
725 num_uc_to_switch++;
726 }
727 }
728
729 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700730 list_for_each(node, &adev->usecase_list) {
731 usecase = node_to_item(node, struct audio_usecase, list);
732 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700733 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900734 }
735 }
736
737 list_for_each(node, &adev->usecase_list) {
738 usecase = node_to_item(node, struct audio_usecase, list);
739 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700740 enable_snd_device(adev, snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700741 }
742 }
743
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700744 /* Re-route all the usecases on the shared backend other than the
745 specified usecase to new snd devices */
746 list_for_each(node, &adev->usecase_list) {
747 usecase = node_to_item(node, struct audio_usecase, list);
748 /* Update the out_snd_device only before enabling the audio route */
749 if (switch_device[usecase->id] ) {
750 usecase->out_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700751 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700752 }
753 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700754 }
755}
756
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700757static void check_and_route_capture_usecases(struct audio_device *adev,
758 struct audio_usecase *uc_info,
759 snd_device_t snd_device)
760{
761 struct listnode *node;
762 struct audio_usecase *usecase;
763 bool switch_device[AUDIO_USECASE_MAX];
764 int i, num_uc_to_switch = 0;
765
vivek mehta4ed66e62016-04-15 23:33:34 -0700766 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
767
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700768 /*
769 * This function is to make sure that all the active capture usecases
770 * are always routed to the same input sound device.
771 * For example, if audio-record and voice-call usecases are currently
772 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
773 * is received for voice call then we have to make sure that audio-record
774 * usecase is also switched to earpiece i.e. voice-dmic-ef,
775 * because of the limitation that two devices cannot be enabled
776 * at the same time if they share the same backend.
777 */
778 for (i = 0; i < AUDIO_USECASE_MAX; i++)
779 switch_device[i] = false;
780
781 list_for_each(node, &adev->usecase_list) {
782 usecase = node_to_item(node, struct audio_usecase, list);
783 if (usecase->type != PCM_PLAYBACK &&
784 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700785 usecase->in_snd_device != snd_device &&
786 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700787 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
788 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700789 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700790 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700791 switch_device[usecase->id] = true;
792 num_uc_to_switch++;
793 }
794 }
795
796 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700797 list_for_each(node, &adev->usecase_list) {
798 usecase = node_to_item(node, struct audio_usecase, list);
799 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700800 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700801 }
802 }
803
804 list_for_each(node, &adev->usecase_list) {
805 usecase = node_to_item(node, struct audio_usecase, list);
806 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700807 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700808 }
809 }
810
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700811 /* Re-route all the usecases on the shared backend other than the
812 specified usecase to new snd devices */
813 list_for_each(node, &adev->usecase_list) {
814 usecase = node_to_item(node, struct audio_usecase, list);
815 /* Update the in_snd_device only before enabling the audio route */
816 if (switch_device[usecase->id] ) {
817 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700818 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700819 }
820 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700821 }
822}
823
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800824/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700825static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800826{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700827 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700828 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800829
830 switch (channels) {
831 /*
832 * Do not handle stereo output in Multi-channel cases
833 * Stereo case is handled in normal playback path
834 */
835 case 6:
836 ALOGV("%s: HDMI supports 5.1", __func__);
837 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
838 break;
839 case 8:
840 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
841 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
842 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
843 break;
844 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700845 ALOGE("HDMI does not support multi channel playback");
846 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800847 break;
848 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700849 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800850}
851
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -0700852static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
853{
854 struct audio_usecase *usecase;
855 struct listnode *node;
856
857 list_for_each(node, &adev->usecase_list) {
858 usecase = node_to_item(node, struct audio_usecase, list);
859 if (usecase->type == VOICE_CALL) {
860 ALOGV("%s: usecase id %d", __func__, usecase->id);
861 return usecase->id;
862 }
863 }
864 return USECASE_INVALID;
865}
866
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800867struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
868 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700869{
870 struct audio_usecase *usecase;
871 struct listnode *node;
872
873 list_for_each(node, &adev->usecase_list) {
874 usecase = node_to_item(node, struct audio_usecase, list);
875 if (usecase->id == uc_id)
876 return usecase;
877 }
878 return NULL;
879}
880
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800881int select_devices(struct audio_device *adev,
882 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800883{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800884 snd_device_t out_snd_device = SND_DEVICE_NONE;
885 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700886 struct audio_usecase *usecase = NULL;
887 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800888 struct audio_usecase *hfp_usecase = NULL;
889 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800890 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700891 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800892
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700893 usecase = get_usecase_from_list(adev, uc_id);
894 if (usecase == NULL) {
895 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
896 return -EINVAL;
897 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800898
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800899 if ((usecase->type == VOICE_CALL) ||
900 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700901 out_snd_device = platform_get_output_snd_device(adev->platform,
902 usecase->stream.out->devices);
903 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700904 usecase->devices = usecase->stream.out->devices;
905 } else {
906 /*
907 * If the voice call is active, use the sound devices of voice call usecase
908 * so that it would not result any device switch. All the usecases will
909 * be switched to new device when select_devices() is called for voice call
910 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700911 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700912 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700913 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -0700914 vc_usecase = get_usecase_from_list(adev,
915 get_voice_usecase_id_from_list(adev));
916 if ((vc_usecase != NULL) &&
917 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
918 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700919 in_snd_device = vc_usecase->in_snd_device;
920 out_snd_device = vc_usecase->out_snd_device;
921 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800922 } else if (audio_extn_hfp_is_active(adev)) {
923 hfp_ucid = audio_extn_hfp_get_usecase();
924 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
925 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
926 in_snd_device = hfp_usecase->in_snd_device;
927 out_snd_device = hfp_usecase->out_snd_device;
928 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700929 }
930 if (usecase->type == PCM_PLAYBACK) {
931 usecase->devices = usecase->stream.out->devices;
932 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700933 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700934 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700935 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700936 if (usecase->stream.out == adev->primary_output &&
937 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -0700938 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
939 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -0800940 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700941 select_devices(adev, adev->active_input->usecase);
942 }
943 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700944 } else if (usecase->type == PCM_CAPTURE) {
945 usecase->devices = usecase->stream.in->device;
946 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700947 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700948 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -0700949 if (adev->active_input &&
950 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
951 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -0800952 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -0700953 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
954 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
955 } else if (adev->primary_output) {
956 out_device = adev->primary_output->devices;
957 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700958 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700959 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700960 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700961 }
962 }
963
964 if (out_snd_device == usecase->out_snd_device &&
965 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800966 return 0;
967 }
968
Eric Laurent2bafff12016-03-17 12:17:23 -0700969 if (out_snd_device != SND_DEVICE_NONE &&
970 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
971 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
972 __func__,
973 use_case_table[uc_id],
974 adev->last_logged_snd_device[uc_id][0],
975 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
976 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
977 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
978 -1,
979 out_snd_device,
980 platform_get_snd_device_name(out_snd_device),
981 platform_get_snd_device_acdb_id(out_snd_device));
982 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
983 }
984 if (in_snd_device != SND_DEVICE_NONE &&
985 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
986 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
987 __func__,
988 use_case_table[uc_id],
989 adev->last_logged_snd_device[uc_id][1],
990 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
991 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
992 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
993 -1,
994 in_snd_device,
995 platform_get_snd_device_name(in_snd_device),
996 platform_get_snd_device_acdb_id(in_snd_device));
997 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
998 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800999
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001000 /*
1001 * Limitation: While in call, to do a device switch we need to disable
1002 * and enable both RX and TX devices though one of them is same as current
1003 * device.
1004 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001005 if ((usecase->type == VOICE_CALL) &&
1006 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1007 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001008 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001009 /* Disable sidetone only if voice call already exists */
1010 if (voice_is_call_state_active(adev))
1011 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001012 }
1013
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001014 /* Disable current sound devices */
1015 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001016 disable_audio_route(adev, usecase);
1017 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001018 }
1019
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001020 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001021 disable_audio_route(adev, usecase);
1022 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001023 }
1024
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001025 /* Applicable only on the targets that has external modem.
1026 * New device information should be sent to modem before enabling
1027 * the devices to reduce in-call device switch time.
1028 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001029 if ((usecase->type == VOICE_CALL) &&
1030 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1031 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001032 status = platform_switch_voice_call_enable_device_config(adev->platform,
1033 out_snd_device,
1034 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001035 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001036
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001037 /* Enable new sound devices */
1038 if (out_snd_device != SND_DEVICE_NONE) {
1039 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001040 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001041 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001042 }
1043
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001044 if (in_snd_device != SND_DEVICE_NONE) {
1045 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001046 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001047 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001048
Eric Laurentb23d5282013-05-14 15:27:20 -07001049 if (usecase->type == VOICE_CALL)
1050 status = platform_switch_voice_call_device_post(adev->platform,
1051 out_snd_device,
1052 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001053
sangwoo170731f2013-06-08 15:36:36 +09001054 usecase->in_snd_device = in_snd_device;
1055 usecase->out_snd_device = out_snd_device;
1056
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001057 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001058
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001059 /* Applicable only on the targets that has external modem.
1060 * Enable device command should be sent to modem only after
1061 * enabling voice call mixer controls
1062 */
vivek mehta765eb642015-08-07 19:46:06 -07001063 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001064 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1065 out_snd_device,
1066 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001067 /* Enable sidetone only if voice call already exists */
1068 if (voice_is_call_state_active(adev))
1069 voice_set_sidetone(adev, out_snd_device, true);
1070 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001071
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001072 return status;
1073}
1074
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001075static int stop_input_stream(struct stream_in *in)
1076{
1077 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001078 struct audio_usecase *uc_info;
1079 struct audio_device *adev = in->dev;
1080
Eric Laurentc8400632013-02-14 19:04:54 -08001081 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001082
Eric Laurent994a6932013-07-17 11:51:42 -07001083 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001084 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001085 uc_info = get_usecase_from_list(adev, in->usecase);
1086 if (uc_info == NULL) {
1087 ALOGE("%s: Could not find the usecase (%d) in the list",
1088 __func__, in->usecase);
1089 return -EINVAL;
1090 }
1091
Eric Laurent150dbfe2013-02-27 14:31:02 -08001092 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001093 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001094
1095 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001096 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001097
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001098 list_remove(&uc_info->list);
1099 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001100
Eric Laurent994a6932013-07-17 11:51:42 -07001101 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001102 return ret;
1103}
1104
1105int start_input_stream(struct stream_in *in)
1106{
1107 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001108 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001109 struct audio_usecase *uc_info;
1110 struct audio_device *adev = in->dev;
1111
Eric Laurent994a6932013-07-17 11:51:42 -07001112 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001113
1114 if (in->card_status == CARD_STATUS_OFFLINE ||
1115 adev->card_status == CARD_STATUS_OFFLINE) {
1116 ALOGW("in->card_status or adev->card_status offline, try again");
1117 ret = -EAGAIN;
1118 goto error_config;
1119 }
1120
Eric Laurentb23d5282013-05-14 15:27:20 -07001121 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001122 if (in->pcm_device_id < 0) {
1123 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1124 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001125 ret = -EINVAL;
1126 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001127 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001128
1129 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001130 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1131 uc_info->id = in->usecase;
1132 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001133 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001134 uc_info->devices = in->device;
1135 uc_info->in_snd_device = SND_DEVICE_NONE;
1136 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001137
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001138 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001139
1140 audio_extn_perf_lock_acquire();
1141
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001142 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001143
Eric Laurentc8400632013-02-14 19:04:54 -08001144 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001145 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001146
Andy Hung6ebe5962016-01-15 17:46:57 -08001147 unsigned int flags = PCM_IN | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001148 unsigned int pcm_open_retry_count = 0;
1149
1150 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1151 flags |= PCM_MMAP | PCM_NOIRQ;
1152 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001153 } else if (in->realtime) {
1154 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001155 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001156
1157 while (1) {
1158 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1159 flags, &in->config);
1160 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1161 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1162 if (in->pcm != NULL) {
1163 pcm_close(in->pcm);
1164 in->pcm = NULL;
1165 }
1166 if (pcm_open_retry_count-- == 0) {
1167 ret = -EIO;
1168 goto error_open;
1169 }
1170 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1171 continue;
1172 }
1173 break;
1174 }
1175
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001176 ALOGV("%s: pcm_prepare", __func__);
1177 ret = pcm_prepare(in->pcm);
1178 if (ret < 0) {
1179 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1180 pcm_close(in->pcm);
1181 in->pcm = NULL;
1182 goto error_open;
1183 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001184 if (in->realtime) {
1185 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001186 if (ret < 0) {
1187 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1188 pcm_close(in->pcm);
1189 in->pcm = NULL;
1190 goto error_open;
1191 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001192 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001193 register_in_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001194 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001195 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001196
Eric Laurentc8400632013-02-14 19:04:54 -08001197 return ret;
1198
1199error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001200 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001201 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001202
1203error_config:
1204 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001205 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001206
1207 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001208}
1209
Eric Laurenta1478072015-09-21 17:21:52 -07001210void lock_input_stream(struct stream_in *in)
1211{
1212 pthread_mutex_lock(&in->pre_lock);
1213 pthread_mutex_lock(&in->lock);
1214 pthread_mutex_unlock(&in->pre_lock);
1215}
1216
1217void lock_output_stream(struct stream_out *out)
1218{
1219 pthread_mutex_lock(&out->pre_lock);
1220 pthread_mutex_lock(&out->lock);
1221 pthread_mutex_unlock(&out->pre_lock);
1222}
1223
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001224/* must be called with out->lock locked */
1225static int send_offload_cmd_l(struct stream_out* out, int command)
1226{
1227 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1228
1229 ALOGVV("%s %d", __func__, command);
1230
1231 cmd->cmd = command;
1232 list_add_tail(&out->offload_cmd_list, &cmd->node);
1233 pthread_cond_signal(&out->offload_cond);
1234 return 0;
1235}
1236
1237/* must be called iwth out->lock locked */
1238static void stop_compressed_output_l(struct stream_out *out)
1239{
1240 out->offload_state = OFFLOAD_STATE_IDLE;
1241 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001242 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001243 if (out->compr != NULL) {
1244 compress_stop(out->compr);
1245 while (out->offload_thread_blocked) {
1246 pthread_cond_wait(&out->cond, &out->lock);
1247 }
1248 }
1249}
1250
1251static void *offload_thread_loop(void *context)
1252{
1253 struct stream_out *out = (struct stream_out *) context;
1254 struct listnode *item;
1255
1256 out->offload_state = OFFLOAD_STATE_IDLE;
1257 out->playback_started = 0;
1258
1259 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1260 set_sched_policy(0, SP_FOREGROUND);
1261 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1262
1263 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001264 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001265 for (;;) {
1266 struct offload_cmd *cmd = NULL;
1267 stream_callback_event_t event;
1268 bool send_callback = false;
1269
1270 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1271 __func__, list_empty(&out->offload_cmd_list),
1272 out->offload_state);
1273 if (list_empty(&out->offload_cmd_list)) {
1274 ALOGV("%s SLEEPING", __func__);
1275 pthread_cond_wait(&out->offload_cond, &out->lock);
1276 ALOGV("%s RUNNING", __func__);
1277 continue;
1278 }
1279
1280 item = list_head(&out->offload_cmd_list);
1281 cmd = node_to_item(item, struct offload_cmd, node);
1282 list_remove(item);
1283
1284 ALOGVV("%s STATE %d CMD %d out->compr %p",
1285 __func__, out->offload_state, cmd->cmd, out->compr);
1286
1287 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1288 free(cmd);
1289 break;
1290 }
1291
1292 if (out->compr == NULL) {
1293 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001294 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001295 pthread_cond_signal(&out->cond);
1296 continue;
1297 }
1298 out->offload_thread_blocked = true;
1299 pthread_mutex_unlock(&out->lock);
1300 send_callback = false;
1301 switch(cmd->cmd) {
1302 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1303 compress_wait(out->compr, -1);
1304 send_callback = true;
1305 event = STREAM_CBK_EVENT_WRITE_READY;
1306 break;
1307 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001308 compress_next_track(out->compr);
1309 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001310 send_callback = true;
1311 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001312 /* Resend the metadata for next iteration */
1313 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001314 break;
1315 case OFFLOAD_CMD_DRAIN:
1316 compress_drain(out->compr);
1317 send_callback = true;
1318 event = STREAM_CBK_EVENT_DRAIN_READY;
1319 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001320 case OFFLOAD_CMD_ERROR:
1321 send_callback = true;
1322 event = STREAM_CBK_EVENT_ERROR;
1323 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001324 default:
1325 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1326 break;
1327 }
Eric Laurenta1478072015-09-21 17:21:52 -07001328 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001329 out->offload_thread_blocked = false;
1330 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001331 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001332 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001333 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001334 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001335 free(cmd);
1336 }
1337
1338 pthread_cond_signal(&out->cond);
1339 while (!list_empty(&out->offload_cmd_list)) {
1340 item = list_head(&out->offload_cmd_list);
1341 list_remove(item);
1342 free(node_to_item(item, struct offload_cmd, node));
1343 }
1344 pthread_mutex_unlock(&out->lock);
1345
1346 return NULL;
1347}
1348
1349static int create_offload_callback_thread(struct stream_out *out)
1350{
1351 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1352 list_init(&out->offload_cmd_list);
1353 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1354 offload_thread_loop, out);
1355 return 0;
1356}
1357
1358static int destroy_offload_callback_thread(struct stream_out *out)
1359{
Eric Laurenta1478072015-09-21 17:21:52 -07001360 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001361 stop_compressed_output_l(out);
1362 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1363
1364 pthread_mutex_unlock(&out->lock);
1365 pthread_join(out->offload_thread, (void **) NULL);
1366 pthread_cond_destroy(&out->offload_cond);
1367
1368 return 0;
1369}
1370
Eric Laurent07eeafd2013-10-06 12:52:49 -07001371static bool allow_hdmi_channel_config(struct audio_device *adev)
1372{
1373 struct listnode *node;
1374 struct audio_usecase *usecase;
1375 bool ret = true;
1376
1377 list_for_each(node, &adev->usecase_list) {
1378 usecase = node_to_item(node, struct audio_usecase, list);
1379 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1380 /*
1381 * If voice call is already existing, do not proceed further to avoid
1382 * disabling/enabling both RX and TX devices, CSD calls, etc.
1383 * Once the voice call done, the HDMI channels can be configured to
1384 * max channels of remaining use cases.
1385 */
1386 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001387 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001388 __func__);
1389 ret = false;
1390 break;
1391 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
Joe Onorato188b6222016-03-01 11:02:27 -08001392 ALOGV("%s: multi channel playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001393 "no change in HDMI channels", __func__);
1394 ret = false;
1395 break;
1396 }
1397 }
1398 }
1399 return ret;
1400}
1401
1402static int check_and_set_hdmi_channels(struct audio_device *adev,
1403 unsigned int channels)
1404{
1405 struct listnode *node;
1406 struct audio_usecase *usecase;
1407
1408 /* Check if change in HDMI channel config is allowed */
1409 if (!allow_hdmi_channel_config(adev))
1410 return 0;
1411
1412 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001413 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001414 return 0;
1415 }
1416
1417 platform_set_hdmi_channels(adev->platform, channels);
1418 adev->cur_hdmi_channels = channels;
1419
1420 /*
1421 * Deroute all the playback streams routed to HDMI so that
1422 * the back end is deactivated. Note that backend will not
1423 * be deactivated if any one stream is connected to it.
1424 */
1425 list_for_each(node, &adev->usecase_list) {
1426 usecase = node_to_item(node, struct audio_usecase, list);
1427 if (usecase->type == PCM_PLAYBACK &&
1428 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001429 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001430 }
1431 }
1432
1433 /*
1434 * Enable all the streams disabled above. Now the HDMI backend
1435 * will be activated with new channel configuration
1436 */
1437 list_for_each(node, &adev->usecase_list) {
1438 usecase = node_to_item(node, struct audio_usecase, list);
1439 if (usecase->type == PCM_PLAYBACK &&
1440 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001441 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001442 }
1443 }
1444
1445 return 0;
1446}
1447
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001448static int stop_output_stream(struct stream_out *out)
1449{
1450 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001451 struct audio_usecase *uc_info;
1452 struct audio_device *adev = out->dev;
1453
Eric Laurent994a6932013-07-17 11:51:42 -07001454 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001455 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001456 uc_info = get_usecase_from_list(adev, out->usecase);
1457 if (uc_info == NULL) {
1458 ALOGE("%s: Could not find the usecase (%d) in the list",
1459 __func__, out->usecase);
1460 return -EINVAL;
1461 }
1462
Haynes Mathew George41f86652014-06-17 14:22:15 -07001463 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1464 if (adev->visualizer_stop_output != NULL)
1465 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1466 if (adev->offload_effects_stop_output != NULL)
1467 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1468 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001469
Eric Laurent150dbfe2013-02-27 14:31:02 -08001470 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001471 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001472
1473 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001474 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001475
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001476 list_remove(&uc_info->list);
1477 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001478
Eric Laurent0499d4f2014-08-25 22:39:29 -05001479 audio_extn_extspk_update(adev->extspk);
1480
Eric Laurent07eeafd2013-10-06 12:52:49 -07001481 /* Must be called after removing the usecase from list */
1482 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1483 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1484
Eric Laurent994a6932013-07-17 11:51:42 -07001485 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001486 return ret;
1487}
1488
1489int start_output_stream(struct stream_out *out)
1490{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001491 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001492 struct audio_usecase *uc_info;
1493 struct audio_device *adev = out->dev;
1494
Eric Laurent994a6932013-07-17 11:51:42 -07001495 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001496 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001497
1498 if (out->card_status == CARD_STATUS_OFFLINE ||
1499 adev->card_status == CARD_STATUS_OFFLINE) {
1500 ALOGW("out->card_status or adev->card_status offline, try again");
1501 ret = -EAGAIN;
1502 goto error_config;
1503 }
1504
Eric Laurentb23d5282013-05-14 15:27:20 -07001505 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001506 if (out->pcm_device_id < 0) {
1507 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1508 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001509 ret = -EINVAL;
1510 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001511 }
1512
1513 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1514 uc_info->id = out->usecase;
1515 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001516 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001517 uc_info->devices = out->devices;
1518 uc_info->in_snd_device = SND_DEVICE_NONE;
1519 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001520
Eric Laurent07eeafd2013-10-06 12:52:49 -07001521 /* This must be called before adding this usecase to the list */
1522 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1523 check_and_set_hdmi_channels(adev, out->config.channels);
1524
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001525 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001526
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001527 audio_extn_perf_lock_acquire();
1528
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001529 select_devices(adev, out->usecase);
1530
Eric Laurent0499d4f2014-08-25 22:39:29 -05001531 audio_extn_extspk_update(adev->extspk);
1532
Andy Hung31aca912014-03-20 17:14:59 -07001533 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001534 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001535 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001536 unsigned int flags = PCM_OUT;
1537 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001538
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001539 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1540 flags |= PCM_MMAP | PCM_NOIRQ;
1541 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001542 } else if (out->realtime) {
1543 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001544 } else
1545 flags |= PCM_MONOTONIC;
1546
1547 while (1) {
1548 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1549 flags, &out->config);
1550 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1551 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1552 if (out->pcm != NULL) {
1553 pcm_close(out->pcm);
1554 out->pcm = NULL;
1555 }
1556 if (pcm_open_retry_count-- == 0) {
1557 ret = -EIO;
1558 goto error_open;
1559 }
1560 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1561 continue;
1562 }
1563 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001564 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001565 ALOGV("%s: pcm_prepare", __func__);
1566 if (pcm_is_ready(out->pcm)) {
1567 ret = pcm_prepare(out->pcm);
1568 if (ret < 0) {
1569 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1570 pcm_close(out->pcm);
1571 out->pcm = NULL;
1572 goto error_open;
1573 }
1574 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001575 } else {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001576 out->pcm = NULL;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001577 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001578 COMPRESS_IN, &out->compr_config);
1579 if (out->compr && !is_compress_ready(out->compr)) {
1580 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1581 compress_close(out->compr);
1582 out->compr = NULL;
1583 ret = -EIO;
1584 goto error_open;
1585 }
1586 if (out->offload_callback)
1587 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001588
1589 if (adev->visualizer_start_output != NULL)
Haynes Mathew George41f86652014-06-17 14:22:15 -07001590 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1591 if (adev->offload_effects_start_output != NULL)
1592 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001593 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001594 ret = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001595 if (out->realtime) {
1596 ret = pcm_start(out->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001597 if (ret < 0) {
1598 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1599 pcm_close(out->pcm);
1600 out->pcm = NULL;
1601 goto error_open;
1602 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001603 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001604 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001605 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001606 ALOGV("%s: exit", __func__);
Haynes Mathew George03c40102016-01-29 17:57:48 -08001607 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001608error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001609 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001610 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001611error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001612 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001613}
1614
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001615static int check_input_parameters(uint32_t sample_rate,
1616 audio_format_t format,
1617 int channel_count)
1618{
vivek mehta4ed66e62016-04-15 23:33:34 -07001619 if ((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT)) {
vivek mehtadae44712015-07-27 14:13:18 -07001620 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1621 return -EINVAL;
1622 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001623
vivek mehtadae44712015-07-27 14:13:18 -07001624 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > MAX_CHANNEL_COUNT)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001625 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
vivek mehtadae44712015-07-27 14:13:18 -07001626 channel_count, MIN_CHANNEL_COUNT, MAX_CHANNEL_COUNT);
1627 return -EINVAL;
1628 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001629
1630 switch (sample_rate) {
1631 case 8000:
1632 case 11025:
1633 case 12000:
1634 case 16000:
1635 case 22050:
1636 case 24000:
1637 case 32000:
1638 case 44100:
1639 case 48000:
1640 break;
1641 default:
vivek mehtadae44712015-07-27 14:13:18 -07001642 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001643 return -EINVAL;
1644 }
1645
1646 return 0;
1647}
1648
1649static size_t get_input_buffer_size(uint32_t sample_rate,
1650 audio_format_t format,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001651 int channel_count,
1652 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001653{
1654 size_t size = 0;
1655
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001656 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1657 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001658
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001659 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001660 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001661 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07001662
1663 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001664
Glenn Kasten4f993392014-05-14 07:30:48 -07001665 /* make sure the size is multiple of 32 bytes
1666 * At 48 kHz mono 16-bit PCM:
1667 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1668 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1669 */
1670 size += 0x1f;
1671 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001672
1673 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001674}
1675
1676static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1677{
1678 struct stream_out *out = (struct stream_out *)stream;
1679
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001680 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001681}
1682
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001683static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001684{
1685 return -ENOSYS;
1686}
1687
1688static size_t out_get_buffer_size(const struct audio_stream *stream)
1689{
1690 struct stream_out *out = (struct stream_out *)stream;
1691
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001692 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1693 return out->compr_config.fragment_size;
1694 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001695 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07001696 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001697}
1698
1699static uint32_t out_get_channels(const struct audio_stream *stream)
1700{
1701 struct stream_out *out = (struct stream_out *)stream;
1702
1703 return out->channel_mask;
1704}
1705
1706static audio_format_t out_get_format(const struct audio_stream *stream)
1707{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001708 struct stream_out *out = (struct stream_out *)stream;
1709
1710 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001711}
1712
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001713static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001714{
1715 return -ENOSYS;
1716}
1717
1718static int out_standby(struct audio_stream *stream)
1719{
1720 struct stream_out *out = (struct stream_out *)stream;
1721 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001722
Eric Laurent994a6932013-07-17 11:51:42 -07001723 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001724 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001725
Eric Laurenta1478072015-09-21 17:21:52 -07001726 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001727 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001728 if (adev->adm_deregister_stream)
1729 adev->adm_deregister_stream(adev->adm_data, out->handle);
1730
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001731 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001732 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001733 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1734 if (out->pcm) {
1735 pcm_close(out->pcm);
1736 out->pcm = NULL;
1737 }
1738 } else {
1739 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001740 out->gapless_mdata.encoder_delay = 0;
1741 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001742 if (out->compr != NULL) {
1743 compress_close(out->compr);
1744 out->compr = NULL;
1745 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001746 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001747 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001748 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001749 }
1750 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001751 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001752 return 0;
1753}
1754
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001755static int out_on_error(struct audio_stream *stream)
1756{
1757 struct stream_out *out = (struct stream_out *)stream;
1758 struct audio_device *adev = out->dev;
1759 bool do_standby = false;
1760
1761 lock_output_stream(out);
1762 if (!out->standby) {
1763 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1764 stop_compressed_output_l(out);
1765 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
1766 } else
1767 do_standby = true;
1768 }
1769 pthread_mutex_unlock(&out->lock);
1770
1771 if (do_standby)
1772 return out_standby(&out->stream.common);
1773
1774 return 0;
1775}
1776
Andy Hung7401c7c2016-09-21 12:41:21 -07001777static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001778{
Andy Hung7401c7c2016-09-21 12:41:21 -07001779 struct stream_out *out = (struct stream_out *)stream;
1780
1781 // We try to get the lock for consistency,
1782 // but it isn't necessary for these variables.
1783 // If we're not in standby, we may be blocked on a write.
1784 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
1785 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
1786 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
1787
1788 if (locked) {
1789 log_dump_l(&out->error_log, fd);
1790 pthread_mutex_unlock(&out->lock);
1791 } else {
1792 // We don't have the lock here, copy for safety.
1793 struct error_log log = out->error_log;
1794 log_dump_l(&log, fd);
1795 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001796 return 0;
1797}
1798
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001799static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1800{
1801 int ret = 0;
1802 char value[32];
1803 struct compr_gapless_mdata tmp_mdata;
1804
1805 if (!out || !parms) {
1806 return -EINVAL;
1807 }
1808
1809 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1810 if (ret >= 0) {
1811 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
1812 } else {
1813 return -EINVAL;
1814 }
1815
1816 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1817 if (ret >= 0) {
1818 tmp_mdata.encoder_padding = atoi(value);
1819 } else {
1820 return -EINVAL;
1821 }
1822
1823 out->gapless_mdata = tmp_mdata;
1824 out->send_new_metadata = 1;
1825 ALOGV("%s new encoder delay %u and padding %u", __func__,
1826 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1827
1828 return 0;
1829}
1830
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001831static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1832{
1833 return out == adev->primary_output || out == adev->voice_tx_output;
1834}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001835
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001836static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1837{
1838 struct stream_out *out = (struct stream_out *)stream;
1839 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001840 struct audio_usecase *usecase;
1841 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001842 struct str_parms *parms;
1843 char value[32];
1844 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001845 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07001846 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001847
Eric Laurent2e140aa2016-06-30 17:14:46 -07001848 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001849 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001850 parms = str_parms_create_str(kvpairs);
1851 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1852 if (ret >= 0) {
1853 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07001854 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001855 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001856
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001857 /*
1858 * When HDMI cable is unplugged the music playback is paused and
1859 * the policy manager sends routing=0. But the audioflinger
1860 * continues to write data until standby time (3sec).
1861 * As the HDMI core is turned off, the write gets blocked.
1862 * Avoid this by routing audio to speaker until standby.
1863 */
1864 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
1865 val == AUDIO_DEVICE_NONE) {
1866 val = AUDIO_DEVICE_OUT_SPEAKER;
1867 }
1868
1869 /*
1870 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001871 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001872 * the select_devices(). But how do we undo this?
1873 *
1874 * For example, music playback is active on headset (deep-buffer usecase)
1875 * and if we go to ringtones and select a ringtone, low-latency usecase
1876 * will be started on headset+speaker. As we can't enable headset+speaker
1877 * and headset devices at the same time, select_devices() switches the music
1878 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1879 * So when the ringtone playback is completed, how do we undo the same?
1880 *
1881 * We are relying on the out_set_parameters() call on deep-buffer output,
1882 * once the ringtone playback is ended.
1883 * NOTE: We should not check if the current devices are same as new devices.
1884 * Because select_devices() must be called to switch back the music
1885 * playback to headset.
1886 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08001887 audio_devices_t new_dev = val;
1888 if (new_dev != AUDIO_DEVICE_NONE) {
1889 bool same_dev = out->devices == new_dev;
1890 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001891
Eric Laurenta7657192014-10-09 21:09:33 -07001892 if (output_drives_call(adev, out)) {
1893 if (!voice_is_in_call(adev)) {
1894 if (adev->mode == AUDIO_MODE_IN_CALL) {
1895 adev->current_call_output = out;
1896 ret = voice_start_call(adev);
1897 }
1898 } else {
1899 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001900 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07001901 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001902 }
vivek mehta0d3637a2016-07-24 09:32:02 -07001903
1904 if (!out->standby) {
1905 if (!same_dev) {
1906 ALOGV("update routing change");
1907 out->routing_change = true;
1908 }
1909 select_devices(adev, out->usecase);
1910 }
1911
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001912 }
1913
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001914 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001915 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05001916
1917 /*handles device and call state changes*/
1918 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001919 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001920
1921 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1922 parse_compress_metadata(out, parms);
1923 }
1924
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001925 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07001926 ALOGV("%s: exit: code(%d)", __func__, status);
1927 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001928}
1929
1930static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1931{
1932 struct stream_out *out = (struct stream_out *)stream;
1933 struct str_parms *query = str_parms_create_str(keys);
1934 char *str;
1935 char value[256];
1936 struct str_parms *reply = str_parms_create();
1937 size_t i, j;
1938 int ret;
1939 bool first = true;
Eric Laurent994a6932013-07-17 11:51:42 -07001940 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001941 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1942 if (ret >= 0) {
1943 value[0] = '\0';
1944 i = 0;
1945 while (out->supported_channel_masks[i] != 0) {
1946 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1947 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1948 if (!first) {
1949 strcat(value, "|");
1950 }
1951 strcat(value, out_channels_name_to_enum_table[j].name);
1952 first = false;
1953 break;
1954 }
1955 }
1956 i++;
1957 }
1958 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1959 str = str_parms_to_str(reply);
1960 } else {
1961 str = strdup(keys);
1962 }
1963 str_parms_destroy(query);
1964 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07001965 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001966 return str;
1967}
1968
1969static uint32_t out_get_latency(const struct audio_stream_out *stream)
1970{
Haynes Mathew George03c40102016-01-29 17:57:48 -08001971 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001972 struct stream_out *out = (struct stream_out *)stream;
1973
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001974 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
1975 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001976 else if (out->realtime) {
1977 // since the buffer won't be filled up faster than realtime,
1978 // return a smaller number
1979 period_ms = (out->af_period_multiplier * out->config.period_size *
1980 1000) / (out->config.rate);
1981 hw_delay = platform_render_latency(out->usecase)/1000;
1982 return period_ms + hw_delay;
1983 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001984
1985 return (out->config.period_count * out->config.period_size * 1000) /
1986 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001987}
1988
1989static int out_set_volume(struct audio_stream_out *stream, float left,
1990 float right)
1991{
Eric Laurenta9024de2013-04-04 09:19:12 -07001992 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001993 int volume[2];
1994
Eric Laurenta9024de2013-04-04 09:19:12 -07001995 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1996 /* only take left channel into account: the API is for stereo anyway */
1997 out->muted = (left == 0.0f);
1998 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001999 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2000 const char *mixer_ctl_name = "Compress Playback Volume";
2001 struct audio_device *adev = out->dev;
2002 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002003 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2004 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002005 /* try with the control based on device id */
2006 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2007 PCM_PLAYBACK);
2008 char ctl_name[128] = {0};
2009 snprintf(ctl_name, sizeof(ctl_name),
2010 "Compress Playback %d Volume", pcm_device_id);
2011 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2012 if (!ctl) {
2013 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2014 return -EINVAL;
2015 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002016 }
2017 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2018 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2019 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2020 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002021 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002022
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002023 return -ENOSYS;
2024}
2025
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002026// note: this call is safe only if the stream_cb is
2027// removed first in close_output_stream (as is done now).
2028static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2029{
2030 if (!stream || !parms)
2031 return;
2032
2033 struct stream_out *out = (struct stream_out *)stream;
2034 struct audio_device *adev = out->dev;
2035
2036 card_status_t status;
2037 int card;
2038 if (parse_snd_card_status(parms, &card, &status) < 0)
2039 return;
2040
2041 pthread_mutex_lock(&adev->lock);
2042 bool valid_cb = (card == adev->snd_card);
2043 pthread_mutex_unlock(&adev->lock);
2044
2045 if (!valid_cb)
2046 return;
2047
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002048 lock_output_stream(out);
2049 if (out->card_status != status)
2050 out->card_status = status;
2051 pthread_mutex_unlock(&out->lock);
2052
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002053 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2054 use_case_table[out->usecase],
2055 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2056
2057 if (status == CARD_STATUS_OFFLINE)
2058 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002059
2060 return;
2061}
2062
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002063#ifdef NO_AUDIO_OUT
2064static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
2065 const void *buffer, size_t bytes)
2066{
2067 struct stream_out *out = (struct stream_out *)stream;
2068
2069 /* No Output device supported other than BT for playback.
2070 * Sleep for the amount of buffer duration
2071 */
Eric Laurenta1478072015-09-21 17:21:52 -07002072 lock_output_stream(out);
Uday Kishore Pasupuletib14d76b2015-11-13 20:06:37 -08002073 usleep(bytes * 1000000 / audio_stream_out_frame_size(&out->stream.common) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002074 out_get_sample_rate(&out->stream.common));
2075 pthread_mutex_unlock(&out->lock);
2076 return bytes;
2077}
2078#endif
2079
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002080static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2081 size_t bytes)
2082{
2083 struct stream_out *out = (struct stream_out *)stream;
2084 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002085 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002086 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002087
Eric Laurenta1478072015-09-21 17:21:52 -07002088 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002089 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002090 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002091 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002092 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002093 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002094 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002095 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002096 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002097 goto exit;
2098 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002099
2100 if (last_known_cal_step != -1) {
2101 ALOGD("%s: retry previous failed cal level set", __func__);
2102 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2103 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002104 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002105
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002106 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002107 ALOGVV("%s: writing buffer (%d bytes) to compress device", __func__, bytes);
2108 if (out->send_new_metadata) {
2109 ALOGVV("send new gapless metadata");
2110 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2111 out->send_new_metadata = 0;
2112 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002113 unsigned int avail;
2114 struct timespec tstamp;
2115 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2116 /* Do not limit write size if the available frames count is unknown */
2117 if (ret != 0) {
2118 avail = bytes;
2119 }
2120 if (avail == 0) {
2121 ret = 0;
2122 } else {
2123 if (avail > bytes) {
2124 avail = bytes;
2125 }
2126 ret = compress_write(out->compr, buffer, avail);
2127 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2128 __func__, avail, ret);
2129 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002130
Eric Laurent6e895242013-09-05 16:10:57 -07002131 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002132 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2133 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002134 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002135 compress_start(out->compr);
2136 out->playback_started = 1;
2137 out->offload_state = OFFLOAD_STATE_PLAYING;
2138 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002139 if (ret < 0) {
2140 log_error_l(&out->error_log, ERROR_CODE_WRITE);
2141 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002142 pthread_mutex_unlock(&out->lock);
2143 return ret;
2144 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002145 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002146 if (out->pcm) {
2147 if (out->muted)
2148 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002149
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002150 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002151
Haynes Mathew George03c40102016-01-29 17:57:48 -08002152 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2153 out->config.rate;
2154 request_out_focus(out, ns);
2155
2156 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2157 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002158 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002159 else
2160 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002161
Haynes Mathew George03c40102016-01-29 17:57:48 -08002162 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002163 } else {
2164 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002165 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002166 }
2167
2168exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002169 // For PCM we always consume the buffer and return #bytes regardless of ret.
2170 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2171 out->written += bytes / (out->config.channels * sizeof(short));
2172 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002173 long long sleeptime_us = 0;
2174 if (ret != 0) {
2175 log_error_l(&out->error_log, error_code);
2176 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2177 ALOGE_IF(out->pcm != NULL,
2178 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
2179 sleeptime_us = bytes * 1000000LL / audio_stream_out_frame_size(stream) /
2180 out_get_sample_rate(&out->stream.common);
2181 // usleep not guaranteed for values over 1 second but we don't limit here.
2182 }
2183 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002184
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002185 pthread_mutex_unlock(&out->lock);
2186
2187 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002188 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002189 if (sleeptime_us != 0)
2190 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002191 }
2192 return bytes;
2193}
2194
2195static int out_get_render_position(const struct audio_stream_out *stream,
2196 uint32_t *dsp_frames)
2197{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002198 struct stream_out *out = (struct stream_out *)stream;
2199 *dsp_frames = 0;
2200 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002201 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002202 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002203 unsigned long frames = 0;
2204 // TODO: check return value
2205 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2206 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002207 ALOGVV("%s rendered frames %d sample_rate %d",
2208 __func__, *dsp_frames, out->sample_rate);
2209 }
2210 pthread_mutex_unlock(&out->lock);
2211 return 0;
2212 } else
2213 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002214}
2215
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002216static int out_add_audio_effect(const struct audio_stream *stream __unused,
2217 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002218{
2219 return 0;
2220}
2221
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002222static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2223 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002224{
2225 return 0;
2226}
2227
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002228static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2229 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002230{
2231 return -EINVAL;
2232}
2233
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002234static int out_get_presentation_position(const struct audio_stream_out *stream,
2235 uint64_t *frames, struct timespec *timestamp)
2236{
2237 struct stream_out *out = (struct stream_out *)stream;
Andy Hung7171da22016-03-08 16:58:42 -08002238 int ret = -EINVAL;
Eric Laurent949a0892013-09-20 09:20:13 -07002239 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002240
Eric Laurenta1478072015-09-21 17:21:52 -07002241 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002242
Eric Laurent949a0892013-09-20 09:20:13 -07002243 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2244 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002245 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002246 compress_get_tstamp(out->compr, &dsp_frames,
2247 &out->sample_rate);
2248 ALOGVV("%s rendered frames %ld sample_rate %d",
2249 __func__, dsp_frames, out->sample_rate);
2250 *frames = dsp_frames;
2251 ret = 0;
2252 /* this is the best we can do */
2253 clock_gettime(CLOCK_MONOTONIC, timestamp);
2254 }
2255 } else {
2256 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002257 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002258 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2259 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002260 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002261 // This adjustment accounts for buffering after app processor.
2262 // It is based on estimated DSP latency per use case, rather than exact.
2263 signed_frames -=
2264 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2265
Eric Laurent949a0892013-09-20 09:20:13 -07002266 // It would be unusual for this value to be negative, but check just in case ...
2267 if (signed_frames >= 0) {
2268 *frames = signed_frames;
2269 ret = 0;
2270 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002271 }
2272 }
2273 }
2274
2275 pthread_mutex_unlock(&out->lock);
2276
2277 return ret;
2278}
2279
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002280static int out_set_callback(struct audio_stream_out *stream,
2281 stream_callback_t callback, void *cookie)
2282{
2283 struct stream_out *out = (struct stream_out *)stream;
2284
2285 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002286 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002287 out->offload_callback = callback;
2288 out->offload_cookie = cookie;
2289 pthread_mutex_unlock(&out->lock);
2290 return 0;
2291}
2292
2293static int out_pause(struct audio_stream_out* stream)
2294{
2295 struct stream_out *out = (struct stream_out *)stream;
2296 int status = -ENOSYS;
2297 ALOGV("%s", __func__);
2298 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002299 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002300 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2301 status = compress_pause(out->compr);
2302 out->offload_state = OFFLOAD_STATE_PAUSED;
2303 }
2304 pthread_mutex_unlock(&out->lock);
2305 }
2306 return status;
2307}
2308
2309static int out_resume(struct audio_stream_out* stream)
2310{
2311 struct stream_out *out = (struct stream_out *)stream;
2312 int status = -ENOSYS;
2313 ALOGV("%s", __func__);
2314 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2315 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002316 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002317 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2318 status = compress_resume(out->compr);
2319 out->offload_state = OFFLOAD_STATE_PLAYING;
2320 }
2321 pthread_mutex_unlock(&out->lock);
2322 }
2323 return status;
2324}
2325
2326static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2327{
2328 struct stream_out *out = (struct stream_out *)stream;
2329 int status = -ENOSYS;
2330 ALOGV("%s", __func__);
2331 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002332 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002333 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2334 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2335 else
2336 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2337 pthread_mutex_unlock(&out->lock);
2338 }
2339 return status;
2340}
2341
2342static int out_flush(struct audio_stream_out* stream)
2343{
2344 struct stream_out *out = (struct stream_out *)stream;
2345 ALOGV("%s", __func__);
2346 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002347 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002348 stop_compressed_output_l(out);
2349 pthread_mutex_unlock(&out->lock);
2350 return 0;
2351 }
2352 return -ENOSYS;
2353}
2354
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002355/** audio_stream_in implementation **/
2356static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2357{
2358 struct stream_in *in = (struct stream_in *)stream;
2359
2360 return in->config.rate;
2361}
2362
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002363static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002364{
2365 return -ENOSYS;
2366}
2367
2368static size_t in_get_buffer_size(const struct audio_stream *stream)
2369{
2370 struct stream_in *in = (struct stream_in *)stream;
2371
Haynes Mathew George03c40102016-01-29 17:57:48 -08002372 return in->config.period_size * in->af_period_multiplier *
2373 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002374}
2375
2376static uint32_t in_get_channels(const struct audio_stream *stream)
2377{
2378 struct stream_in *in = (struct stream_in *)stream;
2379
2380 return in->channel_mask;
2381}
2382
vivek mehta4ed66e62016-04-15 23:33:34 -07002383static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002384{
vivek mehta4ed66e62016-04-15 23:33:34 -07002385 struct stream_in *in = (struct stream_in *)stream;
2386 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002387}
2388
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002389static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002390{
2391 return -ENOSYS;
2392}
2393
2394static int in_standby(struct audio_stream *stream)
2395{
2396 struct stream_in *in = (struct stream_in *)stream;
2397 struct audio_device *adev = in->dev;
2398 int status = 0;
Eric Laurent994a6932013-07-17 11:51:42 -07002399 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002400
2401 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002402
2403 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08002404 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002405 audio_extn_sound_trigger_stop_lab(in);
2406 in->standby = true;
2407 }
2408
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002409 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002410 if (adev->adm_deregister_stream)
2411 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2412
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002413 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002414 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002415 if (in->pcm) {
2416 pcm_close(in->pcm);
2417 in->pcm = NULL;
2418 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002419 adev->enable_voicerx = false;
2420 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002421 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002422 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002423 }
2424 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002425 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002426 return status;
2427}
2428
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002429static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002430{
2431 return 0;
2432}
2433
2434static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2435{
2436 struct stream_in *in = (struct stream_in *)stream;
2437 struct audio_device *adev = in->dev;
2438 struct str_parms *parms;
2439 char *str;
2440 char value[32];
2441 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07002442 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002443
Eric Laurent994a6932013-07-17 11:51:42 -07002444 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002445 parms = str_parms_create_str(kvpairs);
2446
2447 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2448
Eric Laurenta1478072015-09-21 17:21:52 -07002449 lock_input_stream(in);
2450
Eric Laurent150dbfe2013-02-27 14:31:02 -08002451 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002452 if (ret >= 0) {
2453 val = atoi(value);
2454 /* no audio source uses val == 0 */
2455 if ((in->source != val) && (val != 0)) {
2456 in->source = val;
2457 }
2458 }
2459
2460 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07002461
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002462 if (ret >= 0) {
2463 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002464 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002465 in->device = val;
2466 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002467 if (!in->standby) {
2468 ALOGV("update input routing change");
2469 in->routing_change = true;
2470 select_devices(adev, in->usecase);
2471 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002472 }
2473 }
2474
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002475 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002476 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002477
2478 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002479 ALOGV("%s: exit: status(%d)", __func__, status);
2480 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002481}
2482
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002483static char* in_get_parameters(const struct audio_stream *stream __unused,
2484 const char *keys __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002485{
2486 return strdup("");
2487}
2488
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002489static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002490{
2491 return 0;
2492}
2493
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002494static void in_snd_mon_cb(void * stream, struct str_parms * parms)
2495{
2496 if (!stream || !parms)
2497 return;
2498
2499 struct stream_in *in = (struct stream_in *)stream;
2500 struct audio_device *adev = in->dev;
2501
2502 card_status_t status;
2503 int card;
2504 if (parse_snd_card_status(parms, &card, &status) < 0)
2505 return;
2506
2507 pthread_mutex_lock(&adev->lock);
2508 bool valid_cb = (card == adev->snd_card);
2509 pthread_mutex_unlock(&adev->lock);
2510
2511 if (!valid_cb)
2512 return;
2513
2514 lock_input_stream(in);
2515 if (in->card_status != status)
2516 in->card_status = status;
2517 pthread_mutex_unlock(&in->lock);
2518
2519 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
2520 use_case_table[in->usecase],
2521 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2522
2523 // a better solution would be to report error back to AF and let
2524 // it put the stream to standby
2525 if (status == CARD_STATUS_OFFLINE)
2526 in_standby(&in->stream.common);
2527
2528 return;
2529}
2530
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002531static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2532 size_t bytes)
2533{
2534 struct stream_in *in = (struct stream_in *)stream;
2535 struct audio_device *adev = in->dev;
2536 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07002537 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002538
Eric Laurenta1478072015-09-21 17:21:52 -07002539 lock_input_stream(in);
2540
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002541 if (in->is_st_session) {
2542 ALOGVV(" %s: reading on st session bytes=%d", __func__, bytes);
2543 /* Read from sound trigger HAL */
2544 audio_extn_sound_trigger_read(in, buffer, bytes);
2545 pthread_mutex_unlock(&in->lock);
2546 return bytes;
2547 }
2548
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002549 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002550 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002551 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002552 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002553 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002554 goto exit;
2555 }
2556 in->standby = 0;
2557 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002558
Haynes Mathew George03c40102016-01-29 17:57:48 -08002559 //what's the duration requested by the client?
2560 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
2561 in->config.rate;
2562 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002563
Haynes Mathew George03c40102016-01-29 17:57:48 -08002564 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002565 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002566 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002567 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07002568 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002569 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002570 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002571 if (ret < 0) {
2572 ALOGE("Failed to read w/err %s", strerror(errno));
2573 ret = -errno;
2574 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002575 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
2576 if (bytes % 4 == 0) {
2577 /* data from DSP comes in 24_8 format, convert it to 8_24 */
2578 int_buf_stream = buffer;
2579 for (size_t itt=0; itt < bytes/4 ; itt++) {
2580 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07002581 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002582 } else {
2583 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
2584 ret = -EINVAL;
2585 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07002586 }
2587 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002588 }
2589
Haynes Mathew George03c40102016-01-29 17:57:48 -08002590 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002591
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002592 /*
2593 * Instead of writing zeroes here, we could trust the hardware
2594 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002595 * 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 -08002596 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002597 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002598 memset(buffer, 0, bytes);
2599
2600exit:
2601 pthread_mutex_unlock(&in->lock);
2602
2603 if (ret != 0) {
2604 in_standby(&in->stream.common);
2605 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Eric Laurentfdf296a2014-07-03 16:41:51 -07002606 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002607 in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08002608 memset(buffer, 0, bytes); // clear return data
2609 }
2610 if (bytes > 0) {
Andy Hung6ebe5962016-01-15 17:46:57 -08002611 in->frames_read += bytes / audio_stream_in_frame_size(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002612 }
2613 return bytes;
2614}
2615
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002616static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002617{
2618 return 0;
2619}
2620
Andy Hung6ebe5962016-01-15 17:46:57 -08002621static int in_get_capture_position(const struct audio_stream_in *stream,
2622 int64_t *frames, int64_t *time)
2623{
2624 if (stream == NULL || frames == NULL || time == NULL) {
2625 return -EINVAL;
2626 }
2627 struct stream_in *in = (struct stream_in *)stream;
2628 int ret = -ENOSYS;
2629
2630 lock_input_stream(in);
2631 if (in->pcm) {
2632 struct timespec timestamp;
2633 unsigned int avail;
2634 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
2635 *frames = in->frames_read + avail;
2636 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
2637 ret = 0;
2638 }
2639 }
2640 pthread_mutex_unlock(&in->lock);
2641 return ret;
2642}
2643
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002644static int add_remove_audio_effect(const struct audio_stream *stream,
2645 effect_handle_t effect,
2646 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002647{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002648 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002649 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002650 int status = 0;
2651 effect_descriptor_t desc;
2652
2653 status = (*effect)->get_descriptor(effect, &desc);
2654 if (status != 0)
2655 return status;
2656
Eric Laurenta1478072015-09-21 17:21:52 -07002657 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002658 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07002659 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07002660 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07002661 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002662 in->enable_aec != enable &&
2663 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2664 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002665 if (!enable)
2666 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07002667 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2668 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
2669 adev->enable_voicerx = enable;
2670 struct audio_usecase *usecase;
2671 struct listnode *node;
2672 list_for_each(node, &adev->usecase_list) {
2673 usecase = node_to_item(node, struct audio_usecase, list);
2674 if (usecase->type == PCM_PLAYBACK) {
2675 select_devices(adev, usecase->id);
2676 break;
2677 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002678 }
2679 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002680 if (!in->standby)
2681 select_devices(in->dev, in->usecase);
2682 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07002683 if (in->enable_ns != enable &&
2684 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2685 in->enable_ns = enable;
2686 if (!in->standby)
2687 select_devices(in->dev, in->usecase);
2688 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002689 pthread_mutex_unlock(&in->dev->lock);
2690 pthread_mutex_unlock(&in->lock);
2691
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002692 return 0;
2693}
2694
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002695static int in_add_audio_effect(const struct audio_stream *stream,
2696 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002697{
Eric Laurent994a6932013-07-17 11:51:42 -07002698 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002699 return add_remove_audio_effect(stream, effect, true);
2700}
2701
2702static int in_remove_audio_effect(const struct audio_stream *stream,
2703 effect_handle_t effect)
2704{
Eric Laurent994a6932013-07-17 11:51:42 -07002705 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002706 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002707}
2708
2709static int adev_open_output_stream(struct audio_hw_device *dev,
2710 audio_io_handle_t handle,
2711 audio_devices_t devices,
2712 audio_output_flags_t flags,
2713 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07002714 struct audio_stream_out **stream_out,
2715 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002716{
2717 struct audio_device *adev = (struct audio_device *)dev;
2718 struct stream_out *out;
2719 int i, ret;
2720
Eric Laurent994a6932013-07-17 11:51:42 -07002721 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002722 __func__, config->sample_rate, config->channel_mask, devices, flags);
2723 *stream_out = NULL;
2724 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2725
2726 if (devices == AUDIO_DEVICE_NONE)
2727 devices = AUDIO_DEVICE_OUT_SPEAKER;
2728
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002729 out->flags = flags;
2730 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002731 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002732 out->format = config->format;
2733 out->sample_rate = config->sample_rate;
2734 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2735 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002736 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002737
2738 /* Init use case and pcm_config */
2739 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
Eric Laurent7f245042013-09-30 19:22:50 -07002740 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002741 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002742 pthread_mutex_lock(&adev->lock);
2743 ret = read_hdmi_channel_masks(out);
2744 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002745 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002746 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002747
2748 if (config->sample_rate == 0)
2749 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2750 if (config->channel_mask == 0)
2751 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Eric Laurentad1cec22015-12-16 10:12:27 -08002752 if (config->format == AUDIO_FORMAT_DEFAULT)
2753 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002754
2755 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002756 out->sample_rate = config->sample_rate;
Eric Laurentad1cec22015-12-16 10:12:27 -08002757 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002758 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2759 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002760 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002761 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002762 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002763 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07002764 pthread_mutex_lock(&adev->lock);
2765 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
2766 pthread_mutex_unlock(&adev->lock);
2767
2768 // reject offload during card offline to allow
2769 // fallback to s/w paths
2770 if (offline) {
2771 ret = -ENODEV;
2772 goto error_open;
2773 }
2774
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002775 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2776 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2777 ALOGE("%s: Unsupported Offload information", __func__);
2778 ret = -EINVAL;
2779 goto error_open;
2780 }
2781 if (!is_supported_format(config->offload_info.format)) {
2782 ALOGE("%s: Unsupported audio format", __func__);
2783 ret = -EINVAL;
2784 goto error_open;
2785 }
2786
2787 out->compr_config.codec = (struct snd_codec *)
2788 calloc(1, sizeof(struct snd_codec));
2789
2790 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
2791 if (config->offload_info.channel_mask)
2792 out->channel_mask = config->offload_info.channel_mask;
2793 else if (config->channel_mask)
2794 out->channel_mask = config->channel_mask;
2795 out->format = config->offload_info.format;
2796 out->sample_rate = config->offload_info.sample_rate;
2797
2798 out->stream.set_callback = out_set_callback;
2799 out->stream.pause = out_pause;
2800 out->stream.resume = out_resume;
2801 out->stream.drain = out_drain;
2802 out->stream.flush = out_flush;
2803
2804 out->compr_config.codec->id =
2805 get_snd_codec_id(config->offload_info.format);
2806 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
2807 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07002808 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002809 out->compr_config.codec->bit_rate =
2810 config->offload_info.bit_rate;
2811 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002812 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002813 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
2814
2815 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2816 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002817
2818 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002819 create_offload_callback_thread(out);
2820 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2821 __func__, config->offload_info.version,
2822 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002823 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2824 if (config->sample_rate == 0)
2825 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2826 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2827 config->sample_rate != 8000) {
2828 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2829 ret = -EINVAL;
2830 goto error_open;
2831 }
2832 out->sample_rate = config->sample_rate;
2833 out->config.rate = config->sample_rate;
2834 if (config->format == AUDIO_FORMAT_DEFAULT)
2835 config->format = AUDIO_FORMAT_PCM_16_BIT;
2836 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2837 config->format = AUDIO_FORMAT_PCM_16_BIT;
2838 ret = -EINVAL;
2839 goto error_open;
2840 }
2841 out->format = config->format;
2842 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2843 out->config = pcm_config_afe_proxy_playback;
2844 adev->voice_tx_output = out;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002845 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07002846 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2847 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2848 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07002849 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
2850 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
2851 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07002852 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
2853 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002854 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
2855 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
2856 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Andy Hung6fcba9c2014-03-18 11:53:32 -07002857 } else {
2858 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2859 out->config = pcm_config_low_latency;
2860 }
2861 if (config->format != audio_format_from_pcm_format(out->config.format)) {
2862 if (k_enable_extended_precision
2863 && pcm_params_format_test(adev->use_case_table[out->usecase],
2864 pcm_format_from_audio_format(config->format))) {
2865 out->config.format = pcm_format_from_audio_format(config->format);
2866 /* out->format already set to config->format */
2867 } else {
2868 /* deny the externally proposed config format
2869 * and use the one specified in audio_hw layer configuration.
2870 * Note: out->format is returned by out->stream.common.get_format()
2871 * and is used to set config->format in the code several lines below.
2872 */
2873 out->format = audio_format_from_pcm_format(out->config.format);
2874 }
2875 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002876 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002877 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07002878 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
2879 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002880
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002881 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002882 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002883 adev->primary_output = out;
2884 else {
2885 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002886 ret = -EEXIST;
2887 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002888 }
2889 }
2890
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002891 /* Check if this usecase is already existing */
2892 pthread_mutex_lock(&adev->lock);
2893 if (get_usecase_from_list(adev, out->usecase) != NULL) {
2894 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002895 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002896 ret = -EEXIST;
2897 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002898 }
2899 pthread_mutex_unlock(&adev->lock);
2900
2901 out->stream.common.get_sample_rate = out_get_sample_rate;
2902 out->stream.common.set_sample_rate = out_set_sample_rate;
2903 out->stream.common.get_buffer_size = out_get_buffer_size;
2904 out->stream.common.get_channels = out_get_channels;
2905 out->stream.common.get_format = out_get_format;
2906 out->stream.common.set_format = out_set_format;
2907 out->stream.common.standby = out_standby;
2908 out->stream.common.dump = out_dump;
2909 out->stream.common.set_parameters = out_set_parameters;
2910 out->stream.common.get_parameters = out_get_parameters;
2911 out->stream.common.add_audio_effect = out_add_audio_effect;
2912 out->stream.common.remove_audio_effect = out_remove_audio_effect;
2913 out->stream.get_latency = out_get_latency;
2914 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002915#ifdef NO_AUDIO_OUT
2916 out->stream.write = out_write_for_no_output;
2917#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002918 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002919#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002920 out->stream.get_render_position = out_get_render_position;
2921 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002922 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002923
Haynes Mathew George03c40102016-01-29 17:57:48 -08002924 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002925 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07002926 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002927 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002928
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002929 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07002930 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002931 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2932
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002933 config->format = out->stream.common.get_format(&out->stream.common);
2934 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
2935 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
2936
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002937
2938 /*
2939 By locking output stream before registering, we allow the callback
2940 to update stream's state only after stream's initial state is set to
2941 adev state.
2942 */
2943 lock_output_stream(out);
2944 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
2945 pthread_mutex_lock(&adev->lock);
2946 out->card_status = adev->card_status;
2947 pthread_mutex_unlock(&adev->lock);
2948 pthread_mutex_unlock(&out->lock);
2949
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002950 *stream_out = &out->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07002951 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002952 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002953
2954error_open:
2955 free(out);
2956 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07002957 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002958 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002959}
2960
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002961static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002962 struct audio_stream_out *stream)
2963{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002964 struct stream_out *out = (struct stream_out *)stream;
2965 struct audio_device *adev = out->dev;
2966
Eric Laurent994a6932013-07-17 11:51:42 -07002967 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002968
2969 // must deregister from sndmonitor first to prevent races
2970 // between the callback and close_stream
2971 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002972 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002973 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2974 destroy_offload_callback_thread(out);
2975
2976 if (out->compr_config.codec != NULL)
2977 free(out->compr_config.codec);
2978 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07002979
2980 if (adev->voice_tx_output == out)
2981 adev->voice_tx_output = NULL;
2982
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002983 pthread_cond_destroy(&out->cond);
2984 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002985 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07002986 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002987}
2988
2989static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
2990{
2991 struct audio_device *adev = (struct audio_device *)dev;
2992 struct str_parms *parms;
2993 char *str;
2994 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002995 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002996 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07002997 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002998
Joe Onorato188b6222016-03-01 11:02:27 -08002999 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003000
3001 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003002
3003 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003004 status = voice_set_parameters(adev, parms);
3005 if (status != 0) {
3006 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003007 }
3008
3009 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3010 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003011 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003012 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3013 adev->bluetooth_nrec = true;
3014 else
3015 adev->bluetooth_nrec = false;
3016 }
3017
3018 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3019 if (ret >= 0) {
3020 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3021 adev->screen_off = false;
3022 else
3023 adev->screen_off = true;
3024 }
3025
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003026 ret = str_parms_get_int(parms, "rotation", &val);
3027 if (ret >= 0) {
3028 bool reverse_speakers = false;
3029 switch(val) {
3030 // FIXME: note that the code below assumes that the speakers are in the correct placement
3031 // relative to the user when the device is rotated 90deg from its default rotation. This
3032 // assumption is device-specific, not platform-specific like this code.
3033 case 270:
3034 reverse_speakers = true;
3035 break;
3036 case 0:
3037 case 90:
3038 case 180:
3039 break;
3040 default:
3041 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003042 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003043 }
Eric Laurent03f09432014-03-25 18:09:11 -07003044 if (status == 0) {
Ravi Kumar Alamanda1f60cf82015-04-23 19:45:17 -07003045 platform_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003046 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003047 }
3048
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003049 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3050 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003051 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003052 }
3053
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08003054 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003055done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003056 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003057 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07003058 ALOGV("%s: exit with code(%d)", __func__, status);
3059 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003060}
3061
3062static char* adev_get_parameters(const struct audio_hw_device *dev,
3063 const char *keys)
3064{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003065 struct audio_device *adev = (struct audio_device *)dev;
3066 struct str_parms *reply = str_parms_create();
3067 struct str_parms *query = str_parms_create_str(keys);
3068 char *str;
3069
3070 pthread_mutex_lock(&adev->lock);
3071
3072 voice_get_parameters(adev, query, reply);
3073 str = str_parms_to_str(reply);
3074 str_parms_destroy(query);
3075 str_parms_destroy(reply);
3076
3077 pthread_mutex_unlock(&adev->lock);
3078 ALOGV("%s: exit: returns - %s", __func__, str);
3079 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003080}
3081
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003082static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003083{
3084 return 0;
3085}
3086
Haynes Mathew George5191a852013-09-11 14:19:36 -07003087static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3088{
3089 int ret;
3090 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003091
Eric Laurent4cc4ce12014-09-10 13:21:01 -05003092 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
3093
Haynes Mathew George5191a852013-09-11 14:19:36 -07003094 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003095 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003096 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003097
Haynes Mathew George5191a852013-09-11 14:19:36 -07003098 return ret;
3099}
3100
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003101static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003102{
3103 return -ENOSYS;
3104}
3105
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003106static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3107 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003108{
3109 return -ENOSYS;
3110}
3111
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003112static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003113{
3114 return -ENOSYS;
3115}
3116
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003117static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003118{
3119 return -ENOSYS;
3120}
3121
3122static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3123{
3124 struct audio_device *adev = (struct audio_device *)dev;
3125
3126 pthread_mutex_lock(&adev->lock);
3127 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07003128 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003129 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07003130 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3131 voice_is_in_call(adev)) {
3132 voice_stop_call(adev);
3133 adev->current_call_output = NULL;
3134 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003135 }
3136 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003137
3138 audio_extn_extspk_set_mode(adev->extspk, mode);
3139
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003140 return 0;
3141}
3142
3143static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3144{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003145 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003146 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003147
Eric Laurent2bafff12016-03-17 12:17:23 -07003148 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003149 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003150 ret = voice_set_mic_mute(adev, state);
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003151 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00003152 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003153
3154 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003155}
3156
3157static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3158{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003159 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003160 return 0;
3161}
3162
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003163static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003164 const struct audio_config *config)
3165{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003166 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003167
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003168 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3169 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003170}
3171
3172static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003173 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003174 audio_devices_t devices,
3175 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003176 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07003177 audio_input_flags_t flags,
3178 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05003179 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003180{
3181 struct audio_device *adev = (struct audio_device *)dev;
3182 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003183 int ret = 0, buffer_size, frame_size;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003184 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003185 bool is_low_latency = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003186
Eric Laurent994a6932013-07-17 11:51:42 -07003187 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003188 *stream_in = NULL;
3189 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3190 return -EINVAL;
3191
3192 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
3193
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003194 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003195 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003196
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003197 in->stream.common.get_sample_rate = in_get_sample_rate;
3198 in->stream.common.set_sample_rate = in_set_sample_rate;
3199 in->stream.common.get_buffer_size = in_get_buffer_size;
3200 in->stream.common.get_channels = in_get_channels;
3201 in->stream.common.get_format = in_get_format;
3202 in->stream.common.set_format = in_set_format;
3203 in->stream.common.standby = in_standby;
3204 in->stream.common.dump = in_dump;
3205 in->stream.common.set_parameters = in_set_parameters;
3206 in->stream.common.get_parameters = in_get_parameters;
3207 in->stream.common.add_audio_effect = in_add_audio_effect;
3208 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3209 in->stream.set_gain = in_set_gain;
3210 in->stream.read = in_read;
3211 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08003212 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003213
3214 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003215 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003216 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003217 in->standby = 1;
3218 in->channel_mask = config->channel_mask;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003219 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003220 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003221
vivek mehta57ff9b52016-04-28 14:13:08 -07003222 // restrict 24 bit capture for unprocessed source only
3223 // for other sources if 24 bit requested reject 24 and set 16 bit capture only
3224 if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07003225 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07003226 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
3227 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
3228 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
3229 bool ret_error = false;
3230 /* 24 bit is restricted to UNPROCESSED source only,also format supported
3231 from HAL is 8_24
3232 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
3233 8_24 return error indicating supported format is 8_24
3234 *> In case of any other source requesting 24 bit or float return error
3235 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07003236
vivek mehta57ff9b52016-04-28 14:13:08 -07003237 on error flinger will retry with supported format passed
3238 */
3239 if (source != AUDIO_SOURCE_UNPROCESSED) {
3240 config->format = AUDIO_FORMAT_PCM_16_BIT;
3241 ret_error = true;
3242 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
3243 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
3244 ret_error = true;
3245 }
3246
3247 if (ret_error) {
3248 ret = -EINVAL;
3249 goto err_open;
3250 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003251 }
3252
vivek mehta57ff9b52016-04-28 14:13:08 -07003253 in->format = config->format;
3254
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003255 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003256 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
3257 if (config->sample_rate == 0)
3258 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3259 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3260 config->sample_rate != 8000) {
3261 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3262 ret = -EINVAL;
3263 goto err_open;
3264 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003265
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003266 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3267 config->format = AUDIO_FORMAT_PCM_16_BIT;
3268 ret = -EINVAL;
3269 goto err_open;
3270 }
3271
3272 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3273 in->config = pcm_config_afe_proxy_record;
3274 } else {
3275 in->usecase = USECASE_AUDIO_RECORD;
3276 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3277 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3278 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07003279#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003280 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07003281#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08003282 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003283 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003284
Haynes Mathew George03c40102016-01-29 17:57:48 -08003285 in->config = in->realtime ? pcm_config_audio_capture_rt :
3286 pcm_config_audio_capture;
3287
vivek mehta4ed66e62016-04-15 23:33:34 -07003288 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
3289 in->config.format = PCM_FORMAT_S24_LE;
3290
Haynes Mathew George03c40102016-01-29 17:57:48 -08003291 if (!in->realtime) {
3292 frame_size = audio_stream_in_frame_size(&in->stream);
3293 buffer_size = get_input_buffer_size(config->sample_rate,
3294 config->format,
3295 channel_count,
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003296 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003297 in->config.period_size = buffer_size / frame_size;
3298 } // period size is left untouched for rt mode playback
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003299 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003300
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003301 in->config.channels = channel_count;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003302 if (in->realtime) {
3303 in->af_period_multiplier = af_period_multiplier;
3304 } else {
3305 in->config.rate = config->sample_rate;
3306 in->af_period_multiplier = 1;
3307 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003308
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003309 /* This stream could be for sound trigger lab,
3310 get sound trigger pcm if present */
3311 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003312
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003313 lock_input_stream(in);
3314 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
3315 pthread_mutex_lock(&adev->lock);
3316 in->card_status = adev->card_status;
3317 pthread_mutex_unlock(&adev->lock);
3318 pthread_mutex_unlock(&in->lock);
3319
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003320 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003321 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003322 return 0;
3323
3324err_open:
3325 free(in);
3326 *stream_in = NULL;
3327 return ret;
3328}
3329
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003330static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003331 struct audio_stream_in *stream)
3332{
Eric Laurent994a6932013-07-17 11:51:42 -07003333 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003334
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003335 // must deregister from sndmonitor first to prevent races
3336 // between the callback and close_stream
3337 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003338 in_standby(&stream->common);
3339 free(stream);
3340
3341 return;
3342}
3343
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003344static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003345{
3346 return 0;
3347}
3348
Andy Hung31aca912014-03-20 17:14:59 -07003349/* verifies input and output devices and their capabilities.
3350 *
3351 * This verification is required when enabling extended bit-depth or
3352 * sampling rates, as not all qcom products support it.
3353 *
3354 * Suitable for calling only on initialization such as adev_open().
3355 * It fills the audio_device use_case_table[] array.
3356 *
3357 * Has a side-effect that it needs to configure audio routing / devices
3358 * in order to power up the devices and read the device parameters.
3359 * It does not acquire any hw device lock. Should restore the devices
3360 * back to "normal state" upon completion.
3361 */
3362static int adev_verify_devices(struct audio_device *adev)
3363{
3364 /* enumeration is a bit difficult because one really wants to pull
3365 * the use_case, device id, etc from the hidden pcm_device_table[].
3366 * In this case there are the following use cases and device ids.
3367 *
3368 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
3369 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
3370 * [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
3371 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
3372 * [USECASE_AUDIO_RECORD] = {0, 0},
3373 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
3374 * [USECASE_VOICE_CALL] = {2, 2},
3375 *
3376 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_MULTI_CH omitted.
3377 * USECASE_VOICE_CALL omitted, but possible for either input or output.
3378 */
3379
3380 /* should be the usecases enabled in adev_open_input_stream() */
3381 static const int test_in_usecases[] = {
3382 USECASE_AUDIO_RECORD,
3383 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
3384 };
3385 /* should be the usecases enabled in adev_open_output_stream()*/
3386 static const int test_out_usecases[] = {
3387 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
3388 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
3389 };
3390 static const usecase_type_t usecase_type_by_dir[] = {
3391 PCM_PLAYBACK,
3392 PCM_CAPTURE,
3393 };
3394 static const unsigned flags_by_dir[] = {
3395 PCM_OUT,
3396 PCM_IN,
3397 };
3398
3399 size_t i;
3400 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003401 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07003402 char info[512]; /* for possible debug info */
3403
3404 for (dir = 0; dir < 2; ++dir) {
3405 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
3406 const unsigned flags_dir = flags_by_dir[dir];
3407 const size_t testsize =
3408 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
3409 const int *testcases =
3410 dir ? test_in_usecases : test_out_usecases;
3411 const audio_devices_t audio_device =
3412 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
3413
3414 for (i = 0; i < testsize; ++i) {
3415 const audio_usecase_t audio_usecase = testcases[i];
3416 int device_id;
3417 snd_device_t snd_device;
3418 struct pcm_params **pparams;
3419 struct stream_out out;
3420 struct stream_in in;
3421 struct audio_usecase uc_info;
3422 int retval;
3423
3424 pparams = &adev->use_case_table[audio_usecase];
3425 pcm_params_free(*pparams); /* can accept null input */
3426 *pparams = NULL;
3427
3428 /* find the device ID for the use case (signed, for error) */
3429 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
3430 if (device_id < 0)
3431 continue;
3432
3433 /* prepare structures for device probing */
3434 memset(&uc_info, 0, sizeof(uc_info));
3435 uc_info.id = audio_usecase;
3436 uc_info.type = usecase_type;
3437 if (dir) {
3438 adev->active_input = &in;
3439 memset(&in, 0, sizeof(in));
3440 in.device = audio_device;
3441 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
3442 uc_info.stream.in = &in;
3443 } else {
3444 adev->active_input = NULL;
3445 }
3446 memset(&out, 0, sizeof(out));
3447 out.devices = audio_device; /* only field needed in select_devices */
3448 uc_info.stream.out = &out;
3449 uc_info.devices = audio_device;
3450 uc_info.in_snd_device = SND_DEVICE_NONE;
3451 uc_info.out_snd_device = SND_DEVICE_NONE;
3452 list_add_tail(&adev->usecase_list, &uc_info.list);
3453
3454 /* select device - similar to start_(in/out)put_stream() */
3455 retval = select_devices(adev, audio_usecase);
3456 if (retval >= 0) {
3457 *pparams = pcm_params_get(card_id, device_id, flags_dir);
3458#if LOG_NDEBUG == 0
3459 if (*pparams) {
3460 ALOGV("%s: (%s) card %d device %d", __func__,
3461 dir ? "input" : "output", card_id, device_id);
3462 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07003463 } else {
3464 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
3465 }
3466#endif
3467 }
3468
3469 /* deselect device - similar to stop_(in/out)put_stream() */
3470 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07003471 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07003472 /* 2. Disable the rx device */
3473 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07003474 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07003475 list_remove(&uc_info.list);
3476 }
3477 }
3478 adev->active_input = NULL; /* restore adev state */
3479 return 0;
3480}
3481
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003482static int adev_close(hw_device_t *device)
3483{
Andy Hung31aca912014-03-20 17:14:59 -07003484 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003485 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003486
3487 if (!adev)
3488 return 0;
3489
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003490 audio_extn_snd_mon_unregister_listener(adev);
vivek mehta1a9b7c02015-06-25 11:49:38 -07003491 pthread_mutex_lock(&adev_init_lock);
3492
3493 if ((--audio_device_ref_count) == 0) {
3494 audio_route_free(adev->audio_route);
3495 free(adev->snd_dev_ref_cnt);
3496 platform_deinit(adev->platform);
3497 audio_extn_extspk_deinit(adev->extspk);
3498 audio_extn_sound_trigger_deinit(adev);
3499 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
3500 pcm_params_free(adev->use_case_table[i]);
3501 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003502 if (adev->adm_deinit)
3503 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07003504 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07003505 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07003506
3507 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003508
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003509 return 0;
3510}
3511
Glenn Kasten4f993392014-05-14 07:30:48 -07003512/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3513 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3514 * just that it _might_ work.
3515 */
3516static int period_size_is_plausible_for_low_latency(int period_size)
3517{
3518 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07003519 case 48:
3520 case 96:
3521 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07003522 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07003523 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07003524 case 240:
3525 case 320:
3526 case 480:
3527 return 1;
3528 default:
3529 return 0;
3530 }
3531}
3532
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003533static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
3534{
3535 int card;
3536 card_status_t status;
3537
3538 if (!parms)
3539 return;
3540
3541 if (parse_snd_card_status(parms, &card, &status) < 0)
3542 return;
3543
3544 pthread_mutex_lock(&adev->lock);
3545 bool valid_cb = (card == adev->snd_card);
3546 if (valid_cb) {
3547 if (adev->card_status != status) {
3548 adev->card_status = status;
3549 platform_snd_card_update(adev->platform, status);
3550 }
3551 }
3552 pthread_mutex_unlock(&adev->lock);
3553 return;
3554}
3555
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003556static int adev_open(const hw_module_t *module, const char *name,
3557 hw_device_t **device)
3558{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003559 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003560
Eric Laurent2bafff12016-03-17 12:17:23 -07003561 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003562 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003563 pthread_mutex_lock(&adev_init_lock);
3564 if (audio_device_ref_count != 0) {
3565 *device = &adev->device.common;
3566 audio_device_ref_count++;
3567 ALOGV("%s: returning existing instance of adev", __func__);
3568 ALOGV("%s: exit", __func__);
3569 pthread_mutex_unlock(&adev_init_lock);
3570 return 0;
3571 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003572 adev = calloc(1, sizeof(struct audio_device));
3573
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003574 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3575
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003576 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3577 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3578 adev->device.common.module = (struct hw_module_t *)module;
3579 adev->device.common.close = adev_close;
3580
3581 adev->device.init_check = adev_init_check;
3582 adev->device.set_voice_volume = adev_set_voice_volume;
3583 adev->device.set_master_volume = adev_set_master_volume;
3584 adev->device.get_master_volume = adev_get_master_volume;
3585 adev->device.set_master_mute = adev_set_master_mute;
3586 adev->device.get_master_mute = adev_get_master_mute;
3587 adev->device.set_mode = adev_set_mode;
3588 adev->device.set_mic_mute = adev_set_mic_mute;
3589 adev->device.get_mic_mute = adev_get_mic_mute;
3590 adev->device.set_parameters = adev_set_parameters;
3591 adev->device.get_parameters = adev_get_parameters;
3592 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3593 adev->device.open_output_stream = adev_open_output_stream;
3594 adev->device.close_output_stream = adev_close_output_stream;
3595 adev->device.open_input_stream = adev_open_input_stream;
3596 adev->device.close_input_stream = adev_close_input_stream;
3597 adev->device.dump = adev_dump;
3598
3599 /* Set the default route before the PCM stream is opened */
3600 pthread_mutex_lock(&adev->lock);
3601 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003602 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003603 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003604 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003605 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003606 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003607 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003608 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003609 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003610 pthread_mutex_unlock(&adev->lock);
3611
3612 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003613 adev->platform = platform_init(adev);
3614 if (!adev->platform) {
3615 free(adev->snd_dev_ref_cnt);
3616 free(adev);
3617 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3618 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003619 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003620 return -EINVAL;
3621 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05003622 adev->extspk = audio_extn_extspk_init(adev);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003623 audio_extn_sound_trigger_init(adev);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003624
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003625 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3626 if (adev->visualizer_lib == NULL) {
3627 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3628 } else {
3629 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3630 adev->visualizer_start_output =
3631 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
3632 "visualizer_hal_start_output");
3633 adev->visualizer_stop_output =
3634 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
3635 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07003636 }
3637
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003638 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3639 if (adev->offload_effects_lib == NULL) {
3640 ALOGW("%s: DLOPEN failed for %s", __func__,
3641 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3642 } else {
3643 ALOGV("%s: DLOPEN successful for %s", __func__,
3644 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3645 adev->offload_effects_start_output =
3646 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3647 "offload_effects_bundle_hal_start_output");
3648 adev->offload_effects_stop_output =
3649 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3650 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07003651 }
3652
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003653 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
3654 if (adev->adm_lib == NULL) {
3655 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
3656 } else {
3657 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
3658 adev->adm_init = (adm_init_t)
3659 dlsym(adev->adm_lib, "adm_init");
3660 adev->adm_deinit = (adm_deinit_t)
3661 dlsym(adev->adm_lib, "adm_deinit");
3662 adev->adm_register_input_stream = (adm_register_input_stream_t)
3663 dlsym(adev->adm_lib, "adm_register_input_stream");
3664 adev->adm_register_output_stream = (adm_register_output_stream_t)
3665 dlsym(adev->adm_lib, "adm_register_output_stream");
3666 adev->adm_deregister_stream = (adm_deregister_stream_t)
3667 dlsym(adev->adm_lib, "adm_deregister_stream");
3668 adev->adm_request_focus = (adm_request_focus_t)
3669 dlsym(adev->adm_lib, "adm_request_focus");
3670 adev->adm_abandon_focus = (adm_abandon_focus_t)
3671 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08003672 adev->adm_set_config = (adm_set_config_t)
3673 dlsym(adev->adm_lib, "adm_set_config");
3674 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
3675 dlsym(adev->adm_lib, "adm_request_focus_v2");
3676 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
3677 dlsym(adev->adm_lib, "adm_is_noirq_avail");
3678 adev->adm_on_routing_change = (adm_on_routing_change_t)
3679 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003680 }
3681
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003682 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003683 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003684
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003685 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003686
Andy Hung31aca912014-03-20 17:14:59 -07003687 if (k_enable_extended_precision)
3688 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003689
Glenn Kasten4f993392014-05-14 07:30:48 -07003690 char value[PROPERTY_VALUE_MAX];
3691 int trial;
3692 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3693 trial = atoi(value);
3694 if (period_size_is_plausible_for_low_latency(trial)) {
3695 pcm_config_low_latency.period_size = trial;
3696 pcm_config_low_latency.start_threshold = trial / 4;
3697 pcm_config_low_latency.avail_min = trial / 4;
3698 configured_low_latency_capture_period_size = trial;
3699 }
3700 }
3701 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3702 trial = atoi(value);
3703 if (period_size_is_plausible_for_low_latency(trial)) {
3704 configured_low_latency_capture_period_size = trial;
3705 }
3706 }
3707
Yamit Mehtae3b99562016-09-16 22:44:00 +05303708 audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07003709 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003710
3711 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
3712 af_period_multiplier = atoi(value);
3713 if (af_period_multiplier < 0) {
3714 af_period_multiplier = 2;
3715 } else if (af_period_multiplier > 4) {
3716 af_period_multiplier = 4;
3717 }
3718 ALOGV("new period_multiplier = %d", af_period_multiplier);
3719 }
3720
vivek mehta1a9b7c02015-06-25 11:49:38 -07003721 pthread_mutex_unlock(&adev_init_lock);
3722
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003723 if (adev->adm_init)
3724 adev->adm_data = adev->adm_init();
3725
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07003726 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003727 audio_extn_snd_mon_init();
3728 pthread_mutex_lock(&adev->lock);
3729 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
3730 adev->card_status = CARD_STATUS_ONLINE;
3731 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07003732
Eric Laurent2bafff12016-03-17 12:17:23 -07003733 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003734 return 0;
3735}
3736
3737static struct hw_module_methods_t hal_module_methods = {
3738 .open = adev_open,
3739};
3740
3741struct audio_module HAL_MODULE_INFO_SYM = {
3742 .common = {
3743 .tag = HARDWARE_MODULE_TAG,
3744 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3745 .hal_api_version = HARDWARE_HAL_API_VERSION,
3746 .id = AUDIO_HARDWARE_MODULE_ID,
3747 .name = "QCOM Audio HAL",
3748 .author = "Code Aurora Forum",
3749 .methods = &hal_module_methods,
3750 },
3751};