blob: 8585a7672d5d45e6eee00c84ed0469f8d62657ff [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
550 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500551 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700552 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700553 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800554
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800555 ALOGV("%s: exit", __func__);
556 return 0;
557}
558
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800559int disable_audio_route(struct audio_device *adev,
560 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800561{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700562 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800563 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800564
565 if (usecase == NULL)
566 return -EINVAL;
567
568 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700569 if (usecase->type == PCM_CAPTURE)
570 snd_device = usecase->in_snd_device;
571 else
572 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800573 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500574 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700575 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700576 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800577
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800578 ALOGV("%s: exit", __func__);
579 return 0;
580}
581
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800582int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700583 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800584{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700585 int i, num_devices = 0;
586 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800587 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800588 if (snd_device < SND_DEVICE_MIN ||
589 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800590 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800591 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800592 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700593
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700594 platform_send_audio_calibration(adev->platform, snd_device);
595
vivek mehtade4849c2016-03-03 17:23:38 -0800596 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700597 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700598 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800599 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700600 }
601
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700602 /* due to the possibility of calibration overwrite between listen
603 and audio, notify sound trigger hal before audio calibration is sent */
604 audio_extn_sound_trigger_update_device_status(snd_device,
605 ST_EVENT_SND_DEVICE_BUSY);
606
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700607 if (audio_extn_spkr_prot_is_enabled())
608 audio_extn_spkr_prot_calib_cancel(adev);
609
zhaoyang yin4211fad2015-06-04 21:13:25 +0800610 audio_extn_dsm_feedback_enable(adev, snd_device, true);
611
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700612 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
613 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
614 audio_extn_spkr_prot_is_enabled()) {
615 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800616 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700617 }
618 if (audio_extn_spkr_prot_start_processing(snd_device)) {
619 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800620 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700621 }
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700622 } else if (platform_can_split_snd_device(snd_device, &num_devices, new_snd_devices)) {
623 for (i = 0; i < num_devices; i++) {
624 enable_snd_device(adev, new_snd_devices[i]);
625 }
vivek mehtab6506412015-08-07 16:55:17 -0700626 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700627 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800628 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
629 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
630 ALOGE(" %s: Invalid sound device returned", __func__);
631 goto on_error;
632 }
Ed Tam70b5c142016-03-21 19:14:29 -0700633
Eric Laurent2e140aa2016-06-30 17:14:46 -0700634 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800635 audio_route_apply_and_update_path(adev->audio_route, device_name);
636 }
637on_success:
638 adev->snd_dev_ref_cnt[snd_device]++;
639 ret_val = 0;
640on_error:
641 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800642}
643
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800644int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700645 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800646{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700647 int i, num_devices = 0;
648 snd_device_t new_snd_devices[2];
649
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800650 if (snd_device < SND_DEVICE_MIN ||
651 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800652 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800653 return -EINVAL;
654 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700655 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
656 ALOGE("%s: device ref cnt is already 0", __func__);
657 return -EINVAL;
658 }
659 adev->snd_dev_ref_cnt[snd_device]--;
660 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800661 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700662 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
663 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
664 audio_extn_spkr_prot_is_enabled()) {
665 audio_extn_spkr_prot_stop_processing(snd_device);
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700666 } else if (platform_can_split_snd_device(snd_device, &num_devices, new_snd_devices)) {
667 for (i = 0; i < num_devices; i++) {
668 disable_snd_device(adev, new_snd_devices[i]);
669 }
vivek mehtab6506412015-08-07 16:55:17 -0700670 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700671 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800672 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
673 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
674 ALOGE(" %s: Invalid sound device returned", __func__);
675 return -EINVAL;
676 }
677
Eric Laurent2e140aa2016-06-30 17:14:46 -0700678 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800679 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700680 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700681 audio_extn_sound_trigger_update_device_status(snd_device,
682 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700683 }
vivek mehtab6506412015-08-07 16:55:17 -0700684
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800685 return 0;
686}
687
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700688static void check_and_route_playback_usecases(struct audio_device *adev,
689 struct audio_usecase *uc_info,
690 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700691{
692 struct listnode *node;
693 struct audio_usecase *usecase;
694 bool switch_device[AUDIO_USECASE_MAX];
695 int i, num_uc_to_switch = 0;
696
697 /*
698 * This function is to make sure that all the usecases that are active on
699 * the hardware codec backend are always routed to any one device that is
700 * handled by the hardware codec.
701 * For example, if low-latency and deep-buffer usecases are currently active
702 * on speaker and out_set_parameters(headset) is received on low-latency
703 * output, then we have to make sure deep-buffer is also switched to headset,
704 * because of the limitation that both the devices cannot be enabled
705 * at the same time as they share the same backend.
706 */
707 /* Disable all the usecases on the shared backend other than the
708 specified usecase */
709 for (i = 0; i < AUDIO_USECASE_MAX; i++)
710 switch_device[i] = false;
711
712 list_for_each(node, &adev->usecase_list) {
713 usecase = node_to_item(node, struct audio_usecase, list);
714 if (usecase->type != PCM_CAPTURE &&
715 usecase != uc_info &&
716 usecase->out_snd_device != snd_device &&
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700717 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
718 platform_check_backends_match(snd_device, usecase->out_snd_device)) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700719 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
720 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700721 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700722 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700723 switch_device[usecase->id] = true;
724 num_uc_to_switch++;
725 }
726 }
727
728 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700729 list_for_each(node, &adev->usecase_list) {
730 usecase = node_to_item(node, struct audio_usecase, list);
731 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700732 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900733 }
734 }
735
736 list_for_each(node, &adev->usecase_list) {
737 usecase = node_to_item(node, struct audio_usecase, list);
738 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700739 enable_snd_device(adev, snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700740 }
741 }
742
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700743 /* Re-route all the usecases on the shared backend other than the
744 specified usecase to new snd devices */
745 list_for_each(node, &adev->usecase_list) {
746 usecase = node_to_item(node, struct audio_usecase, list);
747 /* Update the out_snd_device only before enabling the audio route */
748 if (switch_device[usecase->id] ) {
749 usecase->out_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700750 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700751 }
752 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700753 }
754}
755
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700756static void check_and_route_capture_usecases(struct audio_device *adev,
757 struct audio_usecase *uc_info,
758 snd_device_t snd_device)
759{
760 struct listnode *node;
761 struct audio_usecase *usecase;
762 bool switch_device[AUDIO_USECASE_MAX];
763 int i, num_uc_to_switch = 0;
764
vivek mehta4ed66e62016-04-15 23:33:34 -0700765 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
766
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700767 /*
768 * This function is to make sure that all the active capture usecases
769 * are always routed to the same input sound device.
770 * For example, if audio-record and voice-call usecases are currently
771 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
772 * is received for voice call then we have to make sure that audio-record
773 * usecase is also switched to earpiece i.e. voice-dmic-ef,
774 * because of the limitation that two devices cannot be enabled
775 * at the same time if they share the same backend.
776 */
777 for (i = 0; i < AUDIO_USECASE_MAX; i++)
778 switch_device[i] = false;
779
780 list_for_each(node, &adev->usecase_list) {
781 usecase = node_to_item(node, struct audio_usecase, list);
782 if (usecase->type != PCM_PLAYBACK &&
783 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700784 usecase->in_snd_device != snd_device &&
785 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700786 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
787 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700788 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700789 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700790 switch_device[usecase->id] = true;
791 num_uc_to_switch++;
792 }
793 }
794
795 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700796 list_for_each(node, &adev->usecase_list) {
797 usecase = node_to_item(node, struct audio_usecase, list);
798 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700799 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700800 }
801 }
802
803 list_for_each(node, &adev->usecase_list) {
804 usecase = node_to_item(node, struct audio_usecase, list);
805 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700806 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700807 }
808 }
809
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700810 /* Re-route all the usecases on the shared backend other than the
811 specified usecase to new snd devices */
812 list_for_each(node, &adev->usecase_list) {
813 usecase = node_to_item(node, struct audio_usecase, list);
814 /* Update the in_snd_device only before enabling the audio route */
815 if (switch_device[usecase->id] ) {
816 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700817 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700818 }
819 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700820 }
821}
822
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800823/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700824static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800825{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700826 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700827 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800828
829 switch (channels) {
830 /*
831 * Do not handle stereo output in Multi-channel cases
832 * Stereo case is handled in normal playback path
833 */
834 case 6:
835 ALOGV("%s: HDMI supports 5.1", __func__);
836 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
837 break;
838 case 8:
839 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
840 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
841 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
842 break;
843 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700844 ALOGE("HDMI does not support multi channel playback");
845 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800846 break;
847 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700848 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800849}
850
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -0700851static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
852{
853 struct audio_usecase *usecase;
854 struct listnode *node;
855
856 list_for_each(node, &adev->usecase_list) {
857 usecase = node_to_item(node, struct audio_usecase, list);
858 if (usecase->type == VOICE_CALL) {
859 ALOGV("%s: usecase id %d", __func__, usecase->id);
860 return usecase->id;
861 }
862 }
863 return USECASE_INVALID;
864}
865
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800866struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
867 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700868{
869 struct audio_usecase *usecase;
870 struct listnode *node;
871
872 list_for_each(node, &adev->usecase_list) {
873 usecase = node_to_item(node, struct audio_usecase, list);
874 if (usecase->id == uc_id)
875 return usecase;
876 }
877 return NULL;
878}
879
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800880int select_devices(struct audio_device *adev,
881 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800882{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800883 snd_device_t out_snd_device = SND_DEVICE_NONE;
884 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700885 struct audio_usecase *usecase = NULL;
886 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800887 struct audio_usecase *hfp_usecase = NULL;
888 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800889 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700890 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800891
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700892 usecase = get_usecase_from_list(adev, uc_id);
893 if (usecase == NULL) {
894 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
895 return -EINVAL;
896 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800897
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800898 if ((usecase->type == VOICE_CALL) ||
899 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700900 out_snd_device = platform_get_output_snd_device(adev->platform,
901 usecase->stream.out->devices);
902 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700903 usecase->devices = usecase->stream.out->devices;
904 } else {
905 /*
906 * If the voice call is active, use the sound devices of voice call usecase
907 * so that it would not result any device switch. All the usecases will
908 * be switched to new device when select_devices() is called for voice call
909 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700910 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700911 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700912 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -0700913 vc_usecase = get_usecase_from_list(adev,
914 get_voice_usecase_id_from_list(adev));
915 if ((vc_usecase != NULL) &&
916 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
917 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700918 in_snd_device = vc_usecase->in_snd_device;
919 out_snd_device = vc_usecase->out_snd_device;
920 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800921 } else if (audio_extn_hfp_is_active(adev)) {
922 hfp_ucid = audio_extn_hfp_get_usecase();
923 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
924 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
925 in_snd_device = hfp_usecase->in_snd_device;
926 out_snd_device = hfp_usecase->out_snd_device;
927 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700928 }
929 if (usecase->type == PCM_PLAYBACK) {
930 usecase->devices = usecase->stream.out->devices;
931 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700932 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700933 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700934 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700935 if (usecase->stream.out == adev->primary_output &&
936 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -0700937 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
938 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -0800939 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700940 select_devices(adev, adev->active_input->usecase);
941 }
942 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700943 } else if (usecase->type == PCM_CAPTURE) {
944 usecase->devices = usecase->stream.in->device;
945 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700946 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700947 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -0700948 if (adev->active_input &&
949 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
950 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -0800951 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -0700952 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
953 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
954 } else if (adev->primary_output) {
955 out_device = adev->primary_output->devices;
956 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700957 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700958 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700959 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700960 }
961 }
962
963 if (out_snd_device == usecase->out_snd_device &&
964 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800965 return 0;
966 }
967
Eric Laurent2bafff12016-03-17 12:17:23 -0700968 if (out_snd_device != SND_DEVICE_NONE &&
969 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
970 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
971 __func__,
972 use_case_table[uc_id],
973 adev->last_logged_snd_device[uc_id][0],
974 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
975 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
976 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
977 -1,
978 out_snd_device,
979 platform_get_snd_device_name(out_snd_device),
980 platform_get_snd_device_acdb_id(out_snd_device));
981 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
982 }
983 if (in_snd_device != SND_DEVICE_NONE &&
984 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
985 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
986 __func__,
987 use_case_table[uc_id],
988 adev->last_logged_snd_device[uc_id][1],
989 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
990 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
991 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
992 -1,
993 in_snd_device,
994 platform_get_snd_device_name(in_snd_device),
995 platform_get_snd_device_acdb_id(in_snd_device));
996 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
997 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800998
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800999 /*
1000 * Limitation: While in call, to do a device switch we need to disable
1001 * and enable both RX and TX devices though one of them is same as current
1002 * device.
1003 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001004 if ((usecase->type == VOICE_CALL) &&
1005 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1006 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001007 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001008 /* Disable sidetone only if voice call already exists */
1009 if (voice_is_call_state_active(adev))
1010 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001011 }
1012
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001013 /* Disable current sound devices */
1014 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001015 disable_audio_route(adev, usecase);
1016 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001017 }
1018
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001019 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001020 disable_audio_route(adev, usecase);
1021 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001022 }
1023
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001024 /* Applicable only on the targets that has external modem.
1025 * New device information should be sent to modem before enabling
1026 * the devices to reduce in-call device switch time.
1027 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001028 if ((usecase->type == VOICE_CALL) &&
1029 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1030 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001031 status = platform_switch_voice_call_enable_device_config(adev->platform,
1032 out_snd_device,
1033 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001034 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001035
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001036 /* Enable new sound devices */
1037 if (out_snd_device != SND_DEVICE_NONE) {
1038 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001039 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001040 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001041 }
1042
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001043 if (in_snd_device != SND_DEVICE_NONE) {
1044 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001045 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001046 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001047
Eric Laurentb23d5282013-05-14 15:27:20 -07001048 if (usecase->type == VOICE_CALL)
1049 status = platform_switch_voice_call_device_post(adev->platform,
1050 out_snd_device,
1051 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001052
sangwoo170731f2013-06-08 15:36:36 +09001053 usecase->in_snd_device = in_snd_device;
1054 usecase->out_snd_device = out_snd_device;
1055
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001056 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001057
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001058 /* Applicable only on the targets that has external modem.
1059 * Enable device command should be sent to modem only after
1060 * enabling voice call mixer controls
1061 */
vivek mehta765eb642015-08-07 19:46:06 -07001062 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001063 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1064 out_snd_device,
1065 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001066 /* Enable sidetone only if voice call already exists */
1067 if (voice_is_call_state_active(adev))
1068 voice_set_sidetone(adev, out_snd_device, true);
1069 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001070
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001071 return status;
1072}
1073
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001074static int stop_input_stream(struct stream_in *in)
1075{
1076 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001077 struct audio_usecase *uc_info;
1078 struct audio_device *adev = in->dev;
1079
Eric Laurentc8400632013-02-14 19:04:54 -08001080 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001081
Eric Laurent994a6932013-07-17 11:51:42 -07001082 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001083 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001084 uc_info = get_usecase_from_list(adev, in->usecase);
1085 if (uc_info == NULL) {
1086 ALOGE("%s: Could not find the usecase (%d) in the list",
1087 __func__, in->usecase);
1088 return -EINVAL;
1089 }
1090
Eric Laurent150dbfe2013-02-27 14:31:02 -08001091 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001092 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001093
1094 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001095 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001096
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001097 list_remove(&uc_info->list);
1098 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001099
Eric Laurent994a6932013-07-17 11:51:42 -07001100 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001101 return ret;
1102}
1103
1104int start_input_stream(struct stream_in *in)
1105{
1106 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001107 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001108 struct audio_usecase *uc_info;
1109 struct audio_device *adev = in->dev;
1110
Eric Laurent994a6932013-07-17 11:51:42 -07001111 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001112
1113 if (in->card_status == CARD_STATUS_OFFLINE ||
1114 adev->card_status == CARD_STATUS_OFFLINE) {
1115 ALOGW("in->card_status or adev->card_status offline, try again");
1116 ret = -EAGAIN;
1117 goto error_config;
1118 }
1119
Eric Laurentb23d5282013-05-14 15:27:20 -07001120 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001121 if (in->pcm_device_id < 0) {
1122 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1123 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001124 ret = -EINVAL;
1125 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001126 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001127
1128 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001129 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1130 uc_info->id = in->usecase;
1131 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001132 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001133 uc_info->devices = in->device;
1134 uc_info->in_snd_device = SND_DEVICE_NONE;
1135 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001136
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001137 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001138
1139 audio_extn_perf_lock_acquire();
1140
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001141 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001142
Eric Laurentc8400632013-02-14 19:04:54 -08001143 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001144 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001145
Andy Hung6ebe5962016-01-15 17:46:57 -08001146 unsigned int flags = PCM_IN | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001147 unsigned int pcm_open_retry_count = 0;
1148
1149 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1150 flags |= PCM_MMAP | PCM_NOIRQ;
1151 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001152 } else if (in->realtime) {
1153 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001154 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001155
1156 while (1) {
1157 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1158 flags, &in->config);
1159 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1160 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1161 if (in->pcm != NULL) {
1162 pcm_close(in->pcm);
1163 in->pcm = NULL;
1164 }
1165 if (pcm_open_retry_count-- == 0) {
1166 ret = -EIO;
1167 goto error_open;
1168 }
1169 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1170 continue;
1171 }
1172 break;
1173 }
1174
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001175 ALOGV("%s: pcm_prepare", __func__);
1176 ret = pcm_prepare(in->pcm);
1177 if (ret < 0) {
1178 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1179 pcm_close(in->pcm);
1180 in->pcm = NULL;
1181 goto error_open;
1182 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001183 if (in->realtime) {
1184 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001185 if (ret < 0) {
1186 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1187 pcm_close(in->pcm);
1188 in->pcm = NULL;
1189 goto error_open;
1190 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001191 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001192 register_in_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001193 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001194 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001195
Eric Laurentc8400632013-02-14 19:04:54 -08001196 return ret;
1197
1198error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001199 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001200 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001201
1202error_config:
1203 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001204 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001205
1206 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001207}
1208
Eric Laurenta1478072015-09-21 17:21:52 -07001209void lock_input_stream(struct stream_in *in)
1210{
1211 pthread_mutex_lock(&in->pre_lock);
1212 pthread_mutex_lock(&in->lock);
1213 pthread_mutex_unlock(&in->pre_lock);
1214}
1215
1216void lock_output_stream(struct stream_out *out)
1217{
1218 pthread_mutex_lock(&out->pre_lock);
1219 pthread_mutex_lock(&out->lock);
1220 pthread_mutex_unlock(&out->pre_lock);
1221}
1222
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001223/* must be called with out->lock locked */
1224static int send_offload_cmd_l(struct stream_out* out, int command)
1225{
1226 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1227
1228 ALOGVV("%s %d", __func__, command);
1229
1230 cmd->cmd = command;
1231 list_add_tail(&out->offload_cmd_list, &cmd->node);
1232 pthread_cond_signal(&out->offload_cond);
1233 return 0;
1234}
1235
1236/* must be called iwth out->lock locked */
1237static void stop_compressed_output_l(struct stream_out *out)
1238{
1239 out->offload_state = OFFLOAD_STATE_IDLE;
1240 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001241 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001242 if (out->compr != NULL) {
1243 compress_stop(out->compr);
1244 while (out->offload_thread_blocked) {
1245 pthread_cond_wait(&out->cond, &out->lock);
1246 }
1247 }
1248}
1249
1250static void *offload_thread_loop(void *context)
1251{
1252 struct stream_out *out = (struct stream_out *) context;
1253 struct listnode *item;
1254
1255 out->offload_state = OFFLOAD_STATE_IDLE;
1256 out->playback_started = 0;
1257
1258 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1259 set_sched_policy(0, SP_FOREGROUND);
1260 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1261
1262 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001263 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001264 for (;;) {
1265 struct offload_cmd *cmd = NULL;
1266 stream_callback_event_t event;
1267 bool send_callback = false;
1268
1269 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1270 __func__, list_empty(&out->offload_cmd_list),
1271 out->offload_state);
1272 if (list_empty(&out->offload_cmd_list)) {
1273 ALOGV("%s SLEEPING", __func__);
1274 pthread_cond_wait(&out->offload_cond, &out->lock);
1275 ALOGV("%s RUNNING", __func__);
1276 continue;
1277 }
1278
1279 item = list_head(&out->offload_cmd_list);
1280 cmd = node_to_item(item, struct offload_cmd, node);
1281 list_remove(item);
1282
1283 ALOGVV("%s STATE %d CMD %d out->compr %p",
1284 __func__, out->offload_state, cmd->cmd, out->compr);
1285
1286 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1287 free(cmd);
1288 break;
1289 }
1290
1291 if (out->compr == NULL) {
1292 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001293 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001294 pthread_cond_signal(&out->cond);
1295 continue;
1296 }
1297 out->offload_thread_blocked = true;
1298 pthread_mutex_unlock(&out->lock);
1299 send_callback = false;
1300 switch(cmd->cmd) {
1301 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1302 compress_wait(out->compr, -1);
1303 send_callback = true;
1304 event = STREAM_CBK_EVENT_WRITE_READY;
1305 break;
1306 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001307 compress_next_track(out->compr);
1308 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001309 send_callback = true;
1310 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001311 /* Resend the metadata for next iteration */
1312 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001313 break;
1314 case OFFLOAD_CMD_DRAIN:
1315 compress_drain(out->compr);
1316 send_callback = true;
1317 event = STREAM_CBK_EVENT_DRAIN_READY;
1318 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001319 case OFFLOAD_CMD_ERROR:
1320 send_callback = true;
1321 event = STREAM_CBK_EVENT_ERROR;
1322 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001323 default:
1324 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1325 break;
1326 }
Eric Laurenta1478072015-09-21 17:21:52 -07001327 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001328 out->offload_thread_blocked = false;
1329 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001330 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001331 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001332 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001333 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001334 free(cmd);
1335 }
1336
1337 pthread_cond_signal(&out->cond);
1338 while (!list_empty(&out->offload_cmd_list)) {
1339 item = list_head(&out->offload_cmd_list);
1340 list_remove(item);
1341 free(node_to_item(item, struct offload_cmd, node));
1342 }
1343 pthread_mutex_unlock(&out->lock);
1344
1345 return NULL;
1346}
1347
1348static int create_offload_callback_thread(struct stream_out *out)
1349{
1350 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1351 list_init(&out->offload_cmd_list);
1352 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1353 offload_thread_loop, out);
1354 return 0;
1355}
1356
1357static int destroy_offload_callback_thread(struct stream_out *out)
1358{
Eric Laurenta1478072015-09-21 17:21:52 -07001359 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001360 stop_compressed_output_l(out);
1361 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1362
1363 pthread_mutex_unlock(&out->lock);
1364 pthread_join(out->offload_thread, (void **) NULL);
1365 pthread_cond_destroy(&out->offload_cond);
1366
1367 return 0;
1368}
1369
Eric Laurent07eeafd2013-10-06 12:52:49 -07001370static bool allow_hdmi_channel_config(struct audio_device *adev)
1371{
1372 struct listnode *node;
1373 struct audio_usecase *usecase;
1374 bool ret = true;
1375
1376 list_for_each(node, &adev->usecase_list) {
1377 usecase = node_to_item(node, struct audio_usecase, list);
1378 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1379 /*
1380 * If voice call is already existing, do not proceed further to avoid
1381 * disabling/enabling both RX and TX devices, CSD calls, etc.
1382 * Once the voice call done, the HDMI channels can be configured to
1383 * max channels of remaining use cases.
1384 */
1385 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001386 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001387 __func__);
1388 ret = false;
1389 break;
1390 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
Joe Onorato188b6222016-03-01 11:02:27 -08001391 ALOGV("%s: multi channel playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001392 "no change in HDMI channels", __func__);
1393 ret = false;
1394 break;
1395 }
1396 }
1397 }
1398 return ret;
1399}
1400
1401static int check_and_set_hdmi_channels(struct audio_device *adev,
1402 unsigned int channels)
1403{
1404 struct listnode *node;
1405 struct audio_usecase *usecase;
1406
1407 /* Check if change in HDMI channel config is allowed */
1408 if (!allow_hdmi_channel_config(adev))
1409 return 0;
1410
1411 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001412 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001413 return 0;
1414 }
1415
1416 platform_set_hdmi_channels(adev->platform, channels);
1417 adev->cur_hdmi_channels = channels;
1418
1419 /*
1420 * Deroute all the playback streams routed to HDMI so that
1421 * the back end is deactivated. Note that backend will not
1422 * be deactivated if any one stream is connected to it.
1423 */
1424 list_for_each(node, &adev->usecase_list) {
1425 usecase = node_to_item(node, struct audio_usecase, list);
1426 if (usecase->type == PCM_PLAYBACK &&
1427 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001428 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001429 }
1430 }
1431
1432 /*
1433 * Enable all the streams disabled above. Now the HDMI backend
1434 * will be activated with new channel configuration
1435 */
1436 list_for_each(node, &adev->usecase_list) {
1437 usecase = node_to_item(node, struct audio_usecase, list);
1438 if (usecase->type == PCM_PLAYBACK &&
1439 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001440 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001441 }
1442 }
1443
1444 return 0;
1445}
1446
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001447static int stop_output_stream(struct stream_out *out)
1448{
1449 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001450 struct audio_usecase *uc_info;
1451 struct audio_device *adev = out->dev;
1452
Eric Laurent994a6932013-07-17 11:51:42 -07001453 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001454 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001455 uc_info = get_usecase_from_list(adev, out->usecase);
1456 if (uc_info == NULL) {
1457 ALOGE("%s: Could not find the usecase (%d) in the list",
1458 __func__, out->usecase);
1459 return -EINVAL;
1460 }
1461
Haynes Mathew George41f86652014-06-17 14:22:15 -07001462 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1463 if (adev->visualizer_stop_output != NULL)
1464 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1465 if (adev->offload_effects_stop_output != NULL)
1466 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1467 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001468
Eric Laurent150dbfe2013-02-27 14:31:02 -08001469 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001470 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001471
1472 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001473 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001474
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001475 list_remove(&uc_info->list);
1476 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001477
Eric Laurent0499d4f2014-08-25 22:39:29 -05001478 audio_extn_extspk_update(adev->extspk);
1479
Eric Laurent07eeafd2013-10-06 12:52:49 -07001480 /* Must be called after removing the usecase from list */
1481 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1482 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1483
Eric Laurent994a6932013-07-17 11:51:42 -07001484 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001485 return ret;
1486}
1487
1488int start_output_stream(struct stream_out *out)
1489{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001490 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001491 struct audio_usecase *uc_info;
1492 struct audio_device *adev = out->dev;
1493
Eric Laurent994a6932013-07-17 11:51:42 -07001494 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001495 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001496
1497 if (out->card_status == CARD_STATUS_OFFLINE ||
1498 adev->card_status == CARD_STATUS_OFFLINE) {
1499 ALOGW("out->card_status or adev->card_status offline, try again");
1500 ret = -EAGAIN;
1501 goto error_config;
1502 }
1503
Eric Laurentb23d5282013-05-14 15:27:20 -07001504 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001505 if (out->pcm_device_id < 0) {
1506 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1507 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001508 ret = -EINVAL;
1509 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001510 }
1511
1512 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1513 uc_info->id = out->usecase;
1514 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001515 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001516 uc_info->devices = out->devices;
1517 uc_info->in_snd_device = SND_DEVICE_NONE;
1518 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001519
Eric Laurent07eeafd2013-10-06 12:52:49 -07001520 /* This must be called before adding this usecase to the list */
1521 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1522 check_and_set_hdmi_channels(adev, out->config.channels);
1523
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001524 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001525
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001526 audio_extn_perf_lock_acquire();
1527
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001528 select_devices(adev, out->usecase);
1529
Eric Laurent0499d4f2014-08-25 22:39:29 -05001530 audio_extn_extspk_update(adev->extspk);
1531
Andy Hung31aca912014-03-20 17:14:59 -07001532 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001533 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001534 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001535 unsigned int flags = PCM_OUT;
1536 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001537
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001538 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1539 flags |= PCM_MMAP | PCM_NOIRQ;
1540 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001541 } else if (out->realtime) {
1542 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001543 } else
1544 flags |= PCM_MONOTONIC;
1545
1546 while (1) {
1547 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1548 flags, &out->config);
1549 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1550 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1551 if (out->pcm != NULL) {
1552 pcm_close(out->pcm);
1553 out->pcm = NULL;
1554 }
1555 if (pcm_open_retry_count-- == 0) {
1556 ret = -EIO;
1557 goto error_open;
1558 }
1559 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1560 continue;
1561 }
1562 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001563 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001564 ALOGV("%s: pcm_prepare", __func__);
1565 if (pcm_is_ready(out->pcm)) {
1566 ret = pcm_prepare(out->pcm);
1567 if (ret < 0) {
1568 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1569 pcm_close(out->pcm);
1570 out->pcm = NULL;
1571 goto error_open;
1572 }
1573 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001574 } else {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001575 out->pcm = NULL;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001576 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001577 COMPRESS_IN, &out->compr_config);
1578 if (out->compr && !is_compress_ready(out->compr)) {
1579 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1580 compress_close(out->compr);
1581 out->compr = NULL;
1582 ret = -EIO;
1583 goto error_open;
1584 }
1585 if (out->offload_callback)
1586 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001587
1588 if (adev->visualizer_start_output != NULL)
Haynes Mathew George41f86652014-06-17 14:22:15 -07001589 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1590 if (adev->offload_effects_start_output != NULL)
1591 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001592 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001593 ret = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001594 if (out->realtime) {
1595 ret = pcm_start(out->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001596 if (ret < 0) {
1597 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1598 pcm_close(out->pcm);
1599 out->pcm = NULL;
1600 goto error_open;
1601 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001602 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001603 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001604 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001605 ALOGV("%s: exit", __func__);
Haynes Mathew George03c40102016-01-29 17:57:48 -08001606 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001607error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001608 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001609 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001610error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001611 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001612}
1613
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001614static int check_input_parameters(uint32_t sample_rate,
1615 audio_format_t format,
1616 int channel_count)
1617{
vivek mehta4ed66e62016-04-15 23:33:34 -07001618 if ((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT)) {
vivek mehtadae44712015-07-27 14:13:18 -07001619 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1620 return -EINVAL;
1621 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001622
vivek mehtadae44712015-07-27 14:13:18 -07001623 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > MAX_CHANNEL_COUNT)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001624 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
vivek mehtadae44712015-07-27 14:13:18 -07001625 channel_count, MIN_CHANNEL_COUNT, MAX_CHANNEL_COUNT);
1626 return -EINVAL;
1627 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001628
1629 switch (sample_rate) {
1630 case 8000:
1631 case 11025:
1632 case 12000:
1633 case 16000:
1634 case 22050:
1635 case 24000:
1636 case 32000:
1637 case 44100:
1638 case 48000:
1639 break;
1640 default:
vivek mehtadae44712015-07-27 14:13:18 -07001641 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001642 return -EINVAL;
1643 }
1644
1645 return 0;
1646}
1647
1648static size_t get_input_buffer_size(uint32_t sample_rate,
1649 audio_format_t format,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001650 int channel_count,
1651 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001652{
1653 size_t size = 0;
1654
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001655 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1656 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001657
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001658 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001659 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001660 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07001661
1662 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001663
Glenn Kasten4f993392014-05-14 07:30:48 -07001664 /* make sure the size is multiple of 32 bytes
1665 * At 48 kHz mono 16-bit PCM:
1666 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1667 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1668 */
1669 size += 0x1f;
1670 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001671
1672 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001673}
1674
1675static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1676{
1677 struct stream_out *out = (struct stream_out *)stream;
1678
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001679 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001680}
1681
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001682static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001683{
1684 return -ENOSYS;
1685}
1686
1687static size_t out_get_buffer_size(const struct audio_stream *stream)
1688{
1689 struct stream_out *out = (struct stream_out *)stream;
1690
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001691 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1692 return out->compr_config.fragment_size;
1693 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001694 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07001695 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001696}
1697
1698static uint32_t out_get_channels(const struct audio_stream *stream)
1699{
1700 struct stream_out *out = (struct stream_out *)stream;
1701
1702 return out->channel_mask;
1703}
1704
1705static audio_format_t out_get_format(const struct audio_stream *stream)
1706{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001707 struct stream_out *out = (struct stream_out *)stream;
1708
1709 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001710}
1711
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001712static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001713{
1714 return -ENOSYS;
1715}
1716
1717static int out_standby(struct audio_stream *stream)
1718{
1719 struct stream_out *out = (struct stream_out *)stream;
1720 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001721
Eric Laurent994a6932013-07-17 11:51:42 -07001722 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001723 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001724
Eric Laurenta1478072015-09-21 17:21:52 -07001725 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001726 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001727 if (adev->adm_deregister_stream)
1728 adev->adm_deregister_stream(adev->adm_data, out->handle);
1729
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001730 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001731 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001732 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1733 if (out->pcm) {
1734 pcm_close(out->pcm);
1735 out->pcm = NULL;
1736 }
1737 } else {
1738 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001739 out->gapless_mdata.encoder_delay = 0;
1740 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001741 if (out->compr != NULL) {
1742 compress_close(out->compr);
1743 out->compr = NULL;
1744 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001745 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001746 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001747 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001748 }
1749 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001750 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001751 return 0;
1752}
1753
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001754static int out_on_error(struct audio_stream *stream)
1755{
1756 struct stream_out *out = (struct stream_out *)stream;
1757 struct audio_device *adev = out->dev;
1758 bool do_standby = false;
1759
1760 lock_output_stream(out);
1761 if (!out->standby) {
1762 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1763 stop_compressed_output_l(out);
1764 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
1765 } else
1766 do_standby = true;
1767 }
1768 pthread_mutex_unlock(&out->lock);
1769
1770 if (do_standby)
1771 return out_standby(&out->stream.common);
1772
1773 return 0;
1774}
1775
Andy Hung7401c7c2016-09-21 12:41:21 -07001776static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001777{
Andy Hung7401c7c2016-09-21 12:41:21 -07001778 struct stream_out *out = (struct stream_out *)stream;
1779
1780 // We try to get the lock for consistency,
1781 // but it isn't necessary for these variables.
1782 // If we're not in standby, we may be blocked on a write.
1783 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
1784 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
1785 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
1786
1787 if (locked) {
1788 log_dump_l(&out->error_log, fd);
1789 pthread_mutex_unlock(&out->lock);
1790 } else {
1791 // We don't have the lock here, copy for safety.
1792 struct error_log log = out->error_log;
1793 log_dump_l(&log, fd);
1794 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001795 return 0;
1796}
1797
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001798static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1799{
1800 int ret = 0;
1801 char value[32];
1802 struct compr_gapless_mdata tmp_mdata;
1803
1804 if (!out || !parms) {
1805 return -EINVAL;
1806 }
1807
1808 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1809 if (ret >= 0) {
1810 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
1811 } else {
1812 return -EINVAL;
1813 }
1814
1815 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1816 if (ret >= 0) {
1817 tmp_mdata.encoder_padding = atoi(value);
1818 } else {
1819 return -EINVAL;
1820 }
1821
1822 out->gapless_mdata = tmp_mdata;
1823 out->send_new_metadata = 1;
1824 ALOGV("%s new encoder delay %u and padding %u", __func__,
1825 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1826
1827 return 0;
1828}
1829
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001830static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1831{
1832 return out == adev->primary_output || out == adev->voice_tx_output;
1833}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001834
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001835static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1836{
1837 struct stream_out *out = (struct stream_out *)stream;
1838 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001839 struct audio_usecase *usecase;
1840 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001841 struct str_parms *parms;
1842 char value[32];
1843 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001844 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07001845 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001846
Eric Laurent2e140aa2016-06-30 17:14:46 -07001847 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001848 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001849 parms = str_parms_create_str(kvpairs);
1850 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1851 if (ret >= 0) {
1852 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07001853 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001854 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001855
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001856 /*
1857 * When HDMI cable is unplugged the music playback is paused and
1858 * the policy manager sends routing=0. But the audioflinger
1859 * continues to write data until standby time (3sec).
1860 * As the HDMI core is turned off, the write gets blocked.
1861 * Avoid this by routing audio to speaker until standby.
1862 */
1863 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
1864 val == AUDIO_DEVICE_NONE) {
1865 val = AUDIO_DEVICE_OUT_SPEAKER;
1866 }
1867
1868 /*
1869 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001870 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001871 * the select_devices(). But how do we undo this?
1872 *
1873 * For example, music playback is active on headset (deep-buffer usecase)
1874 * and if we go to ringtones and select a ringtone, low-latency usecase
1875 * will be started on headset+speaker. As we can't enable headset+speaker
1876 * and headset devices at the same time, select_devices() switches the music
1877 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1878 * So when the ringtone playback is completed, how do we undo the same?
1879 *
1880 * We are relying on the out_set_parameters() call on deep-buffer output,
1881 * once the ringtone playback is ended.
1882 * NOTE: We should not check if the current devices are same as new devices.
1883 * Because select_devices() must be called to switch back the music
1884 * playback to headset.
1885 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08001886 audio_devices_t new_dev = val;
1887 if (new_dev != AUDIO_DEVICE_NONE) {
1888 bool same_dev = out->devices == new_dev;
1889 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001890
Eric Laurenta7657192014-10-09 21:09:33 -07001891 if (output_drives_call(adev, out)) {
1892 if (!voice_is_in_call(adev)) {
1893 if (adev->mode == AUDIO_MODE_IN_CALL) {
1894 adev->current_call_output = out;
1895 ret = voice_start_call(adev);
1896 }
1897 } else {
1898 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001899 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07001900 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001901 }
vivek mehta0d3637a2016-07-24 09:32:02 -07001902
1903 if (!out->standby) {
1904 if (!same_dev) {
1905 ALOGV("update routing change");
1906 out->routing_change = true;
1907 }
1908 select_devices(adev, out->usecase);
1909 }
1910
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001911 }
1912
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001913 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001914 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05001915
1916 /*handles device and call state changes*/
1917 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001918 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001919
1920 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1921 parse_compress_metadata(out, parms);
1922 }
1923
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001924 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07001925 ALOGV("%s: exit: code(%d)", __func__, status);
1926 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001927}
1928
1929static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1930{
1931 struct stream_out *out = (struct stream_out *)stream;
1932 struct str_parms *query = str_parms_create_str(keys);
1933 char *str;
1934 char value[256];
1935 struct str_parms *reply = str_parms_create();
1936 size_t i, j;
1937 int ret;
1938 bool first = true;
Eric Laurent994a6932013-07-17 11:51:42 -07001939 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001940 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1941 if (ret >= 0) {
1942 value[0] = '\0';
1943 i = 0;
1944 while (out->supported_channel_masks[i] != 0) {
1945 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1946 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1947 if (!first) {
1948 strcat(value, "|");
1949 }
1950 strcat(value, out_channels_name_to_enum_table[j].name);
1951 first = false;
1952 break;
1953 }
1954 }
1955 i++;
1956 }
1957 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1958 str = str_parms_to_str(reply);
1959 } else {
1960 str = strdup(keys);
1961 }
1962 str_parms_destroy(query);
1963 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07001964 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001965 return str;
1966}
1967
1968static uint32_t out_get_latency(const struct audio_stream_out *stream)
1969{
Haynes Mathew George03c40102016-01-29 17:57:48 -08001970 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001971 struct stream_out *out = (struct stream_out *)stream;
1972
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001973 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
1974 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001975 else if (out->realtime) {
1976 // since the buffer won't be filled up faster than realtime,
1977 // return a smaller number
1978 period_ms = (out->af_period_multiplier * out->config.period_size *
1979 1000) / (out->config.rate);
1980 hw_delay = platform_render_latency(out->usecase)/1000;
1981 return period_ms + hw_delay;
1982 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001983
1984 return (out->config.period_count * out->config.period_size * 1000) /
1985 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001986}
1987
1988static int out_set_volume(struct audio_stream_out *stream, float left,
1989 float right)
1990{
Eric Laurenta9024de2013-04-04 09:19:12 -07001991 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001992 int volume[2];
1993
Eric Laurenta9024de2013-04-04 09:19:12 -07001994 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1995 /* only take left channel into account: the API is for stereo anyway */
1996 out->muted = (left == 0.0f);
1997 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001998 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1999 const char *mixer_ctl_name = "Compress Playback Volume";
2000 struct audio_device *adev = out->dev;
2001 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002002 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2003 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002004 /* try with the control based on device id */
2005 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2006 PCM_PLAYBACK);
2007 char ctl_name[128] = {0};
2008 snprintf(ctl_name, sizeof(ctl_name),
2009 "Compress Playback %d Volume", pcm_device_id);
2010 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2011 if (!ctl) {
2012 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2013 return -EINVAL;
2014 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002015 }
2016 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2017 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2018 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2019 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002020 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002021
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002022 return -ENOSYS;
2023}
2024
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002025// note: this call is safe only if the stream_cb is
2026// removed first in close_output_stream (as is done now).
2027static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2028{
2029 if (!stream || !parms)
2030 return;
2031
2032 struct stream_out *out = (struct stream_out *)stream;
2033 struct audio_device *adev = out->dev;
2034
2035 card_status_t status;
2036 int card;
2037 if (parse_snd_card_status(parms, &card, &status) < 0)
2038 return;
2039
2040 pthread_mutex_lock(&adev->lock);
2041 bool valid_cb = (card == adev->snd_card);
2042 pthread_mutex_unlock(&adev->lock);
2043
2044 if (!valid_cb)
2045 return;
2046
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002047 lock_output_stream(out);
2048 if (out->card_status != status)
2049 out->card_status = status;
2050 pthread_mutex_unlock(&out->lock);
2051
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002052 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2053 use_case_table[out->usecase],
2054 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2055
2056 if (status == CARD_STATUS_OFFLINE)
2057 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002058
2059 return;
2060}
2061
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002062#ifdef NO_AUDIO_OUT
2063static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
2064 const void *buffer, size_t bytes)
2065{
2066 struct stream_out *out = (struct stream_out *)stream;
2067
2068 /* No Output device supported other than BT for playback.
2069 * Sleep for the amount of buffer duration
2070 */
Eric Laurenta1478072015-09-21 17:21:52 -07002071 lock_output_stream(out);
Uday Kishore Pasupuletib14d76b2015-11-13 20:06:37 -08002072 usleep(bytes * 1000000 / audio_stream_out_frame_size(&out->stream.common) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002073 out_get_sample_rate(&out->stream.common));
2074 pthread_mutex_unlock(&out->lock);
2075 return bytes;
2076}
2077#endif
2078
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002079static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2080 size_t bytes)
2081{
2082 struct stream_out *out = (struct stream_out *)stream;
2083 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002084 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002085 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002086
Eric Laurenta1478072015-09-21 17:21:52 -07002087 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002088 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002089 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002090 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002091 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002092 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002093 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002094 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002095 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002096 goto exit;
2097 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002098
2099 if (last_known_cal_step != -1) {
2100 ALOGD("%s: retry previous failed cal level set", __func__);
2101 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2102 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002103 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002104
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002105 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002106 ALOGVV("%s: writing buffer (%d bytes) to compress device", __func__, bytes);
2107 if (out->send_new_metadata) {
2108 ALOGVV("send new gapless metadata");
2109 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2110 out->send_new_metadata = 0;
2111 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002112 unsigned int avail;
2113 struct timespec tstamp;
2114 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2115 /* Do not limit write size if the available frames count is unknown */
2116 if (ret != 0) {
2117 avail = bytes;
2118 }
2119 if (avail == 0) {
2120 ret = 0;
2121 } else {
2122 if (avail > bytes) {
2123 avail = bytes;
2124 }
2125 ret = compress_write(out->compr, buffer, avail);
2126 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2127 __func__, avail, ret);
2128 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002129
Eric Laurent6e895242013-09-05 16:10:57 -07002130 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002131 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2132 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002133 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002134 compress_start(out->compr);
2135 out->playback_started = 1;
2136 out->offload_state = OFFLOAD_STATE_PLAYING;
2137 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002138 if (ret < 0) {
2139 log_error_l(&out->error_log, ERROR_CODE_WRITE);
2140 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002141 pthread_mutex_unlock(&out->lock);
2142 return ret;
2143 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002144 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002145 if (out->pcm) {
2146 if (out->muted)
2147 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002148
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002149 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002150
Haynes Mathew George03c40102016-01-29 17:57:48 -08002151 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2152 out->config.rate;
2153 request_out_focus(out, ns);
2154
2155 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2156 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002157 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002158 else
2159 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002160
Haynes Mathew George03c40102016-01-29 17:57:48 -08002161 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002162 } else {
2163 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002164 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002165 }
2166
2167exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002168 // For PCM we always consume the buffer and return #bytes regardless of ret.
2169 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2170 out->written += bytes / (out->config.channels * sizeof(short));
2171 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002172 long long sleeptime_us = 0;
2173 if (ret != 0) {
2174 log_error_l(&out->error_log, error_code);
2175 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2176 ALOGE_IF(out->pcm != NULL,
2177 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
2178 sleeptime_us = bytes * 1000000LL / audio_stream_out_frame_size(stream) /
2179 out_get_sample_rate(&out->stream.common);
2180 // usleep not guaranteed for values over 1 second but we don't limit here.
2181 }
2182 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002183
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002184 pthread_mutex_unlock(&out->lock);
2185
2186 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002187 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002188 if (sleeptime_us != 0)
2189 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002190 }
2191 return bytes;
2192}
2193
2194static int out_get_render_position(const struct audio_stream_out *stream,
2195 uint32_t *dsp_frames)
2196{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002197 struct stream_out *out = (struct stream_out *)stream;
2198 *dsp_frames = 0;
2199 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002200 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002201 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002202 unsigned long frames = 0;
2203 // TODO: check return value
2204 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2205 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002206 ALOGVV("%s rendered frames %d sample_rate %d",
2207 __func__, *dsp_frames, out->sample_rate);
2208 }
2209 pthread_mutex_unlock(&out->lock);
2210 return 0;
2211 } else
2212 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002213}
2214
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002215static int out_add_audio_effect(const struct audio_stream *stream __unused,
2216 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002217{
2218 return 0;
2219}
2220
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002221static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2222 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002223{
2224 return 0;
2225}
2226
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002227static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2228 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002229{
2230 return -EINVAL;
2231}
2232
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002233static int out_get_presentation_position(const struct audio_stream_out *stream,
2234 uint64_t *frames, struct timespec *timestamp)
2235{
2236 struct stream_out *out = (struct stream_out *)stream;
Andy Hung7171da22016-03-08 16:58:42 -08002237 int ret = -EINVAL;
Eric Laurent949a0892013-09-20 09:20:13 -07002238 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002239
Eric Laurenta1478072015-09-21 17:21:52 -07002240 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002241
Eric Laurent949a0892013-09-20 09:20:13 -07002242 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2243 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002244 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002245 compress_get_tstamp(out->compr, &dsp_frames,
2246 &out->sample_rate);
2247 ALOGVV("%s rendered frames %ld sample_rate %d",
2248 __func__, dsp_frames, out->sample_rate);
2249 *frames = dsp_frames;
2250 ret = 0;
2251 /* this is the best we can do */
2252 clock_gettime(CLOCK_MONOTONIC, timestamp);
2253 }
2254 } else {
2255 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002256 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002257 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2258 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002259 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002260 // This adjustment accounts for buffering after app processor.
2261 // It is based on estimated DSP latency per use case, rather than exact.
2262 signed_frames -=
2263 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2264
Eric Laurent949a0892013-09-20 09:20:13 -07002265 // It would be unusual for this value to be negative, but check just in case ...
2266 if (signed_frames >= 0) {
2267 *frames = signed_frames;
2268 ret = 0;
2269 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002270 }
2271 }
2272 }
2273
2274 pthread_mutex_unlock(&out->lock);
2275
2276 return ret;
2277}
2278
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002279static int out_set_callback(struct audio_stream_out *stream,
2280 stream_callback_t callback, void *cookie)
2281{
2282 struct stream_out *out = (struct stream_out *)stream;
2283
2284 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002285 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002286 out->offload_callback = callback;
2287 out->offload_cookie = cookie;
2288 pthread_mutex_unlock(&out->lock);
2289 return 0;
2290}
2291
2292static int out_pause(struct audio_stream_out* stream)
2293{
2294 struct stream_out *out = (struct stream_out *)stream;
2295 int status = -ENOSYS;
2296 ALOGV("%s", __func__);
2297 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002298 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002299 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2300 status = compress_pause(out->compr);
2301 out->offload_state = OFFLOAD_STATE_PAUSED;
2302 }
2303 pthread_mutex_unlock(&out->lock);
2304 }
2305 return status;
2306}
2307
2308static int out_resume(struct audio_stream_out* stream)
2309{
2310 struct stream_out *out = (struct stream_out *)stream;
2311 int status = -ENOSYS;
2312 ALOGV("%s", __func__);
2313 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2314 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002315 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002316 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2317 status = compress_resume(out->compr);
2318 out->offload_state = OFFLOAD_STATE_PLAYING;
2319 }
2320 pthread_mutex_unlock(&out->lock);
2321 }
2322 return status;
2323}
2324
2325static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2326{
2327 struct stream_out *out = (struct stream_out *)stream;
2328 int status = -ENOSYS;
2329 ALOGV("%s", __func__);
2330 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002331 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002332 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2333 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2334 else
2335 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2336 pthread_mutex_unlock(&out->lock);
2337 }
2338 return status;
2339}
2340
2341static int out_flush(struct audio_stream_out* stream)
2342{
2343 struct stream_out *out = (struct stream_out *)stream;
2344 ALOGV("%s", __func__);
2345 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002346 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002347 stop_compressed_output_l(out);
2348 pthread_mutex_unlock(&out->lock);
2349 return 0;
2350 }
2351 return -ENOSYS;
2352}
2353
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002354/** audio_stream_in implementation **/
2355static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2356{
2357 struct stream_in *in = (struct stream_in *)stream;
2358
2359 return in->config.rate;
2360}
2361
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002362static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002363{
2364 return -ENOSYS;
2365}
2366
2367static size_t in_get_buffer_size(const struct audio_stream *stream)
2368{
2369 struct stream_in *in = (struct stream_in *)stream;
2370
Haynes Mathew George03c40102016-01-29 17:57:48 -08002371 return in->config.period_size * in->af_period_multiplier *
2372 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002373}
2374
2375static uint32_t in_get_channels(const struct audio_stream *stream)
2376{
2377 struct stream_in *in = (struct stream_in *)stream;
2378
2379 return in->channel_mask;
2380}
2381
vivek mehta4ed66e62016-04-15 23:33:34 -07002382static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002383{
vivek mehta4ed66e62016-04-15 23:33:34 -07002384 struct stream_in *in = (struct stream_in *)stream;
2385 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002386}
2387
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002388static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002389{
2390 return -ENOSYS;
2391}
2392
2393static int in_standby(struct audio_stream *stream)
2394{
2395 struct stream_in *in = (struct stream_in *)stream;
2396 struct audio_device *adev = in->dev;
2397 int status = 0;
Eric Laurent994a6932013-07-17 11:51:42 -07002398 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002399
2400 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002401
2402 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08002403 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002404 audio_extn_sound_trigger_stop_lab(in);
2405 in->standby = true;
2406 }
2407
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002408 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002409 if (adev->adm_deregister_stream)
2410 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2411
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002412 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002413 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002414 if (in->pcm) {
2415 pcm_close(in->pcm);
2416 in->pcm = NULL;
2417 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002418 adev->enable_voicerx = false;
2419 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002420 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002421 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002422 }
2423 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002424 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002425 return status;
2426}
2427
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002428static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002429{
2430 return 0;
2431}
2432
2433static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2434{
2435 struct stream_in *in = (struct stream_in *)stream;
2436 struct audio_device *adev = in->dev;
2437 struct str_parms *parms;
2438 char *str;
2439 char value[32];
2440 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07002441 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002442
Eric Laurent994a6932013-07-17 11:51:42 -07002443 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002444 parms = str_parms_create_str(kvpairs);
2445
2446 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2447
Eric Laurenta1478072015-09-21 17:21:52 -07002448 lock_input_stream(in);
2449
Eric Laurent150dbfe2013-02-27 14:31:02 -08002450 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002451 if (ret >= 0) {
2452 val = atoi(value);
2453 /* no audio source uses val == 0 */
2454 if ((in->source != val) && (val != 0)) {
2455 in->source = val;
2456 }
2457 }
2458
2459 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07002460
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002461 if (ret >= 0) {
2462 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002463 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002464 in->device = val;
2465 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002466 if (!in->standby) {
2467 ALOGV("update input routing change");
2468 in->routing_change = true;
2469 select_devices(adev, in->usecase);
2470 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002471 }
2472 }
2473
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002474 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002475 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002476
2477 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002478 ALOGV("%s: exit: status(%d)", __func__, status);
2479 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002480}
2481
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002482static char* in_get_parameters(const struct audio_stream *stream __unused,
2483 const char *keys __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002484{
2485 return strdup("");
2486}
2487
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002488static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002489{
2490 return 0;
2491}
2492
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002493static void in_snd_mon_cb(void * stream, struct str_parms * parms)
2494{
2495 if (!stream || !parms)
2496 return;
2497
2498 struct stream_in *in = (struct stream_in *)stream;
2499 struct audio_device *adev = in->dev;
2500
2501 card_status_t status;
2502 int card;
2503 if (parse_snd_card_status(parms, &card, &status) < 0)
2504 return;
2505
2506 pthread_mutex_lock(&adev->lock);
2507 bool valid_cb = (card == adev->snd_card);
2508 pthread_mutex_unlock(&adev->lock);
2509
2510 if (!valid_cb)
2511 return;
2512
2513 lock_input_stream(in);
2514 if (in->card_status != status)
2515 in->card_status = status;
2516 pthread_mutex_unlock(&in->lock);
2517
2518 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
2519 use_case_table[in->usecase],
2520 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2521
2522 // a better solution would be to report error back to AF and let
2523 // it put the stream to standby
2524 if (status == CARD_STATUS_OFFLINE)
2525 in_standby(&in->stream.common);
2526
2527 return;
2528}
2529
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002530static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2531 size_t bytes)
2532{
2533 struct stream_in *in = (struct stream_in *)stream;
2534 struct audio_device *adev = in->dev;
2535 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07002536 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002537
Eric Laurenta1478072015-09-21 17:21:52 -07002538 lock_input_stream(in);
2539
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002540 if (in->is_st_session) {
2541 ALOGVV(" %s: reading on st session bytes=%d", __func__, bytes);
2542 /* Read from sound trigger HAL */
2543 audio_extn_sound_trigger_read(in, buffer, bytes);
2544 pthread_mutex_unlock(&in->lock);
2545 return bytes;
2546 }
2547
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002548 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002549 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002550 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002551 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002552 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002553 goto exit;
2554 }
2555 in->standby = 0;
2556 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002557
Haynes Mathew George03c40102016-01-29 17:57:48 -08002558 //what's the duration requested by the client?
2559 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
2560 in->config.rate;
2561 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002562
Haynes Mathew George03c40102016-01-29 17:57:48 -08002563 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002564 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002565 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002566 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07002567 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002568 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002569 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002570 if (ret < 0) {
2571 ALOGE("Failed to read w/err %s", strerror(errno));
2572 ret = -errno;
2573 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002574 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
2575 if (bytes % 4 == 0) {
2576 /* data from DSP comes in 24_8 format, convert it to 8_24 */
2577 int_buf_stream = buffer;
2578 for (size_t itt=0; itt < bytes/4 ; itt++) {
2579 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07002580 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002581 } else {
2582 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
2583 ret = -EINVAL;
2584 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07002585 }
2586 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002587 }
2588
Haynes Mathew George03c40102016-01-29 17:57:48 -08002589 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002590
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002591 /*
2592 * Instead of writing zeroes here, we could trust the hardware
2593 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002594 * 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 -08002595 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002596 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002597 memset(buffer, 0, bytes);
2598
2599exit:
2600 pthread_mutex_unlock(&in->lock);
2601
2602 if (ret != 0) {
2603 in_standby(&in->stream.common);
2604 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Eric Laurentfdf296a2014-07-03 16:41:51 -07002605 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002606 in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08002607 memset(buffer, 0, bytes); // clear return data
2608 }
2609 if (bytes > 0) {
Andy Hung6ebe5962016-01-15 17:46:57 -08002610 in->frames_read += bytes / audio_stream_in_frame_size(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002611 }
2612 return bytes;
2613}
2614
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002615static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002616{
2617 return 0;
2618}
2619
Andy Hung6ebe5962016-01-15 17:46:57 -08002620static int in_get_capture_position(const struct audio_stream_in *stream,
2621 int64_t *frames, int64_t *time)
2622{
2623 if (stream == NULL || frames == NULL || time == NULL) {
2624 return -EINVAL;
2625 }
2626 struct stream_in *in = (struct stream_in *)stream;
2627 int ret = -ENOSYS;
2628
2629 lock_input_stream(in);
2630 if (in->pcm) {
2631 struct timespec timestamp;
2632 unsigned int avail;
2633 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
2634 *frames = in->frames_read + avail;
2635 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
2636 ret = 0;
2637 }
2638 }
2639 pthread_mutex_unlock(&in->lock);
2640 return ret;
2641}
2642
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002643static int add_remove_audio_effect(const struct audio_stream *stream,
2644 effect_handle_t effect,
2645 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002646{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002647 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002648 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002649 int status = 0;
2650 effect_descriptor_t desc;
2651
2652 status = (*effect)->get_descriptor(effect, &desc);
2653 if (status != 0)
2654 return status;
2655
Eric Laurenta1478072015-09-21 17:21:52 -07002656 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002657 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07002658 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07002659 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07002660 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002661 in->enable_aec != enable &&
2662 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2663 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002664 if (!enable)
2665 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07002666 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2667 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
2668 adev->enable_voicerx = enable;
2669 struct audio_usecase *usecase;
2670 struct listnode *node;
2671 list_for_each(node, &adev->usecase_list) {
2672 usecase = node_to_item(node, struct audio_usecase, list);
2673 if (usecase->type == PCM_PLAYBACK) {
2674 select_devices(adev, usecase->id);
2675 break;
2676 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002677 }
2678 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002679 if (!in->standby)
2680 select_devices(in->dev, in->usecase);
2681 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07002682 if (in->enable_ns != enable &&
2683 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2684 in->enable_ns = enable;
2685 if (!in->standby)
2686 select_devices(in->dev, in->usecase);
2687 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002688 pthread_mutex_unlock(&in->dev->lock);
2689 pthread_mutex_unlock(&in->lock);
2690
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002691 return 0;
2692}
2693
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002694static int in_add_audio_effect(const struct audio_stream *stream,
2695 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002696{
Eric Laurent994a6932013-07-17 11:51:42 -07002697 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002698 return add_remove_audio_effect(stream, effect, true);
2699}
2700
2701static int in_remove_audio_effect(const struct audio_stream *stream,
2702 effect_handle_t effect)
2703{
Eric Laurent994a6932013-07-17 11:51:42 -07002704 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002705 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002706}
2707
2708static int adev_open_output_stream(struct audio_hw_device *dev,
2709 audio_io_handle_t handle,
2710 audio_devices_t devices,
2711 audio_output_flags_t flags,
2712 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07002713 struct audio_stream_out **stream_out,
2714 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002715{
2716 struct audio_device *adev = (struct audio_device *)dev;
2717 struct stream_out *out;
2718 int i, ret;
2719
Eric Laurent994a6932013-07-17 11:51:42 -07002720 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002721 __func__, config->sample_rate, config->channel_mask, devices, flags);
2722 *stream_out = NULL;
2723 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2724
2725 if (devices == AUDIO_DEVICE_NONE)
2726 devices = AUDIO_DEVICE_OUT_SPEAKER;
2727
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002728 out->flags = flags;
2729 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002730 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002731 out->format = config->format;
2732 out->sample_rate = config->sample_rate;
2733 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2734 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002735 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002736
2737 /* Init use case and pcm_config */
2738 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
Eric Laurent7f245042013-09-30 19:22:50 -07002739 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002740 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002741 pthread_mutex_lock(&adev->lock);
2742 ret = read_hdmi_channel_masks(out);
2743 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002744 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002745 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002746
2747 if (config->sample_rate == 0)
2748 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2749 if (config->channel_mask == 0)
2750 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Eric Laurentad1cec22015-12-16 10:12:27 -08002751 if (config->format == AUDIO_FORMAT_DEFAULT)
2752 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002753
2754 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002755 out->sample_rate = config->sample_rate;
Eric Laurentad1cec22015-12-16 10:12:27 -08002756 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002757 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2758 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002759 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002760 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002761 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002762 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07002763 pthread_mutex_lock(&adev->lock);
2764 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
2765 pthread_mutex_unlock(&adev->lock);
2766
2767 // reject offload during card offline to allow
2768 // fallback to s/w paths
2769 if (offline) {
2770 ret = -ENODEV;
2771 goto error_open;
2772 }
2773
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002774 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2775 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2776 ALOGE("%s: Unsupported Offload information", __func__);
2777 ret = -EINVAL;
2778 goto error_open;
2779 }
2780 if (!is_supported_format(config->offload_info.format)) {
2781 ALOGE("%s: Unsupported audio format", __func__);
2782 ret = -EINVAL;
2783 goto error_open;
2784 }
2785
2786 out->compr_config.codec = (struct snd_codec *)
2787 calloc(1, sizeof(struct snd_codec));
2788
2789 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
2790 if (config->offload_info.channel_mask)
2791 out->channel_mask = config->offload_info.channel_mask;
2792 else if (config->channel_mask)
2793 out->channel_mask = config->channel_mask;
2794 out->format = config->offload_info.format;
2795 out->sample_rate = config->offload_info.sample_rate;
2796
2797 out->stream.set_callback = out_set_callback;
2798 out->stream.pause = out_pause;
2799 out->stream.resume = out_resume;
2800 out->stream.drain = out_drain;
2801 out->stream.flush = out_flush;
2802
2803 out->compr_config.codec->id =
2804 get_snd_codec_id(config->offload_info.format);
2805 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
2806 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07002807 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002808 out->compr_config.codec->bit_rate =
2809 config->offload_info.bit_rate;
2810 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002811 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002812 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
2813
2814 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2815 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002816
2817 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002818 create_offload_callback_thread(out);
2819 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2820 __func__, config->offload_info.version,
2821 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002822 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2823 if (config->sample_rate == 0)
2824 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2825 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2826 config->sample_rate != 8000) {
2827 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2828 ret = -EINVAL;
2829 goto error_open;
2830 }
2831 out->sample_rate = config->sample_rate;
2832 out->config.rate = config->sample_rate;
2833 if (config->format == AUDIO_FORMAT_DEFAULT)
2834 config->format = AUDIO_FORMAT_PCM_16_BIT;
2835 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2836 config->format = AUDIO_FORMAT_PCM_16_BIT;
2837 ret = -EINVAL;
2838 goto error_open;
2839 }
2840 out->format = config->format;
2841 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2842 out->config = pcm_config_afe_proxy_playback;
2843 adev->voice_tx_output = out;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002844 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07002845 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2846 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2847 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07002848 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
2849 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
2850 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07002851 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
2852 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002853 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
2854 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
2855 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Andy Hung6fcba9c2014-03-18 11:53:32 -07002856 } else {
2857 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2858 out->config = pcm_config_low_latency;
2859 }
2860 if (config->format != audio_format_from_pcm_format(out->config.format)) {
2861 if (k_enable_extended_precision
2862 && pcm_params_format_test(adev->use_case_table[out->usecase],
2863 pcm_format_from_audio_format(config->format))) {
2864 out->config.format = pcm_format_from_audio_format(config->format);
2865 /* out->format already set to config->format */
2866 } else {
2867 /* deny the externally proposed config format
2868 * and use the one specified in audio_hw layer configuration.
2869 * Note: out->format is returned by out->stream.common.get_format()
2870 * and is used to set config->format in the code several lines below.
2871 */
2872 out->format = audio_format_from_pcm_format(out->config.format);
2873 }
2874 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002875 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002876 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07002877 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
2878 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002879
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002880 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002881 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002882 adev->primary_output = out;
2883 else {
2884 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002885 ret = -EEXIST;
2886 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002887 }
2888 }
2889
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002890 /* Check if this usecase is already existing */
2891 pthread_mutex_lock(&adev->lock);
2892 if (get_usecase_from_list(adev, out->usecase) != NULL) {
2893 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002894 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002895 ret = -EEXIST;
2896 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002897 }
2898 pthread_mutex_unlock(&adev->lock);
2899
2900 out->stream.common.get_sample_rate = out_get_sample_rate;
2901 out->stream.common.set_sample_rate = out_set_sample_rate;
2902 out->stream.common.get_buffer_size = out_get_buffer_size;
2903 out->stream.common.get_channels = out_get_channels;
2904 out->stream.common.get_format = out_get_format;
2905 out->stream.common.set_format = out_set_format;
2906 out->stream.common.standby = out_standby;
2907 out->stream.common.dump = out_dump;
2908 out->stream.common.set_parameters = out_set_parameters;
2909 out->stream.common.get_parameters = out_get_parameters;
2910 out->stream.common.add_audio_effect = out_add_audio_effect;
2911 out->stream.common.remove_audio_effect = out_remove_audio_effect;
2912 out->stream.get_latency = out_get_latency;
2913 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002914#ifdef NO_AUDIO_OUT
2915 out->stream.write = out_write_for_no_output;
2916#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002917 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002918#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002919 out->stream.get_render_position = out_get_render_position;
2920 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002921 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002922
Haynes Mathew George03c40102016-01-29 17:57:48 -08002923 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002924 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07002925 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002926 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002927
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002928 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07002929 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002930 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2931
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002932 config->format = out->stream.common.get_format(&out->stream.common);
2933 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
2934 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
2935
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002936
2937 /*
2938 By locking output stream before registering, we allow the callback
2939 to update stream's state only after stream's initial state is set to
2940 adev state.
2941 */
2942 lock_output_stream(out);
2943 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
2944 pthread_mutex_lock(&adev->lock);
2945 out->card_status = adev->card_status;
2946 pthread_mutex_unlock(&adev->lock);
2947 pthread_mutex_unlock(&out->lock);
2948
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002949 *stream_out = &out->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07002950 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002951 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002952
2953error_open:
2954 free(out);
2955 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07002956 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002957 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002958}
2959
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002960static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002961 struct audio_stream_out *stream)
2962{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002963 struct stream_out *out = (struct stream_out *)stream;
2964 struct audio_device *adev = out->dev;
2965
Eric Laurent994a6932013-07-17 11:51:42 -07002966 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002967
2968 // must deregister from sndmonitor first to prevent races
2969 // between the callback and close_stream
2970 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002971 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002972 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2973 destroy_offload_callback_thread(out);
2974
2975 if (out->compr_config.codec != NULL)
2976 free(out->compr_config.codec);
2977 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07002978
2979 if (adev->voice_tx_output == out)
2980 adev->voice_tx_output = NULL;
2981
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002982 pthread_cond_destroy(&out->cond);
2983 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002984 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07002985 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002986}
2987
2988static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
2989{
2990 struct audio_device *adev = (struct audio_device *)dev;
2991 struct str_parms *parms;
2992 char *str;
2993 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002994 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002995 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07002996 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002997
Joe Onorato188b6222016-03-01 11:02:27 -08002998 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002999
3000 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003001
3002 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003003 status = voice_set_parameters(adev, parms);
3004 if (status != 0) {
3005 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003006 }
3007
3008 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3009 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003010 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003011 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3012 adev->bluetooth_nrec = true;
3013 else
3014 adev->bluetooth_nrec = false;
3015 }
3016
3017 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3018 if (ret >= 0) {
3019 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3020 adev->screen_off = false;
3021 else
3022 adev->screen_off = true;
3023 }
3024
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003025 ret = str_parms_get_int(parms, "rotation", &val);
3026 if (ret >= 0) {
3027 bool reverse_speakers = false;
3028 switch(val) {
3029 // FIXME: note that the code below assumes that the speakers are in the correct placement
3030 // relative to the user when the device is rotated 90deg from its default rotation. This
3031 // assumption is device-specific, not platform-specific like this code.
3032 case 270:
3033 reverse_speakers = true;
3034 break;
3035 case 0:
3036 case 90:
3037 case 180:
3038 break;
3039 default:
3040 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003041 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003042 }
Eric Laurent03f09432014-03-25 18:09:11 -07003043 if (status == 0) {
Ravi Kumar Alamanda1f60cf82015-04-23 19:45:17 -07003044 platform_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003045 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003046 }
3047
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003048 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3049 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003050 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003051 }
3052
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08003053 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003054done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003055 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003056 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07003057 ALOGV("%s: exit with code(%d)", __func__, status);
3058 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003059}
3060
3061static char* adev_get_parameters(const struct audio_hw_device *dev,
3062 const char *keys)
3063{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003064 struct audio_device *adev = (struct audio_device *)dev;
3065 struct str_parms *reply = str_parms_create();
3066 struct str_parms *query = str_parms_create_str(keys);
3067 char *str;
3068
3069 pthread_mutex_lock(&adev->lock);
3070
3071 voice_get_parameters(adev, query, reply);
3072 str = str_parms_to_str(reply);
3073 str_parms_destroy(query);
3074 str_parms_destroy(reply);
3075
3076 pthread_mutex_unlock(&adev->lock);
3077 ALOGV("%s: exit: returns - %s", __func__, str);
3078 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003079}
3080
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003081static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003082{
3083 return 0;
3084}
3085
Haynes Mathew George5191a852013-09-11 14:19:36 -07003086static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3087{
3088 int ret;
3089 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003090
Eric Laurent4cc4ce12014-09-10 13:21:01 -05003091 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
3092
Haynes Mathew George5191a852013-09-11 14:19:36 -07003093 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003094 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003095 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003096
Haynes Mathew George5191a852013-09-11 14:19:36 -07003097 return ret;
3098}
3099
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003100static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003101{
3102 return -ENOSYS;
3103}
3104
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003105static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3106 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003107{
3108 return -ENOSYS;
3109}
3110
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003111static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003112{
3113 return -ENOSYS;
3114}
3115
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003116static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003117{
3118 return -ENOSYS;
3119}
3120
3121static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3122{
3123 struct audio_device *adev = (struct audio_device *)dev;
3124
3125 pthread_mutex_lock(&adev->lock);
3126 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07003127 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003128 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07003129 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3130 voice_is_in_call(adev)) {
3131 voice_stop_call(adev);
3132 adev->current_call_output = NULL;
3133 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003134 }
3135 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003136
3137 audio_extn_extspk_set_mode(adev->extspk, mode);
3138
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003139 return 0;
3140}
3141
3142static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3143{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003144 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003145 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003146
Eric Laurent2bafff12016-03-17 12:17:23 -07003147 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003148 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003149 ret = voice_set_mic_mute(adev, state);
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003150 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00003151 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003152
3153 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003154}
3155
3156static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3157{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003158 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003159 return 0;
3160}
3161
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003162static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003163 const struct audio_config *config)
3164{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003165 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003166
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003167 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3168 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003169}
3170
3171static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003172 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003173 audio_devices_t devices,
3174 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003175 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07003176 audio_input_flags_t flags,
3177 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05003178 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003179{
3180 struct audio_device *adev = (struct audio_device *)dev;
3181 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003182 int ret = 0, buffer_size, frame_size;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003183 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003184 bool is_low_latency = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003185
Eric Laurent994a6932013-07-17 11:51:42 -07003186 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003187 *stream_in = NULL;
3188 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3189 return -EINVAL;
3190
3191 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
3192
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003193 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003194 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003195
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003196 in->stream.common.get_sample_rate = in_get_sample_rate;
3197 in->stream.common.set_sample_rate = in_set_sample_rate;
3198 in->stream.common.get_buffer_size = in_get_buffer_size;
3199 in->stream.common.get_channels = in_get_channels;
3200 in->stream.common.get_format = in_get_format;
3201 in->stream.common.set_format = in_set_format;
3202 in->stream.common.standby = in_standby;
3203 in->stream.common.dump = in_dump;
3204 in->stream.common.set_parameters = in_set_parameters;
3205 in->stream.common.get_parameters = in_get_parameters;
3206 in->stream.common.add_audio_effect = in_add_audio_effect;
3207 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3208 in->stream.set_gain = in_set_gain;
3209 in->stream.read = in_read;
3210 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08003211 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003212
3213 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003214 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003215 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003216 in->standby = 1;
3217 in->channel_mask = config->channel_mask;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003218 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003219 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003220
vivek mehta57ff9b52016-04-28 14:13:08 -07003221 // restrict 24 bit capture for unprocessed source only
3222 // for other sources if 24 bit requested reject 24 and set 16 bit capture only
3223 if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07003224 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07003225 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
3226 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
3227 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
3228 bool ret_error = false;
3229 /* 24 bit is restricted to UNPROCESSED source only,also format supported
3230 from HAL is 8_24
3231 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
3232 8_24 return error indicating supported format is 8_24
3233 *> In case of any other source requesting 24 bit or float return error
3234 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07003235
vivek mehta57ff9b52016-04-28 14:13:08 -07003236 on error flinger will retry with supported format passed
3237 */
3238 if (source != AUDIO_SOURCE_UNPROCESSED) {
3239 config->format = AUDIO_FORMAT_PCM_16_BIT;
3240 ret_error = true;
3241 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
3242 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
3243 ret_error = true;
3244 }
3245
3246 if (ret_error) {
3247 ret = -EINVAL;
3248 goto err_open;
3249 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003250 }
3251
vivek mehta57ff9b52016-04-28 14:13:08 -07003252 in->format = config->format;
3253
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003254 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003255 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
3256 if (config->sample_rate == 0)
3257 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3258 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3259 config->sample_rate != 8000) {
3260 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3261 ret = -EINVAL;
3262 goto err_open;
3263 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003264
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003265 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3266 config->format = AUDIO_FORMAT_PCM_16_BIT;
3267 ret = -EINVAL;
3268 goto err_open;
3269 }
3270
3271 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3272 in->config = pcm_config_afe_proxy_record;
3273 } else {
3274 in->usecase = USECASE_AUDIO_RECORD;
3275 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3276 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3277 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07003278#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003279 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07003280#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08003281 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003282 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003283
Haynes Mathew George03c40102016-01-29 17:57:48 -08003284 in->config = in->realtime ? pcm_config_audio_capture_rt :
3285 pcm_config_audio_capture;
3286
vivek mehta4ed66e62016-04-15 23:33:34 -07003287 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
3288 in->config.format = PCM_FORMAT_S24_LE;
3289
Haynes Mathew George03c40102016-01-29 17:57:48 -08003290 if (!in->realtime) {
3291 frame_size = audio_stream_in_frame_size(&in->stream);
3292 buffer_size = get_input_buffer_size(config->sample_rate,
3293 config->format,
3294 channel_count,
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003295 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003296 in->config.period_size = buffer_size / frame_size;
3297 } // period size is left untouched for rt mode playback
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003298 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003299
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003300 in->config.channels = channel_count;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003301 if (in->realtime) {
3302 in->af_period_multiplier = af_period_multiplier;
3303 } else {
3304 in->config.rate = config->sample_rate;
3305 in->af_period_multiplier = 1;
3306 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003307
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003308 /* This stream could be for sound trigger lab,
3309 get sound trigger pcm if present */
3310 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003311
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003312 lock_input_stream(in);
3313 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
3314 pthread_mutex_lock(&adev->lock);
3315 in->card_status = adev->card_status;
3316 pthread_mutex_unlock(&adev->lock);
3317 pthread_mutex_unlock(&in->lock);
3318
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003319 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003320 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003321 return 0;
3322
3323err_open:
3324 free(in);
3325 *stream_in = NULL;
3326 return ret;
3327}
3328
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003329static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003330 struct audio_stream_in *stream)
3331{
Eric Laurent994a6932013-07-17 11:51:42 -07003332 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003333
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003334 // must deregister from sndmonitor first to prevent races
3335 // between the callback and close_stream
3336 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003337 in_standby(&stream->common);
3338 free(stream);
3339
3340 return;
3341}
3342
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003343static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003344{
3345 return 0;
3346}
3347
Andy Hung31aca912014-03-20 17:14:59 -07003348/* verifies input and output devices and their capabilities.
3349 *
3350 * This verification is required when enabling extended bit-depth or
3351 * sampling rates, as not all qcom products support it.
3352 *
3353 * Suitable for calling only on initialization such as adev_open().
3354 * It fills the audio_device use_case_table[] array.
3355 *
3356 * Has a side-effect that it needs to configure audio routing / devices
3357 * in order to power up the devices and read the device parameters.
3358 * It does not acquire any hw device lock. Should restore the devices
3359 * back to "normal state" upon completion.
3360 */
3361static int adev_verify_devices(struct audio_device *adev)
3362{
3363 /* enumeration is a bit difficult because one really wants to pull
3364 * the use_case, device id, etc from the hidden pcm_device_table[].
3365 * In this case there are the following use cases and device ids.
3366 *
3367 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
3368 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
3369 * [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
3370 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
3371 * [USECASE_AUDIO_RECORD] = {0, 0},
3372 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
3373 * [USECASE_VOICE_CALL] = {2, 2},
3374 *
3375 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_MULTI_CH omitted.
3376 * USECASE_VOICE_CALL omitted, but possible for either input or output.
3377 */
3378
3379 /* should be the usecases enabled in adev_open_input_stream() */
3380 static const int test_in_usecases[] = {
3381 USECASE_AUDIO_RECORD,
3382 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
3383 };
3384 /* should be the usecases enabled in adev_open_output_stream()*/
3385 static const int test_out_usecases[] = {
3386 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
3387 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
3388 };
3389 static const usecase_type_t usecase_type_by_dir[] = {
3390 PCM_PLAYBACK,
3391 PCM_CAPTURE,
3392 };
3393 static const unsigned flags_by_dir[] = {
3394 PCM_OUT,
3395 PCM_IN,
3396 };
3397
3398 size_t i;
3399 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003400 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07003401 char info[512]; /* for possible debug info */
3402
3403 for (dir = 0; dir < 2; ++dir) {
3404 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
3405 const unsigned flags_dir = flags_by_dir[dir];
3406 const size_t testsize =
3407 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
3408 const int *testcases =
3409 dir ? test_in_usecases : test_out_usecases;
3410 const audio_devices_t audio_device =
3411 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
3412
3413 for (i = 0; i < testsize; ++i) {
3414 const audio_usecase_t audio_usecase = testcases[i];
3415 int device_id;
3416 snd_device_t snd_device;
3417 struct pcm_params **pparams;
3418 struct stream_out out;
3419 struct stream_in in;
3420 struct audio_usecase uc_info;
3421 int retval;
3422
3423 pparams = &adev->use_case_table[audio_usecase];
3424 pcm_params_free(*pparams); /* can accept null input */
3425 *pparams = NULL;
3426
3427 /* find the device ID for the use case (signed, for error) */
3428 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
3429 if (device_id < 0)
3430 continue;
3431
3432 /* prepare structures for device probing */
3433 memset(&uc_info, 0, sizeof(uc_info));
3434 uc_info.id = audio_usecase;
3435 uc_info.type = usecase_type;
3436 if (dir) {
3437 adev->active_input = &in;
3438 memset(&in, 0, sizeof(in));
3439 in.device = audio_device;
3440 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
3441 uc_info.stream.in = &in;
3442 } else {
3443 adev->active_input = NULL;
3444 }
3445 memset(&out, 0, sizeof(out));
3446 out.devices = audio_device; /* only field needed in select_devices */
3447 uc_info.stream.out = &out;
3448 uc_info.devices = audio_device;
3449 uc_info.in_snd_device = SND_DEVICE_NONE;
3450 uc_info.out_snd_device = SND_DEVICE_NONE;
3451 list_add_tail(&adev->usecase_list, &uc_info.list);
3452
3453 /* select device - similar to start_(in/out)put_stream() */
3454 retval = select_devices(adev, audio_usecase);
3455 if (retval >= 0) {
3456 *pparams = pcm_params_get(card_id, device_id, flags_dir);
3457#if LOG_NDEBUG == 0
3458 if (*pparams) {
3459 ALOGV("%s: (%s) card %d device %d", __func__,
3460 dir ? "input" : "output", card_id, device_id);
3461 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07003462 } else {
3463 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
3464 }
3465#endif
3466 }
3467
3468 /* deselect device - similar to stop_(in/out)put_stream() */
3469 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07003470 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07003471 /* 2. Disable the rx device */
3472 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07003473 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07003474 list_remove(&uc_info.list);
3475 }
3476 }
3477 adev->active_input = NULL; /* restore adev state */
3478 return 0;
3479}
3480
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003481static int adev_close(hw_device_t *device)
3482{
Andy Hung31aca912014-03-20 17:14:59 -07003483 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003484 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003485
3486 if (!adev)
3487 return 0;
3488
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003489 audio_extn_snd_mon_unregister_listener(adev);
vivek mehta1a9b7c02015-06-25 11:49:38 -07003490 pthread_mutex_lock(&adev_init_lock);
3491
3492 if ((--audio_device_ref_count) == 0) {
3493 audio_route_free(adev->audio_route);
3494 free(adev->snd_dev_ref_cnt);
3495 platform_deinit(adev->platform);
3496 audio_extn_extspk_deinit(adev->extspk);
3497 audio_extn_sound_trigger_deinit(adev);
3498 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
3499 pcm_params_free(adev->use_case_table[i]);
3500 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003501 if (adev->adm_deinit)
3502 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07003503 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07003504 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07003505
3506 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003507
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003508 return 0;
3509}
3510
Glenn Kasten4f993392014-05-14 07:30:48 -07003511/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3512 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3513 * just that it _might_ work.
3514 */
3515static int period_size_is_plausible_for_low_latency(int period_size)
3516{
3517 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07003518 case 48:
3519 case 96:
3520 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07003521 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07003522 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07003523 case 240:
3524 case 320:
3525 case 480:
3526 return 1;
3527 default:
3528 return 0;
3529 }
3530}
3531
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003532static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
3533{
3534 int card;
3535 card_status_t status;
3536
3537 if (!parms)
3538 return;
3539
3540 if (parse_snd_card_status(parms, &card, &status) < 0)
3541 return;
3542
3543 pthread_mutex_lock(&adev->lock);
3544 bool valid_cb = (card == adev->snd_card);
3545 if (valid_cb) {
3546 if (adev->card_status != status) {
3547 adev->card_status = status;
3548 platform_snd_card_update(adev->platform, status);
3549 }
3550 }
3551 pthread_mutex_unlock(&adev->lock);
3552 return;
3553}
3554
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003555static int adev_open(const hw_module_t *module, const char *name,
3556 hw_device_t **device)
3557{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003558 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003559
Eric Laurent2bafff12016-03-17 12:17:23 -07003560 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003561 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003562 pthread_mutex_lock(&adev_init_lock);
3563 if (audio_device_ref_count != 0) {
3564 *device = &adev->device.common;
3565 audio_device_ref_count++;
3566 ALOGV("%s: returning existing instance of adev", __func__);
3567 ALOGV("%s: exit", __func__);
3568 pthread_mutex_unlock(&adev_init_lock);
3569 return 0;
3570 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003571 adev = calloc(1, sizeof(struct audio_device));
3572
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003573 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3574
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003575 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3576 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3577 adev->device.common.module = (struct hw_module_t *)module;
3578 adev->device.common.close = adev_close;
3579
3580 adev->device.init_check = adev_init_check;
3581 adev->device.set_voice_volume = adev_set_voice_volume;
3582 adev->device.set_master_volume = adev_set_master_volume;
3583 adev->device.get_master_volume = adev_get_master_volume;
3584 adev->device.set_master_mute = adev_set_master_mute;
3585 adev->device.get_master_mute = adev_get_master_mute;
3586 adev->device.set_mode = adev_set_mode;
3587 adev->device.set_mic_mute = adev_set_mic_mute;
3588 adev->device.get_mic_mute = adev_get_mic_mute;
3589 adev->device.set_parameters = adev_set_parameters;
3590 adev->device.get_parameters = adev_get_parameters;
3591 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3592 adev->device.open_output_stream = adev_open_output_stream;
3593 adev->device.close_output_stream = adev_close_output_stream;
3594 adev->device.open_input_stream = adev_open_input_stream;
3595 adev->device.close_input_stream = adev_close_input_stream;
3596 adev->device.dump = adev_dump;
3597
3598 /* Set the default route before the PCM stream is opened */
3599 pthread_mutex_lock(&adev->lock);
3600 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003601 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003602 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003603 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003604 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003605 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003606 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003607 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003608 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003609 pthread_mutex_unlock(&adev->lock);
3610
3611 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003612 adev->platform = platform_init(adev);
3613 if (!adev->platform) {
3614 free(adev->snd_dev_ref_cnt);
3615 free(adev);
3616 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3617 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003618 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003619 return -EINVAL;
3620 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05003621 adev->extspk = audio_extn_extspk_init(adev);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003622 audio_extn_sound_trigger_init(adev);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003623
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003624 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3625 if (adev->visualizer_lib == NULL) {
3626 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3627 } else {
3628 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3629 adev->visualizer_start_output =
3630 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
3631 "visualizer_hal_start_output");
3632 adev->visualizer_stop_output =
3633 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
3634 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07003635 }
3636
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003637 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3638 if (adev->offload_effects_lib == NULL) {
3639 ALOGW("%s: DLOPEN failed for %s", __func__,
3640 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3641 } else {
3642 ALOGV("%s: DLOPEN successful for %s", __func__,
3643 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3644 adev->offload_effects_start_output =
3645 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3646 "offload_effects_bundle_hal_start_output");
3647 adev->offload_effects_stop_output =
3648 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3649 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07003650 }
3651
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003652 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
3653 if (adev->adm_lib == NULL) {
3654 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
3655 } else {
3656 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
3657 adev->adm_init = (adm_init_t)
3658 dlsym(adev->adm_lib, "adm_init");
3659 adev->adm_deinit = (adm_deinit_t)
3660 dlsym(adev->adm_lib, "adm_deinit");
3661 adev->adm_register_input_stream = (adm_register_input_stream_t)
3662 dlsym(adev->adm_lib, "adm_register_input_stream");
3663 adev->adm_register_output_stream = (adm_register_output_stream_t)
3664 dlsym(adev->adm_lib, "adm_register_output_stream");
3665 adev->adm_deregister_stream = (adm_deregister_stream_t)
3666 dlsym(adev->adm_lib, "adm_deregister_stream");
3667 adev->adm_request_focus = (adm_request_focus_t)
3668 dlsym(adev->adm_lib, "adm_request_focus");
3669 adev->adm_abandon_focus = (adm_abandon_focus_t)
3670 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08003671 adev->adm_set_config = (adm_set_config_t)
3672 dlsym(adev->adm_lib, "adm_set_config");
3673 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
3674 dlsym(adev->adm_lib, "adm_request_focus_v2");
3675 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
3676 dlsym(adev->adm_lib, "adm_is_noirq_avail");
3677 adev->adm_on_routing_change = (adm_on_routing_change_t)
3678 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003679 }
3680
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003681 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003682 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003683
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003684 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003685
Andy Hung31aca912014-03-20 17:14:59 -07003686 if (k_enable_extended_precision)
3687 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003688
Glenn Kasten4f993392014-05-14 07:30:48 -07003689 char value[PROPERTY_VALUE_MAX];
3690 int trial;
3691 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3692 trial = atoi(value);
3693 if (period_size_is_plausible_for_low_latency(trial)) {
3694 pcm_config_low_latency.period_size = trial;
3695 pcm_config_low_latency.start_threshold = trial / 4;
3696 pcm_config_low_latency.avail_min = trial / 4;
3697 configured_low_latency_capture_period_size = trial;
3698 }
3699 }
3700 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3701 trial = atoi(value);
3702 if (period_size_is_plausible_for_low_latency(trial)) {
3703 configured_low_latency_capture_period_size = trial;
3704 }
3705 }
3706
vivek mehta1a9b7c02015-06-25 11:49:38 -07003707 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003708
3709 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
3710 af_period_multiplier = atoi(value);
3711 if (af_period_multiplier < 0) {
3712 af_period_multiplier = 2;
3713 } else if (af_period_multiplier > 4) {
3714 af_period_multiplier = 4;
3715 }
3716 ALOGV("new period_multiplier = %d", af_period_multiplier);
3717 }
3718
vivek mehta1a9b7c02015-06-25 11:49:38 -07003719 pthread_mutex_unlock(&adev_init_lock);
3720
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003721 if (adev->adm_init)
3722 adev->adm_data = adev->adm_init();
3723
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07003724 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003725 audio_extn_snd_mon_init();
3726 pthread_mutex_lock(&adev->lock);
3727 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
3728 adev->card_status = CARD_STATUS_ONLINE;
3729 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07003730
Eric Laurent2bafff12016-03-17 12:17:23 -07003731 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003732 return 0;
3733}
3734
3735static struct hw_module_methods_t hal_module_methods = {
3736 .open = adev_open,
3737};
3738
3739struct audio_module HAL_MODULE_INFO_SYM = {
3740 .common = {
3741 .tag = HARDWARE_MODULE_TAG,
3742 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3743 .hal_api_version = HARDWARE_HAL_API_VERSION,
3744 .id = AUDIO_HARDWARE_MODULE_ID,
3745 .name = "QCOM Audio HAL",
3746 .author = "Code Aurora Forum",
3747 .methods = &hal_module_methods,
3748 },
3749};