blob: 0277ec48ff6bbaa3e397dab70a9e9fb2fa7e0f6d [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>
Phil Burkbc991042017-02-24 08:06:44 -080047#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070048#include <audio_effects/effect_aec.h>
49#include <audio_effects/effect_ns.h>
Andy Hungfc044e12017-03-20 09:24:22 -070050#include <audio_utils/clock.h>
51#include <audio_utils/power.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052#include "audio_hw.h"
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -080053#include "audio_extn.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070054#include "platform_api.h"
55#include <platform.h>
Vineeta Srivastava4b89e372014-06-19 14:21:42 -070056#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070058#include "sound/compress_params.h"
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -080059#include "audio_extn/tfa_98xx.h"
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070060
Eric Laurent397db572016-05-11 11:31:47 -070061/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
62 * COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
Marco Nelissen32093f52015-04-08 15:14:02 -070063#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070064// 2 buffers causes problems with high bitrate files
65#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066/* ToDo: Check and update a proper value in msec */
67#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
68#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
69
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070070#define PROXY_OPEN_RETRY_COUNT 100
71#define PROXY_OPEN_WAIT_TIME 20
72
vivek mehtadae44712015-07-27 14:13:18 -070073#define MIN_CHANNEL_COUNT 1
74#define DEFAULT_CHANNEL_COUNT 2
75
Jean-Michel Trivic0750692015-10-12 12:12:32 -070076#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
77#define MAX_CHANNEL_COUNT 1
78#else
vivek mehtadae44712015-07-27 14:13:18 -070079#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
80#define XSTR(x) STR(x)
81#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070082#endif
vivek mehtadae44712015-07-27 14:13:18 -070083
Haynes Mathew George03c40102016-01-29 17:57:48 -080084#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
85
Glenn Kasten4f993392014-05-14 07:30:48 -070086static unsigned int configured_low_latency_capture_period_size =
87 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
88
Eric Laurent0e46adf2016-12-16 12:49:24 -080089
90#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Phil Burkbc991042017-02-24 08:06:44 -080091#define MMAP_PERIOD_COUNT_MIN 32
92#define MMAP_PERIOD_COUNT_MAX 512
93#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
Eric Laurent0e46adf2016-12-16 12:49:24 -080094
95
Andy Hung31aca912014-03-20 17:14:59 -070096/* This constant enables extended precision handling.
97 * TODO The flag is off until more testing is done.
98 */
99static const bool k_enable_extended_precision = false;
100
Eric Laurentb23d5282013-05-14 15:27:20 -0700101struct pcm_config pcm_config_deep_buffer = {
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 = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
105 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
106 .format = PCM_FORMAT_S16_LE,
107 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
108 .stop_threshold = INT_MAX,
109 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
110};
111
112struct pcm_config pcm_config_low_latency = {
vivek mehtadae44712015-07-27 14:13:18 -0700113 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700114 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
115 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
116 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
117 .format = PCM_FORMAT_S16_LE,
118 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
119 .stop_threshold = INT_MAX,
120 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
121};
122
Haynes Mathew George03c40102016-01-29 17:57:48 -0800123static int af_period_multiplier = 4;
124struct pcm_config pcm_config_rt = {
125 .channels = DEFAULT_CHANNEL_COUNT,
126 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
127 .period_size = ULL_PERIOD_SIZE, //1 ms
128 .period_count = 512, //=> buffer size is 512ms
129 .format = PCM_FORMAT_S16_LE,
130 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
131 .stop_threshold = INT_MAX,
132 .silence_threshold = 0,
133 .silence_size = 0,
134 .avail_min = ULL_PERIOD_SIZE, //1 ms
135};
136
Eric Laurentb23d5282013-05-14 15:27:20 -0700137struct pcm_config pcm_config_hdmi_multi = {
138 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
139 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
140 .period_size = HDMI_MULTI_PERIOD_SIZE,
141 .period_count = HDMI_MULTI_PERIOD_COUNT,
142 .format = PCM_FORMAT_S16_LE,
143 .start_threshold = 0,
144 .stop_threshold = INT_MAX,
145 .avail_min = 0,
146};
147
Eric Laurent0e46adf2016-12-16 12:49:24 -0800148struct pcm_config pcm_config_mmap_playback = {
149 .channels = DEFAULT_CHANNEL_COUNT,
150 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
151 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800152 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800153 .format = PCM_FORMAT_S16_LE,
154 .start_threshold = MMAP_PERIOD_SIZE*8,
155 .stop_threshold = INT32_MAX,
156 .silence_threshold = 0,
157 .silence_size = 0,
158 .avail_min = MMAP_PERIOD_SIZE, //1 ms
159};
160
Eric Laurentb23d5282013-05-14 15:27:20 -0700161struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700162 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700163 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
164 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700165 .stop_threshold = INT_MAX,
166 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700167};
168
Haynes Mathew George03c40102016-01-29 17:57:48 -0800169struct pcm_config pcm_config_audio_capture_rt = {
170 .channels = DEFAULT_CHANNEL_COUNT,
171 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
172 .period_size = ULL_PERIOD_SIZE,
173 .period_count = 512,
174 .format = PCM_FORMAT_S16_LE,
175 .start_threshold = 0,
176 .stop_threshold = INT_MAX,
177 .silence_threshold = 0,
178 .silence_size = 0,
179 .avail_min = ULL_PERIOD_SIZE, //1 ms
180};
181
Eric Laurent0e46adf2016-12-16 12:49:24 -0800182struct pcm_config pcm_config_mmap_capture = {
183 .channels = DEFAULT_CHANNEL_COUNT,
184 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
185 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800186 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800187 .format = PCM_FORMAT_S16_LE,
188 .start_threshold = 0,
189 .stop_threshold = INT_MAX,
190 .silence_threshold = 0,
191 .silence_size = 0,
192 .avail_min = MMAP_PERIOD_SIZE, //1 ms
193};
194
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700195#define AFE_PROXY_CHANNEL_COUNT 2
196#define AFE_PROXY_SAMPLING_RATE 48000
197
198#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
199#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
200
201struct pcm_config pcm_config_afe_proxy_playback = {
202 .channels = AFE_PROXY_CHANNEL_COUNT,
203 .rate = AFE_PROXY_SAMPLING_RATE,
204 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
205 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
206 .format = PCM_FORMAT_S16_LE,
207 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
208 .stop_threshold = INT_MAX,
209 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
210};
211
212#define AFE_PROXY_RECORD_PERIOD_SIZE 768
213#define AFE_PROXY_RECORD_PERIOD_COUNT 4
214
215struct pcm_config pcm_config_afe_proxy_record = {
216 .channels = AFE_PROXY_CHANNEL_COUNT,
217 .rate = AFE_PROXY_SAMPLING_RATE,
218 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
219 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
220 .format = PCM_FORMAT_S16_LE,
221 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
222 .stop_threshold = INT_MAX,
223 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
224};
225
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700226const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700227 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
228 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
229 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700230 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700231 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700232 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800233 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700234
Eric Laurentb23d5282013-05-14 15:27:20 -0700235 [USECASE_AUDIO_RECORD] = "audio-record",
236 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800237 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700238
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800239 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
240 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700241
Eric Laurentb23d5282013-05-14 15:27:20 -0700242 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700243 [USECASE_VOICE2_CALL] = "voice2-call",
244 [USECASE_VOLTE_CALL] = "volte-call",
245 [USECASE_QCHAT_CALL] = "qchat-call",
246 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800247 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
248 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700249
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700250 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
251 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
252
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700253 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
254 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700255};
256
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800257
258#define STRING_TO_ENUM(string) { #string, string }
259
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800260struct string_to_enum {
261 const char *name;
262 uint32_t value;
263};
264
265static const struct string_to_enum out_channels_name_to_enum_table[] = {
266 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
267 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
268 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
269};
270
Haynes Mathew George5191a852013-09-11 14:19:36 -0700271static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700272static struct audio_device *adev = NULL;
273static pthread_mutex_t adev_init_lock;
274static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700275//cache last MBDRC cal step level
276static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700277
Haynes Mathew George03c40102016-01-29 17:57:48 -0800278static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
279 int flags __unused)
280{
281 int dir = 0;
282 switch (uc_id) {
283 case USECASE_AUDIO_RECORD_LOW_LATENCY:
284 dir = 1;
285 case USECASE_AUDIO_PLAYBACK_ULL:
286 break;
287 default:
288 return false;
289 }
290
291 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
292 PCM_PLAYBACK : PCM_CAPTURE);
293 if (adev->adm_is_noirq_avail)
294 return adev->adm_is_noirq_avail(adev->adm_data,
295 adev->snd_card, dev_id, dir);
296 return false;
297}
298
299static void register_out_stream(struct stream_out *out)
300{
301 struct audio_device *adev = out->dev;
302 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
303 return;
304
305 if (!adev->adm_register_output_stream)
306 return;
307
308 adev->adm_register_output_stream(adev->adm_data,
309 out->handle,
310 out->flags);
311
312 if (!adev->adm_set_config)
313 return;
314
315 if (out->realtime) {
316 adev->adm_set_config(adev->adm_data,
317 out->handle,
318 out->pcm, &out->config);
319 }
320}
321
322static void register_in_stream(struct stream_in *in)
323{
324 struct audio_device *adev = in->dev;
325 if (!adev->adm_register_input_stream)
326 return;
327
328 adev->adm_register_input_stream(adev->adm_data,
329 in->capture_handle,
330 in->flags);
331
332 if (!adev->adm_set_config)
333 return;
334
335 if (in->realtime) {
336 adev->adm_set_config(adev->adm_data,
337 in->capture_handle,
338 in->pcm,
339 &in->config);
340 }
341}
342
343static void request_out_focus(struct stream_out *out, long ns)
344{
345 struct audio_device *adev = out->dev;
346
347 if (out->routing_change) {
348 out->routing_change = false;
349 if (adev->adm_on_routing_change)
350 adev->adm_on_routing_change(adev->adm_data, out->handle);
351 }
352
353 if (adev->adm_request_focus_v2) {
354 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
355 } else if (adev->adm_request_focus) {
356 adev->adm_request_focus(adev->adm_data, out->handle);
357 }
358}
359
360static void request_in_focus(struct stream_in *in, long ns)
361{
362 struct audio_device *adev = in->dev;
363
364 if (in->routing_change) {
365 in->routing_change = false;
366 if (adev->adm_on_routing_change)
367 adev->adm_on_routing_change(adev->adm_data, in->capture_handle);
368 }
369
370 if (adev->adm_request_focus_v2) {
371 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
372 } else if (adev->adm_request_focus) {
373 adev->adm_request_focus(adev->adm_data, in->capture_handle);
374 }
375}
376
377static void release_out_focus(struct stream_out *out, long ns __unused)
378{
379 struct audio_device *adev = out->dev;
380
381 if (adev->adm_abandon_focus)
382 adev->adm_abandon_focus(adev->adm_data, out->handle);
383}
384
385static void release_in_focus(struct stream_in *in, long ns __unused)
386{
387 struct audio_device *adev = in->dev;
388 if (adev->adm_abandon_focus)
389 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
390}
391
Andy Hung7401c7c2016-09-21 12:41:21 -0700392// Log errors: consecutive errors with the same code will
393// be aggregated if they occur within one second.
394// A mutual exclusion lock must be held before calling.
395static void log_error_l(struct error_log *log, int code) {
396 ++log->errors;
397
Andy Hungfc044e12017-03-20 09:24:22 -0700398 const int64_t now = audio_utils_get_real_time_ns();
Andy Hung7401c7c2016-09-21 12:41:21 -0700399
400 // Within 1 second, cluster the same error codes together.
401 const int one_second = 1000000000;
402 if (code == log->entries[log->idx].code &&
403 now - log->entries[log->idx].last_time < one_second) {
404 log->entries[log->idx].count++;
405 log->entries[log->idx].last_time = now;
406 return;
407 }
408
409 // Add new error entry.
410 if (++log->idx >= ARRAY_SIZE(log->entries)) {
411 log->idx = 0;
412 }
413 log->entries[log->idx].count = 1;
414 log->entries[log->idx].code = code;
415 log->entries[log->idx].first_time = now;
416 log->entries[log->idx].last_time = now;
417}
418
419// Dump information in the error log. A mutual exclusion lock
420// should be held, but if that cannot be obtained, one should
421// make a copy of the error log before calling -- the call is
422// still safe, but there might be some misinterpreted data.
423static void log_dump_l(const struct error_log *log, int fd)
424{
425 dprintf(fd, " Errors: %u\n", log->errors);
426 if (log->errors == 0)
427 return;
428
429 dprintf(fd, " Index Code Freq First time Last time\n");
430 for (size_t i = 0; i < ARRAY_SIZE(log->entries); ++i) {
431 if (log->entries[i].count != 0) {
432 char first_time[32];
433 char last_time[32];
Andy Hungfc044e12017-03-20 09:24:22 -0700434 audio_utils_ns_to_string(log->entries[i].first_time, first_time, sizeof(first_time));
435 audio_utils_ns_to_string(log->entries[i].last_time, last_time, sizeof(last_time));
Andy Hung7401c7c2016-09-21 12:41:21 -0700436 dprintf(fd, " %c%4zu %4d %5d %s %s\n",
437 i == log->idx ? '*' : ' ', // mark head position
438 i, log->entries[i].code, log->entries[i].count,
439 first_time, last_time);
440 }
441 }
442}
443
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700444static int parse_snd_card_status(struct str_parms * parms, int * card,
445 card_status_t * status)
446{
447 char value[32]={0};
448 char state[32]={0};
449
450 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
451
452 if (ret < 0)
453 return -1;
454
455 // sscanf should be okay as value is of max length 32.
456 // same as sizeof state.
457 if (sscanf(value, "%d,%s", card, state) < 2)
458 return -1;
459
460 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
461 CARD_STATUS_OFFLINE;
462 return 0;
463}
464
vivek mehta1a9b7c02015-06-25 11:49:38 -0700465__attribute__ ((visibility ("default")))
466bool audio_hw_send_gain_dep_calibration(int level) {
467 bool ret_val = false;
468 ALOGV("%s: enter ... ", __func__);
469
470 pthread_mutex_lock(&adev_init_lock);
471
472 if (adev != NULL && adev->platform != NULL) {
473 pthread_mutex_lock(&adev->lock);
474 ret_val = platform_send_gain_dep_cal(adev->platform, level);
475 pthread_mutex_unlock(&adev->lock);
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700476
477 // if cal set fails, cache level info
478 // if cal set succeds, reset known last cal set
479 if (!ret_val)
480 last_known_cal_step = level;
481 else if (last_known_cal_step != -1)
482 last_known_cal_step = -1;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700483 } else {
484 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
485 }
486
487 pthread_mutex_unlock(&adev_init_lock);
488
489 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
490 return ret_val;
491}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700492
vivek mehtaa8d7c922016-05-25 14:40:44 -0700493__attribute__ ((visibility ("default")))
494int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
495 int table_size) {
496 int ret_val = 0;
497 ALOGV("%s: enter ... ", __func__);
498
499 pthread_mutex_lock(&adev_init_lock);
500 if (adev == NULL) {
501 ALOGW("%s: adev is NULL .... ", __func__);
502 goto done;
503 }
504
505 pthread_mutex_lock(&adev->lock);
506 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
507 pthread_mutex_unlock(&adev->lock);
508done:
509 pthread_mutex_unlock(&adev_init_lock);
510 ALOGV("%s: exit ... ", __func__);
511 return ret_val;
512}
513
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700514static bool is_supported_format(audio_format_t format)
515{
Eric Laurent8251ac82014-07-23 11:00:25 -0700516 switch (format) {
517 case AUDIO_FORMAT_MP3:
518 case AUDIO_FORMAT_AAC_LC:
519 case AUDIO_FORMAT_AAC_HE_V1:
520 case AUDIO_FORMAT_AAC_HE_V2:
521 return true;
522 default:
523 break;
524 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700525 return false;
526}
527
Haynes Mathew George03c40102016-01-29 17:57:48 -0800528static inline bool is_mmap_usecase(audio_usecase_t uc_id)
529{
530 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
531 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
532}
533
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700534static int get_snd_codec_id(audio_format_t format)
535{
536 int id = 0;
537
Eric Laurent8251ac82014-07-23 11:00:25 -0700538 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700539 case AUDIO_FORMAT_MP3:
540 id = SND_AUDIOCODEC_MP3;
541 break;
542 case AUDIO_FORMAT_AAC:
543 id = SND_AUDIOCODEC_AAC;
544 break;
545 default:
546 ALOGE("%s: Unsupported audio format", __func__);
547 }
548
549 return id;
550}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800551
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800552static int audio_ssr_status(struct audio_device *adev)
553{
554 int ret = 0;
555 struct mixer_ctl *ctl;
556 const char *mixer_ctl_name = "Audio SSR Status";
557
558 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
559 ret = mixer_ctl_get_value(ctl, 0);
560 ALOGD("%s: value: %d", __func__, ret);
561 return ret;
562}
563
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800564int enable_audio_route(struct audio_device *adev,
565 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800566{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700567 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800568 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800569
570 if (usecase == NULL)
571 return -EINVAL;
572
573 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
574
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800575 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700576 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800577 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700578 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800579
Yamit Mehtae3b99562016-09-16 22:44:00 +0530580 audio_extn_utils_send_app_type_cfg(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800581 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500582 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700583 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700584 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800585
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800586 ALOGV("%s: exit", __func__);
587 return 0;
588}
589
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800590int disable_audio_route(struct audio_device *adev,
591 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800592{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700593 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800594 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800595
596 if (usecase == NULL)
597 return -EINVAL;
598
599 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700600 if (usecase->type == PCM_CAPTURE)
601 snd_device = usecase->in_snd_device;
602 else
603 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800604 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500605 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700606 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700607 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800608
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800609 ALOGV("%s: exit", __func__);
610 return 0;
611}
612
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800613int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700614 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800615{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700616 int i, num_devices = 0;
617 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800618 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800619 if (snd_device < SND_DEVICE_MIN ||
620 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800621 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800622 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800623 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700624
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700625 platform_send_audio_calibration(adev->platform, snd_device);
626
vivek mehtade4849c2016-03-03 17:23:38 -0800627 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700628 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700629 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800630 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700631 }
632
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700633 /* due to the possibility of calibration overwrite between listen
634 and audio, notify sound trigger hal before audio calibration is sent */
635 audio_extn_sound_trigger_update_device_status(snd_device,
636 ST_EVENT_SND_DEVICE_BUSY);
637
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700638 if (audio_extn_spkr_prot_is_enabled())
639 audio_extn_spkr_prot_calib_cancel(adev);
640
zhaoyang yin4211fad2015-06-04 21:13:25 +0800641 audio_extn_dsm_feedback_enable(adev, snd_device, true);
642
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700643 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
644 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
645 audio_extn_spkr_prot_is_enabled()) {
646 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800647 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700648 }
649 if (audio_extn_spkr_prot_start_processing(snd_device)) {
650 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800651 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700652 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700653 } else if (platform_can_split_snd_device(snd_device,
654 &num_devices,
655 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700656 for (i = 0; i < num_devices; i++) {
657 enable_snd_device(adev, new_snd_devices[i]);
658 }
vivek mehtab6506412015-08-07 16:55:17 -0700659 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700660 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800661 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
662 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
663 ALOGE(" %s: Invalid sound device returned", __func__);
664 goto on_error;
665 }
Ed Tam70b5c142016-03-21 19:14:29 -0700666
Eric Laurent2e140aa2016-06-30 17:14:46 -0700667 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800668 audio_route_apply_and_update_path(adev->audio_route, device_name);
669 }
670on_success:
671 adev->snd_dev_ref_cnt[snd_device]++;
672 ret_val = 0;
673on_error:
674 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800675}
676
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800677int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700678 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800679{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700680 int i, num_devices = 0;
681 snd_device_t new_snd_devices[2];
682
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800683 if (snd_device < SND_DEVICE_MIN ||
684 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800685 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800686 return -EINVAL;
687 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700688 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
689 ALOGE("%s: device ref cnt is already 0", __func__);
690 return -EINVAL;
691 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800692 audio_extn_tfa_98xx_disable_speaker(snd_device);
693
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700694 adev->snd_dev_ref_cnt[snd_device]--;
695 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800696 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700697 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
698 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
699 audio_extn_spkr_prot_is_enabled()) {
700 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700701 } else if (platform_can_split_snd_device(snd_device,
702 &num_devices,
703 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700704 for (i = 0; i < num_devices; i++) {
705 disable_snd_device(adev, new_snd_devices[i]);
706 }
vivek mehtab6506412015-08-07 16:55:17 -0700707 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700708 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800709 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
710 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
711 ALOGE(" %s: Invalid sound device returned", __func__);
712 return -EINVAL;
713 }
714
Eric Laurent2e140aa2016-06-30 17:14:46 -0700715 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800716 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700717 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700718 audio_extn_sound_trigger_update_device_status(snd_device,
719 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700720 }
vivek mehtab6506412015-08-07 16:55:17 -0700721
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800722 return 0;
723}
724
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700725/*
726 legend:
727 uc - existing usecase
728 new_uc - new usecase
729 d1, d11, d2 - SND_DEVICE enums
730 a1, a2 - corresponding ANDROID device enums
731 B, B1, B2 - backend strings
732
733case 1
734 uc->dev d1 (a1) B1
735 new_uc->dev d1 (a1), d2 (a2) B1, B2
736
737 resolution: disable and enable uc->dev on d1
738
739case 2
740 uc->dev d1 (a1) B1
741 new_uc->dev d11 (a1) B1
742
743 resolution: need to switch uc since d1 and d11 are related
744 (e.g. speaker and voice-speaker)
745 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
746
747case 3
748 uc->dev d1 (a1) B1
749 new_uc->dev d2 (a2) B2
750
751 resolution: no need to switch uc
752
753case 4
754 uc->dev d1 (a1) B
755 new_uc->dev d2 (a2) B
756
757 resolution: disable enable uc-dev on d2 since backends match
758 we cannot enable two streams on two different devices if they
759 share the same backend. e.g. if offload is on speaker device using
760 QUAD_MI2S backend and a low-latency stream is started on voice-handset
761 using the same backend, offload must also be switched to voice-handset.
762
763case 5
764 uc->dev d1 (a1) B
765 new_uc->dev d1 (a1), d2 (a2) B
766
767 resolution: disable enable uc-dev on d2 since backends match
768 we cannot enable two streams on two different devices if they
769 share the same backend.
770
771case 6
772 uc->dev d1 a1 B1
773 new_uc->dev d2 a1 B2
774
775 resolution: no need to switch
776
777case 7
778
779 uc->dev d1 (a1), d2 (a2) B1, B2
780 new_uc->dev d1 B1
781
782 resolution: no need to switch
783
784*/
785static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
786 struct audio_usecase *new_uc,
787 snd_device_t new_snd_device)
788{
789 audio_devices_t a1 = uc->stream.out->devices;
790 audio_devices_t a2 = new_uc->stream.out->devices;
791
792 snd_device_t d1 = uc->out_snd_device;
793 snd_device_t d2 = new_snd_device;
794
795 // Treat as a special case when a1 and a2 are not disjoint
796 if ((a1 != a2) && (a1 & a2)) {
797 snd_device_t d3[2];
798 int num_devices = 0;
799 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
800 &num_devices,
801 d3);
802 if (ret < 0) {
803 if (ret != -ENOSYS) {
804 ALOGW("%s failed to split snd_device %d",
805 __func__,
806 popcount(a1) > 1 ? d1 : d2);
807 }
808 goto end;
809 }
810
811 // NB: case 7 is hypothetical and isn't a practical usecase yet.
812 // But if it does happen, we need to give priority to d2 if
813 // the combo devices active on the existing usecase share a backend.
814 // This is because we cannot have a usecase active on a combo device
815 // and a new usecase requests one device in this combo pair.
816 if (platform_check_backends_match(d3[0], d3[1])) {
817 return d2; // case 5
818 } else {
819 return d1; // case 1
820 }
821 } else {
822 if (platform_check_backends_match(d1, d2)) {
823 return d2; // case 2, 4
824 } else {
825 return d1; // case 6, 3
826 }
827 }
828
829end:
830 return d2; // return whatever was calculated before.
831}
832
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700833static void check_and_route_playback_usecases(struct audio_device *adev,
834 struct audio_usecase *uc_info,
835 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700836{
837 struct listnode *node;
838 struct audio_usecase *usecase;
839 bool switch_device[AUDIO_USECASE_MAX];
840 int i, num_uc_to_switch = 0;
841
David Linee3fe402017-03-13 10:00:42 -0700842 platform_check_and_set_playback_backend_cfg(adev, uc_info, snd_device);
843
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700844 /*
845 * This function is to make sure that all the usecases that are active on
846 * the hardware codec backend are always routed to any one device that is
847 * handled by the hardware codec.
848 * For example, if low-latency and deep-buffer usecases are currently active
849 * on speaker and out_set_parameters(headset) is received on low-latency
850 * output, then we have to make sure deep-buffer is also switched to headset,
851 * because of the limitation that both the devices cannot be enabled
852 * at the same time as they share the same backend.
853 */
854 /* Disable all the usecases on the shared backend other than the
855 specified usecase */
856 for (i = 0; i < AUDIO_USECASE_MAX; i++)
857 switch_device[i] = false;
858
859 list_for_each(node, &adev->usecase_list) {
860 usecase = node_to_item(node, struct audio_usecase, list);
861 if (usecase->type != PCM_CAPTURE &&
862 usecase != uc_info &&
863 usecase->out_snd_device != snd_device &&
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700864 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
865 platform_check_backends_match(snd_device, usecase->out_snd_device)) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700866 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
867 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700868 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700869 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700870 switch_device[usecase->id] = true;
871 num_uc_to_switch++;
872 }
873 }
874
875 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700876 list_for_each(node, &adev->usecase_list) {
877 usecase = node_to_item(node, struct audio_usecase, list);
878 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700879 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900880 }
881 }
882
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700883 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900884 list_for_each(node, &adev->usecase_list) {
885 usecase = node_to_item(node, struct audio_usecase, list);
886 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700887 d_device = derive_playback_snd_device(usecase, uc_info,
888 snd_device);
889 enable_snd_device(adev, d_device);
890 /* Update the out_snd_device before enabling the audio route */
891 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700892 }
893 }
894
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700895 /* Re-route all the usecases on the shared backend other than the
896 specified usecase to new snd devices */
897 list_for_each(node, &adev->usecase_list) {
898 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700899 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700900 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700901 }
902 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700903 }
904}
905
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700906static void check_and_route_capture_usecases(struct audio_device *adev,
907 struct audio_usecase *uc_info,
908 snd_device_t snd_device)
909{
910 struct listnode *node;
911 struct audio_usecase *usecase;
912 bool switch_device[AUDIO_USECASE_MAX];
913 int i, num_uc_to_switch = 0;
914
vivek mehta4ed66e62016-04-15 23:33:34 -0700915 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
916
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700917 /*
918 * This function is to make sure that all the active capture usecases
919 * are always routed to the same input sound device.
920 * For example, if audio-record and voice-call usecases are currently
921 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
922 * is received for voice call then we have to make sure that audio-record
923 * usecase is also switched to earpiece i.e. voice-dmic-ef,
924 * because of the limitation that two devices cannot be enabled
925 * at the same time if they share the same backend.
926 */
927 for (i = 0; i < AUDIO_USECASE_MAX; i++)
928 switch_device[i] = false;
929
930 list_for_each(node, &adev->usecase_list) {
931 usecase = node_to_item(node, struct audio_usecase, list);
932 if (usecase->type != PCM_PLAYBACK &&
933 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700934 usecase->in_snd_device != snd_device &&
935 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700936 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
937 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700938 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700939 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700940 switch_device[usecase->id] = true;
941 num_uc_to_switch++;
942 }
943 }
944
945 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700946 list_for_each(node, &adev->usecase_list) {
947 usecase = node_to_item(node, struct audio_usecase, list);
948 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700949 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700950 }
951 }
952
953 list_for_each(node, &adev->usecase_list) {
954 usecase = node_to_item(node, struct audio_usecase, list);
955 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700956 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700957 }
958 }
959
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700960 /* Re-route all the usecases on the shared backend other than the
961 specified usecase to new snd devices */
962 list_for_each(node, &adev->usecase_list) {
963 usecase = node_to_item(node, struct audio_usecase, list);
964 /* Update the in_snd_device only before enabling the audio route */
965 if (switch_device[usecase->id] ) {
966 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700967 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700968 }
969 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700970 }
971}
972
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800973/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700974static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800975{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700976 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700977 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800978
979 switch (channels) {
980 /*
981 * Do not handle stereo output in Multi-channel cases
982 * Stereo case is handled in normal playback path
983 */
984 case 6:
985 ALOGV("%s: HDMI supports 5.1", __func__);
986 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
987 break;
988 case 8:
989 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
990 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
991 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
992 break;
993 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700994 ALOGE("HDMI does not support multi channel playback");
995 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800996 break;
997 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700998 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800999}
1000
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001001static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1002{
1003 struct audio_usecase *usecase;
1004 struct listnode *node;
1005
1006 list_for_each(node, &adev->usecase_list) {
1007 usecase = node_to_item(node, struct audio_usecase, list);
1008 if (usecase->type == VOICE_CALL) {
1009 ALOGV("%s: usecase id %d", __func__, usecase->id);
1010 return usecase->id;
1011 }
1012 }
1013 return USECASE_INVALID;
1014}
1015
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001016struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1017 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001018{
1019 struct audio_usecase *usecase;
1020 struct listnode *node;
1021
1022 list_for_each(node, &adev->usecase_list) {
1023 usecase = node_to_item(node, struct audio_usecase, list);
1024 if (usecase->id == uc_id)
1025 return usecase;
1026 }
1027 return NULL;
1028}
1029
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001030int select_devices(struct audio_device *adev,
1031 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001032{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001033 snd_device_t out_snd_device = SND_DEVICE_NONE;
1034 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001035 struct audio_usecase *usecase = NULL;
1036 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001037 struct audio_usecase *hfp_usecase = NULL;
1038 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001039 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001040 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001041
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001042 usecase = get_usecase_from_list(adev, uc_id);
1043 if (usecase == NULL) {
1044 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1045 return -EINVAL;
1046 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001047
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001048 if ((usecase->type == VOICE_CALL) ||
1049 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001050 out_snd_device = platform_get_output_snd_device(adev->platform,
1051 usecase->stream.out->devices);
1052 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001053 usecase->devices = usecase->stream.out->devices;
1054 } else {
1055 /*
1056 * If the voice call is active, use the sound devices of voice call usecase
1057 * so that it would not result any device switch. All the usecases will
1058 * be switched to new device when select_devices() is called for voice call
1059 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001060 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001061 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001062 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001063 vc_usecase = get_usecase_from_list(adev,
1064 get_voice_usecase_id_from_list(adev));
1065 if ((vc_usecase != NULL) &&
1066 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1067 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001068 in_snd_device = vc_usecase->in_snd_device;
1069 out_snd_device = vc_usecase->out_snd_device;
1070 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001071 } else if (audio_extn_hfp_is_active(adev)) {
1072 hfp_ucid = audio_extn_hfp_get_usecase();
1073 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1074 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1075 in_snd_device = hfp_usecase->in_snd_device;
1076 out_snd_device = hfp_usecase->out_snd_device;
1077 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001078 }
1079 if (usecase->type == PCM_PLAYBACK) {
1080 usecase->devices = usecase->stream.out->devices;
1081 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001082 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001083 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001084 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001085 if (usecase->stream.out == adev->primary_output &&
1086 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001087 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1088 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001089 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001090 select_devices(adev, adev->active_input->usecase);
1091 }
1092 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001093 } else if (usecase->type == PCM_CAPTURE) {
1094 usecase->devices = usecase->stream.in->device;
1095 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001096 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001097 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001098 if (adev->active_input &&
1099 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1100 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001101 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001102 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1103 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
1104 } else if (adev->primary_output) {
1105 out_device = adev->primary_output->devices;
1106 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001107 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001108 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001109 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001110 }
1111 }
1112
1113 if (out_snd_device == usecase->out_snd_device &&
1114 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001115 return 0;
1116 }
1117
Eric Laurent2bafff12016-03-17 12:17:23 -07001118 if (out_snd_device != SND_DEVICE_NONE &&
1119 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1120 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1121 __func__,
1122 use_case_table[uc_id],
1123 adev->last_logged_snd_device[uc_id][0],
1124 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1125 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1126 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1127 -1,
1128 out_snd_device,
1129 platform_get_snd_device_name(out_snd_device),
1130 platform_get_snd_device_acdb_id(out_snd_device));
1131 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1132 }
1133 if (in_snd_device != SND_DEVICE_NONE &&
1134 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1135 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1136 __func__,
1137 use_case_table[uc_id],
1138 adev->last_logged_snd_device[uc_id][1],
1139 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1140 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1141 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1142 -1,
1143 in_snd_device,
1144 platform_get_snd_device_name(in_snd_device),
1145 platform_get_snd_device_acdb_id(in_snd_device));
1146 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1147 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001148
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001149 /*
1150 * Limitation: While in call, to do a device switch we need to disable
1151 * and enable both RX and TX devices though one of them is same as current
1152 * device.
1153 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001154 if ((usecase->type == VOICE_CALL) &&
1155 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1156 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001157 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001158 /* Disable sidetone only if voice call already exists */
1159 if (voice_is_call_state_active(adev))
1160 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001161 }
1162
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001163 /* Disable current sound devices */
1164 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001165 disable_audio_route(adev, usecase);
1166 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001167 }
1168
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001169 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001170 disable_audio_route(adev, usecase);
1171 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001172 }
1173
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001174 /* Applicable only on the targets that has external modem.
1175 * New device information should be sent to modem before enabling
1176 * the devices to reduce in-call device switch time.
1177 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001178 if ((usecase->type == VOICE_CALL) &&
1179 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1180 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001181 status = platform_switch_voice_call_enable_device_config(adev->platform,
1182 out_snd_device,
1183 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001184 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001185
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001186 /* Enable new sound devices */
1187 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001188 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1189 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001190 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001191 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001192 }
1193
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001194 if (in_snd_device != SND_DEVICE_NONE) {
1195 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001196 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001197 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001198
Eric Laurentb23d5282013-05-14 15:27:20 -07001199 if (usecase->type == VOICE_CALL)
1200 status = platform_switch_voice_call_device_post(adev->platform,
1201 out_snd_device,
1202 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001203
sangwoo170731f2013-06-08 15:36:36 +09001204 usecase->in_snd_device = in_snd_device;
1205 usecase->out_snd_device = out_snd_device;
1206
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001207 audio_extn_tfa_98xx_set_mode();
1208
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001209 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001210
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001211 /* Applicable only on the targets that has external modem.
1212 * Enable device command should be sent to modem only after
1213 * enabling voice call mixer controls
1214 */
vivek mehta765eb642015-08-07 19:46:06 -07001215 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001216 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1217 out_snd_device,
1218 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001219 /* Enable sidetone only if voice call already exists */
1220 if (voice_is_call_state_active(adev))
1221 voice_set_sidetone(adev, out_snd_device, true);
1222 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001223
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001224 return status;
1225}
1226
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001227static int stop_input_stream(struct stream_in *in)
1228{
1229 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001230 struct audio_usecase *uc_info;
1231 struct audio_device *adev = in->dev;
1232
Eric Laurentc8400632013-02-14 19:04:54 -08001233 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001234
Eric Laurent994a6932013-07-17 11:51:42 -07001235 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001236 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001237 uc_info = get_usecase_from_list(adev, in->usecase);
1238 if (uc_info == NULL) {
1239 ALOGE("%s: Could not find the usecase (%d) in the list",
1240 __func__, in->usecase);
1241 return -EINVAL;
1242 }
1243
Eric Laurent150dbfe2013-02-27 14:31:02 -08001244 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001245 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001246
1247 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001248 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001249
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001250 list_remove(&uc_info->list);
1251 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001252
Eric Laurent994a6932013-07-17 11:51:42 -07001253 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001254 return ret;
1255}
1256
1257int start_input_stream(struct stream_in *in)
1258{
1259 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001260 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001261 struct audio_usecase *uc_info;
1262 struct audio_device *adev = in->dev;
1263
Eric Laurent994a6932013-07-17 11:51:42 -07001264 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001265
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001266 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1267 return -EIO;
1268
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001269 if (in->card_status == CARD_STATUS_OFFLINE ||
1270 adev->card_status == CARD_STATUS_OFFLINE) {
1271 ALOGW("in->card_status or adev->card_status offline, try again");
1272 ret = -EAGAIN;
1273 goto error_config;
1274 }
1275
Eric Laurentb23d5282013-05-14 15:27:20 -07001276 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001277 if (in->pcm_device_id < 0) {
1278 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1279 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001280 ret = -EINVAL;
1281 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001282 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001283
1284 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001285 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1286 uc_info->id = in->usecase;
1287 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001288 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001289 uc_info->devices = in->device;
1290 uc_info->in_snd_device = SND_DEVICE_NONE;
1291 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001292
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001293 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001294
1295 audio_extn_perf_lock_acquire();
1296
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001297 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001298
Eric Laurent0e46adf2016-12-16 12:49:24 -08001299 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001300 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001301 ALOGE("%s: pcm stream not ready", __func__);
1302 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001303 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001304 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001305 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001306 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1307 goto error_open;
1308 }
1309 } else {
1310 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1311 unsigned int pcm_open_retry_count = 0;
1312
1313 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1314 flags |= PCM_MMAP | PCM_NOIRQ;
1315 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1316 } else if (in->realtime) {
1317 flags |= PCM_MMAP | PCM_NOIRQ;
1318 }
1319
1320 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1321 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1322
1323 while (1) {
1324 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1325 flags, &in->config);
1326 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1327 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1328 if (in->pcm != NULL) {
1329 pcm_close(in->pcm);
1330 in->pcm = NULL;
1331 }
1332 if (pcm_open_retry_count-- == 0) {
1333 ret = -EIO;
1334 goto error_open;
1335 }
1336 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1337 continue;
1338 }
1339 break;
1340 }
1341
1342 ALOGV("%s: pcm_prepare", __func__);
1343 ret = pcm_prepare(in->pcm);
1344 if (ret < 0) {
1345 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001346 pcm_close(in->pcm);
1347 in->pcm = NULL;
1348 goto error_open;
1349 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001350 if (in->realtime) {
1351 ret = pcm_start(in->pcm);
1352 if (ret < 0) {
1353 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1354 pcm_close(in->pcm);
1355 in->pcm = NULL;
1356 goto error_open;
1357 }
1358 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001359 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001360 register_in_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001361 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001362 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001363
Eric Laurent0e46adf2016-12-16 12:49:24 -08001364 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001365
1366error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001367 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001368 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001369
1370error_config:
1371 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001372 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001373
1374 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001375}
1376
Eric Laurenta1478072015-09-21 17:21:52 -07001377void lock_input_stream(struct stream_in *in)
1378{
1379 pthread_mutex_lock(&in->pre_lock);
1380 pthread_mutex_lock(&in->lock);
1381 pthread_mutex_unlock(&in->pre_lock);
1382}
1383
1384void lock_output_stream(struct stream_out *out)
1385{
1386 pthread_mutex_lock(&out->pre_lock);
1387 pthread_mutex_lock(&out->lock);
1388 pthread_mutex_unlock(&out->pre_lock);
1389}
1390
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001391/* must be called with out->lock locked */
1392static int send_offload_cmd_l(struct stream_out* out, int command)
1393{
1394 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1395
1396 ALOGVV("%s %d", __func__, command);
1397
1398 cmd->cmd = command;
1399 list_add_tail(&out->offload_cmd_list, &cmd->node);
1400 pthread_cond_signal(&out->offload_cond);
1401 return 0;
1402}
1403
1404/* must be called iwth out->lock locked */
1405static void stop_compressed_output_l(struct stream_out *out)
1406{
1407 out->offload_state = OFFLOAD_STATE_IDLE;
1408 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001409 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001410 if (out->compr != NULL) {
1411 compress_stop(out->compr);
1412 while (out->offload_thread_blocked) {
1413 pthread_cond_wait(&out->cond, &out->lock);
1414 }
1415 }
1416}
1417
1418static void *offload_thread_loop(void *context)
1419{
1420 struct stream_out *out = (struct stream_out *) context;
1421 struct listnode *item;
1422
1423 out->offload_state = OFFLOAD_STATE_IDLE;
1424 out->playback_started = 0;
1425
1426 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1427 set_sched_policy(0, SP_FOREGROUND);
1428 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1429
1430 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001431 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001432 for (;;) {
1433 struct offload_cmd *cmd = NULL;
1434 stream_callback_event_t event;
1435 bool send_callback = false;
1436
1437 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1438 __func__, list_empty(&out->offload_cmd_list),
1439 out->offload_state);
1440 if (list_empty(&out->offload_cmd_list)) {
1441 ALOGV("%s SLEEPING", __func__);
1442 pthread_cond_wait(&out->offload_cond, &out->lock);
1443 ALOGV("%s RUNNING", __func__);
1444 continue;
1445 }
1446
1447 item = list_head(&out->offload_cmd_list);
1448 cmd = node_to_item(item, struct offload_cmd, node);
1449 list_remove(item);
1450
1451 ALOGVV("%s STATE %d CMD %d out->compr %p",
1452 __func__, out->offload_state, cmd->cmd, out->compr);
1453
1454 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1455 free(cmd);
1456 break;
1457 }
1458
1459 if (out->compr == NULL) {
1460 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001461 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001462 pthread_cond_signal(&out->cond);
1463 continue;
1464 }
1465 out->offload_thread_blocked = true;
1466 pthread_mutex_unlock(&out->lock);
1467 send_callback = false;
1468 switch(cmd->cmd) {
1469 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1470 compress_wait(out->compr, -1);
1471 send_callback = true;
1472 event = STREAM_CBK_EVENT_WRITE_READY;
1473 break;
1474 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001475 compress_next_track(out->compr);
1476 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001477 send_callback = true;
1478 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001479 /* Resend the metadata for next iteration */
1480 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001481 break;
1482 case OFFLOAD_CMD_DRAIN:
1483 compress_drain(out->compr);
1484 send_callback = true;
1485 event = STREAM_CBK_EVENT_DRAIN_READY;
1486 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001487 case OFFLOAD_CMD_ERROR:
1488 send_callback = true;
1489 event = STREAM_CBK_EVENT_ERROR;
1490 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001491 default:
1492 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1493 break;
1494 }
Eric Laurenta1478072015-09-21 17:21:52 -07001495 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001496 out->offload_thread_blocked = false;
1497 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001498 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001499 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001500 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001501 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001502 free(cmd);
1503 }
1504
1505 pthread_cond_signal(&out->cond);
1506 while (!list_empty(&out->offload_cmd_list)) {
1507 item = list_head(&out->offload_cmd_list);
1508 list_remove(item);
1509 free(node_to_item(item, struct offload_cmd, node));
1510 }
1511 pthread_mutex_unlock(&out->lock);
1512
1513 return NULL;
1514}
1515
1516static int create_offload_callback_thread(struct stream_out *out)
1517{
1518 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1519 list_init(&out->offload_cmd_list);
1520 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1521 offload_thread_loop, out);
1522 return 0;
1523}
1524
1525static int destroy_offload_callback_thread(struct stream_out *out)
1526{
Eric Laurenta1478072015-09-21 17:21:52 -07001527 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001528 stop_compressed_output_l(out);
1529 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1530
1531 pthread_mutex_unlock(&out->lock);
1532 pthread_join(out->offload_thread, (void **) NULL);
1533 pthread_cond_destroy(&out->offload_cond);
1534
1535 return 0;
1536}
1537
Eric Laurent07eeafd2013-10-06 12:52:49 -07001538static bool allow_hdmi_channel_config(struct audio_device *adev)
1539{
1540 struct listnode *node;
1541 struct audio_usecase *usecase;
1542 bool ret = true;
1543
1544 list_for_each(node, &adev->usecase_list) {
1545 usecase = node_to_item(node, struct audio_usecase, list);
1546 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1547 /*
1548 * If voice call is already existing, do not proceed further to avoid
1549 * disabling/enabling both RX and TX devices, CSD calls, etc.
1550 * Once the voice call done, the HDMI channels can be configured to
1551 * max channels of remaining use cases.
1552 */
1553 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001554 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001555 __func__);
1556 ret = false;
1557 break;
1558 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
Joe Onorato188b6222016-03-01 11:02:27 -08001559 ALOGV("%s: multi channel playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001560 "no change in HDMI channels", __func__);
1561 ret = false;
1562 break;
1563 }
1564 }
1565 }
1566 return ret;
1567}
1568
1569static int check_and_set_hdmi_channels(struct audio_device *adev,
1570 unsigned int channels)
1571{
1572 struct listnode *node;
1573 struct audio_usecase *usecase;
1574
1575 /* Check if change in HDMI channel config is allowed */
1576 if (!allow_hdmi_channel_config(adev))
1577 return 0;
1578
1579 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001580 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001581 return 0;
1582 }
1583
1584 platform_set_hdmi_channels(adev->platform, channels);
1585 adev->cur_hdmi_channels = channels;
1586
1587 /*
1588 * Deroute all the playback streams routed to HDMI so that
1589 * the back end is deactivated. Note that backend will not
1590 * be deactivated if any one stream is connected to it.
1591 */
1592 list_for_each(node, &adev->usecase_list) {
1593 usecase = node_to_item(node, struct audio_usecase, list);
1594 if (usecase->type == PCM_PLAYBACK &&
1595 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001596 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001597 }
1598 }
1599
1600 /*
1601 * Enable all the streams disabled above. Now the HDMI backend
1602 * will be activated with new channel configuration
1603 */
1604 list_for_each(node, &adev->usecase_list) {
1605 usecase = node_to_item(node, struct audio_usecase, list);
1606 if (usecase->type == PCM_PLAYBACK &&
1607 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001608 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001609 }
1610 }
1611
1612 return 0;
1613}
1614
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001615static int stop_output_stream(struct stream_out *out)
1616{
1617 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001618 struct audio_usecase *uc_info;
1619 struct audio_device *adev = out->dev;
1620
Eric Laurent994a6932013-07-17 11:51:42 -07001621 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001622 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001623 uc_info = get_usecase_from_list(adev, out->usecase);
1624 if (uc_info == NULL) {
1625 ALOGE("%s: Could not find the usecase (%d) in the list",
1626 __func__, out->usecase);
1627 return -EINVAL;
1628 }
1629
Haynes Mathew George41f86652014-06-17 14:22:15 -07001630 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1631 if (adev->visualizer_stop_output != NULL)
1632 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1633 if (adev->offload_effects_stop_output != NULL)
1634 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1635 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001636
Eric Laurent150dbfe2013-02-27 14:31:02 -08001637 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001638 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001639
1640 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001641 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001642
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001643 list_remove(&uc_info->list);
1644 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001645
Eric Laurent0499d4f2014-08-25 22:39:29 -05001646 audio_extn_extspk_update(adev->extspk);
1647
Eric Laurent07eeafd2013-10-06 12:52:49 -07001648 /* Must be called after removing the usecase from list */
1649 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1650 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1651
Eric Laurent994a6932013-07-17 11:51:42 -07001652 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001653 return ret;
1654}
1655
1656int start_output_stream(struct stream_out *out)
1657{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001658 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001659 struct audio_usecase *uc_info;
1660 struct audio_device *adev = out->dev;
1661
Eric Laurent994a6932013-07-17 11:51:42 -07001662 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001663 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001664
1665 if (out->card_status == CARD_STATUS_OFFLINE ||
1666 adev->card_status == CARD_STATUS_OFFLINE) {
1667 ALOGW("out->card_status or adev->card_status offline, try again");
1668 ret = -EAGAIN;
1669 goto error_config;
1670 }
1671
Eric Laurentb23d5282013-05-14 15:27:20 -07001672 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001673 if (out->pcm_device_id < 0) {
1674 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1675 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001676 ret = -EINVAL;
1677 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001678 }
1679
1680 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1681 uc_info->id = out->usecase;
1682 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001683 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001684 uc_info->devices = out->devices;
1685 uc_info->in_snd_device = SND_DEVICE_NONE;
1686 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001687
Eric Laurent07eeafd2013-10-06 12:52:49 -07001688 /* This must be called before adding this usecase to the list */
1689 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1690 check_and_set_hdmi_channels(adev, out->config.channels);
1691
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001692 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001693
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001694 audio_extn_perf_lock_acquire();
1695
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001696 select_devices(adev, out->usecase);
1697
Eric Laurent0499d4f2014-08-25 22:39:29 -05001698 audio_extn_extspk_update(adev->extspk);
1699
Andy Hung31aca912014-03-20 17:14:59 -07001700 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001701 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001702 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1703 out->pcm = NULL;
1704 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1705 COMPRESS_IN, &out->compr_config);
1706 if (out->compr && !is_compress_ready(out->compr)) {
1707 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1708 compress_close(out->compr);
1709 out->compr = NULL;
1710 ret = -EIO;
1711 goto error_open;
1712 }
1713 if (out->offload_callback)
1714 compress_nonblock(out->compr, out->non_blocking);
1715
1716 if (adev->visualizer_start_output != NULL)
1717 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1718 if (adev->offload_effects_start_output != NULL)
1719 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
1720 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001721 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001722 ALOGE("%s: pcm stream not ready", __func__);
1723 goto error_open;
1724 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001725 ret = pcm_start(out->pcm);
1726 if (ret < 0) {
1727 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1728 goto error_open;
1729 }
1730 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001731 unsigned int flags = PCM_OUT;
1732 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001733
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001734 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1735 flags |= PCM_MMAP | PCM_NOIRQ;
1736 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001737 } else if (out->realtime) {
1738 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001739 } else
1740 flags |= PCM_MONOTONIC;
1741
1742 while (1) {
1743 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1744 flags, &out->config);
1745 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1746 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1747 if (out->pcm != NULL) {
1748 pcm_close(out->pcm);
1749 out->pcm = NULL;
1750 }
1751 if (pcm_open_retry_count-- == 0) {
1752 ret = -EIO;
1753 goto error_open;
1754 }
1755 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1756 continue;
1757 }
1758 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001759 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001760 ALOGV("%s: pcm_prepare", __func__);
1761 if (pcm_is_ready(out->pcm)) {
1762 ret = pcm_prepare(out->pcm);
1763 if (ret < 0) {
1764 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1765 pcm_close(out->pcm);
1766 out->pcm = NULL;
1767 goto error_open;
1768 }
1769 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001770 if (out->realtime) {
1771 ret = pcm_start(out->pcm);
1772 if (ret < 0) {
1773 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1774 pcm_close(out->pcm);
1775 out->pcm = NULL;
1776 goto error_open;
1777 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001778 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001779 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001780 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001781 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001782 audio_extn_tfa_98xx_enable_speaker();
1783
Eric Laurent994a6932013-07-17 11:51:42 -07001784 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001785 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001786error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001787 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001788 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001789error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001790 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001791}
1792
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001793static int check_input_parameters(uint32_t sample_rate,
1794 audio_format_t format,
1795 int channel_count)
1796{
vivek mehta4ed66e62016-04-15 23:33:34 -07001797 if ((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT)) {
vivek mehtadae44712015-07-27 14:13:18 -07001798 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1799 return -EINVAL;
1800 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001801
vivek mehtadae44712015-07-27 14:13:18 -07001802 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > MAX_CHANNEL_COUNT)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001803 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
vivek mehtadae44712015-07-27 14:13:18 -07001804 channel_count, MIN_CHANNEL_COUNT, MAX_CHANNEL_COUNT);
1805 return -EINVAL;
1806 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001807
1808 switch (sample_rate) {
1809 case 8000:
1810 case 11025:
1811 case 12000:
1812 case 16000:
1813 case 22050:
1814 case 24000:
1815 case 32000:
1816 case 44100:
1817 case 48000:
1818 break;
1819 default:
vivek mehtadae44712015-07-27 14:13:18 -07001820 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001821 return -EINVAL;
1822 }
1823
1824 return 0;
1825}
1826
1827static size_t get_input_buffer_size(uint32_t sample_rate,
1828 audio_format_t format,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001829 int channel_count,
1830 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001831{
1832 size_t size = 0;
1833
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001834 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1835 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001836
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001837 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001838 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001839 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07001840
1841 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001842
Glenn Kasten4f993392014-05-14 07:30:48 -07001843 /* make sure the size is multiple of 32 bytes
1844 * At 48 kHz mono 16-bit PCM:
1845 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1846 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1847 */
1848 size += 0x1f;
1849 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001850
1851 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001852}
1853
1854static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1855{
1856 struct stream_out *out = (struct stream_out *)stream;
1857
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001858 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001859}
1860
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001861static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001862{
1863 return -ENOSYS;
1864}
1865
1866static size_t out_get_buffer_size(const struct audio_stream *stream)
1867{
1868 struct stream_out *out = (struct stream_out *)stream;
1869
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001870 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1871 return out->compr_config.fragment_size;
1872 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001873 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07001874 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001875}
1876
1877static uint32_t out_get_channels(const struct audio_stream *stream)
1878{
1879 struct stream_out *out = (struct stream_out *)stream;
1880
1881 return out->channel_mask;
1882}
1883
1884static audio_format_t out_get_format(const struct audio_stream *stream)
1885{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001886 struct stream_out *out = (struct stream_out *)stream;
1887
1888 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001889}
1890
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001891static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001892{
1893 return -ENOSYS;
1894}
1895
1896static int out_standby(struct audio_stream *stream)
1897{
1898 struct stream_out *out = (struct stream_out *)stream;
1899 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08001900 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001901
Eric Laurent994a6932013-07-17 11:51:42 -07001902 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001903 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001904
Eric Laurenta1478072015-09-21 17:21:52 -07001905 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001906 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001907 if (adev->adm_deregister_stream)
1908 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001909 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001910 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001911 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1912 if (out->pcm) {
1913 pcm_close(out->pcm);
1914 out->pcm = NULL;
1915 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001916 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001917 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08001918 out->playback_started = false;
1919 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001920 } else {
1921 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001922 out->gapless_mdata.encoder_delay = 0;
1923 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001924 if (out->compr != NULL) {
1925 compress_close(out->compr);
1926 out->compr = NULL;
1927 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001928 }
Phil Burkbc991042017-02-24 08:06:44 -08001929 if (do_stop) {
1930 stop_output_stream(out);
1931 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001932 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001933 }
1934 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001935 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001936 return 0;
1937}
1938
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001939static int out_on_error(struct audio_stream *stream)
1940{
1941 struct stream_out *out = (struct stream_out *)stream;
1942 struct audio_device *adev = out->dev;
1943 bool do_standby = false;
1944
1945 lock_output_stream(out);
1946 if (!out->standby) {
1947 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1948 stop_compressed_output_l(out);
1949 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
1950 } else
1951 do_standby = true;
1952 }
1953 pthread_mutex_unlock(&out->lock);
1954
1955 if (do_standby)
1956 return out_standby(&out->stream.common);
1957
1958 return 0;
1959}
1960
Andy Hung7401c7c2016-09-21 12:41:21 -07001961static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001962{
Andy Hung7401c7c2016-09-21 12:41:21 -07001963 struct stream_out *out = (struct stream_out *)stream;
1964
1965 // We try to get the lock for consistency,
1966 // but it isn't necessary for these variables.
1967 // If we're not in standby, we may be blocked on a write.
1968 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
1969 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
1970 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
1971
1972 if (locked) {
1973 log_dump_l(&out->error_log, fd);
1974 pthread_mutex_unlock(&out->lock);
1975 } else {
1976 // We don't have the lock here, copy for safety.
1977 struct error_log log = out->error_log;
1978 log_dump_l(&log, fd);
1979 }
Andy Hungfc044e12017-03-20 09:24:22 -07001980 // dump power info (out->power_log may be null)
1981 (void)power_log_dump(out->power_log, fd, POWER_LOG_LINES, 0 /* limitNs */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001982 return 0;
1983}
1984
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001985static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1986{
1987 int ret = 0;
1988 char value[32];
1989 struct compr_gapless_mdata tmp_mdata;
1990
1991 if (!out || !parms) {
1992 return -EINVAL;
1993 }
1994
1995 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1996 if (ret >= 0) {
1997 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
1998 } else {
1999 return -EINVAL;
2000 }
2001
2002 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2003 if (ret >= 0) {
2004 tmp_mdata.encoder_padding = atoi(value);
2005 } else {
2006 return -EINVAL;
2007 }
2008
2009 out->gapless_mdata = tmp_mdata;
2010 out->send_new_metadata = 1;
2011 ALOGV("%s new encoder delay %u and padding %u", __func__,
2012 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2013
2014 return 0;
2015}
2016
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002017static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2018{
2019 return out == adev->primary_output || out == adev->voice_tx_output;
2020}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002021
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002022static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2023{
2024 struct stream_out *out = (struct stream_out *)stream;
2025 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002026 struct audio_usecase *usecase;
2027 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002028 struct str_parms *parms;
2029 char value[32];
2030 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002031 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002032 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002033
Eric Laurent2e140aa2016-06-30 17:14:46 -07002034 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002035 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002036 parms = str_parms_create_str(kvpairs);
2037 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2038 if (ret >= 0) {
2039 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07002040 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002041 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002042
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002043 /*
2044 * When HDMI cable is unplugged the music playback is paused and
2045 * the policy manager sends routing=0. But the audioflinger
2046 * continues to write data until standby time (3sec).
2047 * As the HDMI core is turned off, the write gets blocked.
2048 * Avoid this by routing audio to speaker until standby.
2049 */
2050 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2051 val == AUDIO_DEVICE_NONE) {
2052 val = AUDIO_DEVICE_OUT_SPEAKER;
2053 }
2054
2055 /*
2056 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002057 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002058 * the select_devices(). But how do we undo this?
2059 *
2060 * For example, music playback is active on headset (deep-buffer usecase)
2061 * and if we go to ringtones and select a ringtone, low-latency usecase
2062 * will be started on headset+speaker. As we can't enable headset+speaker
2063 * and headset devices at the same time, select_devices() switches the music
2064 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2065 * So when the ringtone playback is completed, how do we undo the same?
2066 *
2067 * We are relying on the out_set_parameters() call on deep-buffer output,
2068 * once the ringtone playback is ended.
2069 * NOTE: We should not check if the current devices are same as new devices.
2070 * Because select_devices() must be called to switch back the music
2071 * playback to headset.
2072 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002073 audio_devices_t new_dev = val;
2074 if (new_dev != AUDIO_DEVICE_NONE) {
2075 bool same_dev = out->devices == new_dev;
2076 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002077
Eric Laurenta7657192014-10-09 21:09:33 -07002078 if (output_drives_call(adev, out)) {
2079 if (!voice_is_in_call(adev)) {
2080 if (adev->mode == AUDIO_MODE_IN_CALL) {
2081 adev->current_call_output = out;
2082 ret = voice_start_call(adev);
2083 }
2084 } else {
2085 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002086 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002087 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002088 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002089
2090 if (!out->standby) {
2091 if (!same_dev) {
2092 ALOGV("update routing change");
2093 out->routing_change = true;
2094 }
2095 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002096 audio_extn_tfa_98xx_update();
vivek mehta0d3637a2016-07-24 09:32:02 -07002097 }
2098
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002099 }
2100
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002101 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002102 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002103
2104 /*handles device and call state changes*/
2105 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002106 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002107
2108 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2109 parse_compress_metadata(out, parms);
2110 }
2111
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002112 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002113 ALOGV("%s: exit: code(%d)", __func__, status);
2114 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002115}
2116
2117static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2118{
2119 struct stream_out *out = (struct stream_out *)stream;
2120 struct str_parms *query = str_parms_create_str(keys);
2121 char *str;
2122 char value[256];
2123 struct str_parms *reply = str_parms_create();
2124 size_t i, j;
2125 int ret;
2126 bool first = true;
Eric Laurent994a6932013-07-17 11:51:42 -07002127 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002128 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2129 if (ret >= 0) {
2130 value[0] = '\0';
2131 i = 0;
2132 while (out->supported_channel_masks[i] != 0) {
2133 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2134 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2135 if (!first) {
2136 strcat(value, "|");
2137 }
2138 strcat(value, out_channels_name_to_enum_table[j].name);
2139 first = false;
2140 break;
2141 }
2142 }
2143 i++;
2144 }
2145 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2146 str = str_parms_to_str(reply);
2147 } else {
2148 str = strdup(keys);
2149 }
2150 str_parms_destroy(query);
2151 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002152 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002153 return str;
2154}
2155
2156static uint32_t out_get_latency(const struct audio_stream_out *stream)
2157{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002158 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002159 struct stream_out *out = (struct stream_out *)stream;
2160
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002161 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2162 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002163 else if ((out->realtime) ||
2164 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002165 // since the buffer won't be filled up faster than realtime,
2166 // return a smaller number
2167 period_ms = (out->af_period_multiplier * out->config.period_size *
2168 1000) / (out->config.rate);
2169 hw_delay = platform_render_latency(out->usecase)/1000;
2170 return period_ms + hw_delay;
2171 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002172
2173 return (out->config.period_count * out->config.period_size * 1000) /
2174 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002175}
2176
2177static int out_set_volume(struct audio_stream_out *stream, float left,
2178 float right)
2179{
Eric Laurenta9024de2013-04-04 09:19:12 -07002180 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002181 int volume[2];
2182
Eric Laurenta9024de2013-04-04 09:19:12 -07002183 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2184 /* only take left channel into account: the API is for stereo anyway */
2185 out->muted = (left == 0.0f);
2186 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002187 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2188 const char *mixer_ctl_name = "Compress Playback Volume";
2189 struct audio_device *adev = out->dev;
2190 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002191 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2192 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002193 /* try with the control based on device id */
2194 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2195 PCM_PLAYBACK);
2196 char ctl_name[128] = {0};
2197 snprintf(ctl_name, sizeof(ctl_name),
2198 "Compress Playback %d Volume", pcm_device_id);
2199 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2200 if (!ctl) {
2201 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2202 return -EINVAL;
2203 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002204 }
2205 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2206 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2207 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2208 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002209 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002210
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002211 return -ENOSYS;
2212}
2213
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002214// note: this call is safe only if the stream_cb is
2215// removed first in close_output_stream (as is done now).
2216static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2217{
2218 if (!stream || !parms)
2219 return;
2220
2221 struct stream_out *out = (struct stream_out *)stream;
2222 struct audio_device *adev = out->dev;
2223
2224 card_status_t status;
2225 int card;
2226 if (parse_snd_card_status(parms, &card, &status) < 0)
2227 return;
2228
2229 pthread_mutex_lock(&adev->lock);
2230 bool valid_cb = (card == adev->snd_card);
2231 pthread_mutex_unlock(&adev->lock);
2232
2233 if (!valid_cb)
2234 return;
2235
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002236 lock_output_stream(out);
2237 if (out->card_status != status)
2238 out->card_status = status;
2239 pthread_mutex_unlock(&out->lock);
2240
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002241 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2242 use_case_table[out->usecase],
2243 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2244
2245 if (status == CARD_STATUS_OFFLINE)
2246 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002247
2248 return;
2249}
2250
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002251#ifdef NO_AUDIO_OUT
2252static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002253 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002254{
2255 struct stream_out *out = (struct stream_out *)stream;
2256
2257 /* No Output device supported other than BT for playback.
2258 * Sleep for the amount of buffer duration
2259 */
Eric Laurenta1478072015-09-21 17:21:52 -07002260 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002261 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2262 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002263 out_get_sample_rate(&out->stream.common));
2264 pthread_mutex_unlock(&out->lock);
2265 return bytes;
2266}
2267#endif
2268
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002269static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2270 size_t bytes)
2271{
2272 struct stream_out *out = (struct stream_out *)stream;
2273 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002274 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002275 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002276
Eric Laurenta1478072015-09-21 17:21:52 -07002277 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002278 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2279 error_code = ERROR_CODE_WRITE;
2280 goto exit;
2281 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002282 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002283 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002284 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002285 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002286 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002287 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002288 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002289 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002290 goto exit;
2291 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002292
2293 if (last_known_cal_step != -1) {
2294 ALOGD("%s: retry previous failed cal level set", __func__);
2295 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2296 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002297 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002298
Andy Hungfc044e12017-03-20 09:24:22 -07002299 // this is always nonzero
2300 const size_t frame_size = audio_stream_out_frame_size(stream);
2301
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002302 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002303 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002304 if (out->send_new_metadata) {
2305 ALOGVV("send new gapless metadata");
2306 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2307 out->send_new_metadata = 0;
2308 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002309 unsigned int avail;
2310 struct timespec tstamp;
2311 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2312 /* Do not limit write size if the available frames count is unknown */
2313 if (ret != 0) {
2314 avail = bytes;
2315 }
2316 if (avail == 0) {
2317 ret = 0;
2318 } else {
2319 if (avail > bytes) {
2320 avail = bytes;
2321 }
2322 ret = compress_write(out->compr, buffer, avail);
2323 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2324 __func__, avail, ret);
2325 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002326
Eric Laurent6e895242013-09-05 16:10:57 -07002327 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002328 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2329 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002330 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002331 compress_start(out->compr);
2332 out->playback_started = 1;
2333 out->offload_state = OFFLOAD_STATE_PLAYING;
2334 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002335 if (ret < 0) {
2336 log_error_l(&out->error_log, ERROR_CODE_WRITE);
2337 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002338 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002339 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002340 return ret;
2341 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002342 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002343 if (out->pcm) {
2344 if (out->muted)
2345 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002346
Eric Laurent0e46adf2016-12-16 12:49:24 -08002347 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002348
Haynes Mathew George03c40102016-01-29 17:57:48 -08002349 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2350 out->config.rate;
2351 request_out_focus(out, ns);
2352
2353 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2354 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002355 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002356 else
2357 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002358
Haynes Mathew George03c40102016-01-29 17:57:48 -08002359 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002360 } else {
2361 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002362 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002363 }
2364
2365exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002366 // For PCM we always consume the buffer and return #bytes regardless of ret.
2367 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2368 out->written += bytes / (out->config.channels * sizeof(short));
2369 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002370 long long sleeptime_us = 0;
Andy Hungfc044e12017-03-20 09:24:22 -07002371 const int64_t now_ns = audio_utils_get_real_time_ns();
2372
Andy Hung7401c7c2016-09-21 12:41:21 -07002373 if (ret != 0) {
2374 log_error_l(&out->error_log, error_code);
2375 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2376 ALOGE_IF(out->pcm != NULL,
2377 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hungfc044e12017-03-20 09:24:22 -07002378 sleeptime_us = bytes * 1000000LL / frame_size /
Andy Hung7401c7c2016-09-21 12:41:21 -07002379 out_get_sample_rate(&out->stream.common);
2380 // usleep not guaranteed for values over 1 second but we don't limit here.
2381 }
2382 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002383
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002384 pthread_mutex_unlock(&out->lock);
2385
2386 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002387 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002388 if (sleeptime_us != 0)
2389 usleep(sleeptime_us);
Andy Hungfc044e12017-03-20 09:24:22 -07002390 } else {
2391 // only log if the data is properly written (out->power_log may be null)
2392 power_log_log(out->power_log, buffer, bytes / frame_size, now_ns);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002393 }
2394 return bytes;
2395}
2396
2397static int out_get_render_position(const struct audio_stream_out *stream,
2398 uint32_t *dsp_frames)
2399{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002400 struct stream_out *out = (struct stream_out *)stream;
2401 *dsp_frames = 0;
2402 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002403 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002404 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002405 unsigned long frames = 0;
2406 // TODO: check return value
2407 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2408 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002409 ALOGVV("%s rendered frames %d sample_rate %d",
2410 __func__, *dsp_frames, out->sample_rate);
2411 }
2412 pthread_mutex_unlock(&out->lock);
2413 return 0;
2414 } else
2415 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002416}
2417
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002418static int out_add_audio_effect(const struct audio_stream *stream __unused,
2419 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002420{
2421 return 0;
2422}
2423
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002424static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2425 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002426{
2427 return 0;
2428}
2429
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002430static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2431 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002432{
2433 return -EINVAL;
2434}
2435
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002436static int out_get_presentation_position(const struct audio_stream_out *stream,
2437 uint64_t *frames, struct timespec *timestamp)
2438{
2439 struct stream_out *out = (struct stream_out *)stream;
Andy Hung7171da22016-03-08 16:58:42 -08002440 int ret = -EINVAL;
Eric Laurent949a0892013-09-20 09:20:13 -07002441 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002442
Eric Laurenta1478072015-09-21 17:21:52 -07002443 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002444
Eric Laurent949a0892013-09-20 09:20:13 -07002445 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2446 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002447 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002448 compress_get_tstamp(out->compr, &dsp_frames,
2449 &out->sample_rate);
2450 ALOGVV("%s rendered frames %ld sample_rate %d",
2451 __func__, dsp_frames, out->sample_rate);
2452 *frames = dsp_frames;
2453 ret = 0;
2454 /* this is the best we can do */
2455 clock_gettime(CLOCK_MONOTONIC, timestamp);
2456 }
2457 } else {
2458 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002459 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002460 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2461 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002462 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002463 // This adjustment accounts for buffering after app processor.
2464 // It is based on estimated DSP latency per use case, rather than exact.
2465 signed_frames -=
2466 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2467
Eric Laurent949a0892013-09-20 09:20:13 -07002468 // It would be unusual for this value to be negative, but check just in case ...
2469 if (signed_frames >= 0) {
2470 *frames = signed_frames;
2471 ret = 0;
2472 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002473 }
2474 }
2475 }
2476
2477 pthread_mutex_unlock(&out->lock);
2478
2479 return ret;
2480}
2481
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002482static int out_set_callback(struct audio_stream_out *stream,
2483 stream_callback_t callback, void *cookie)
2484{
2485 struct stream_out *out = (struct stream_out *)stream;
2486
2487 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002488 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002489 out->offload_callback = callback;
2490 out->offload_cookie = cookie;
2491 pthread_mutex_unlock(&out->lock);
2492 return 0;
2493}
2494
2495static int out_pause(struct audio_stream_out* stream)
2496{
2497 struct stream_out *out = (struct stream_out *)stream;
2498 int status = -ENOSYS;
2499 ALOGV("%s", __func__);
2500 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002501 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002502 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2503 status = compress_pause(out->compr);
2504 out->offload_state = OFFLOAD_STATE_PAUSED;
2505 }
2506 pthread_mutex_unlock(&out->lock);
2507 }
2508 return status;
2509}
2510
2511static int out_resume(struct audio_stream_out* stream)
2512{
2513 struct stream_out *out = (struct stream_out *)stream;
2514 int status = -ENOSYS;
2515 ALOGV("%s", __func__);
2516 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2517 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002518 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002519 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2520 status = compress_resume(out->compr);
2521 out->offload_state = OFFLOAD_STATE_PLAYING;
2522 }
2523 pthread_mutex_unlock(&out->lock);
2524 }
2525 return status;
2526}
2527
2528static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2529{
2530 struct stream_out *out = (struct stream_out *)stream;
2531 int status = -ENOSYS;
2532 ALOGV("%s", __func__);
2533 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002534 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002535 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2536 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2537 else
2538 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2539 pthread_mutex_unlock(&out->lock);
2540 }
2541 return status;
2542}
2543
2544static int out_flush(struct audio_stream_out* stream)
2545{
2546 struct stream_out *out = (struct stream_out *)stream;
2547 ALOGV("%s", __func__);
2548 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002549 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002550 stop_compressed_output_l(out);
2551 pthread_mutex_unlock(&out->lock);
2552 return 0;
2553 }
2554 return -ENOSYS;
2555}
2556
Eric Laurent0e46adf2016-12-16 12:49:24 -08002557static int out_stop(const struct audio_stream_out* stream)
2558{
2559 struct stream_out *out = (struct stream_out *)stream;
2560 struct audio_device *adev = out->dev;
2561 int ret = -ENOSYS;
2562
2563 ALOGV("%s", __func__);
2564 pthread_mutex_lock(&adev->lock);
2565 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2566 out->playback_started && out->pcm != NULL) {
2567 pcm_stop(out->pcm);
2568 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08002569 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002570 }
2571 pthread_mutex_unlock(&adev->lock);
2572 return ret;
2573}
2574
2575static int out_start(const struct audio_stream_out* stream)
2576{
2577 struct stream_out *out = (struct stream_out *)stream;
2578 struct audio_device *adev = out->dev;
2579 int ret = -ENOSYS;
2580
2581 ALOGV("%s", __func__);
2582 pthread_mutex_lock(&adev->lock);
2583 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2584 !out->playback_started && out->pcm != NULL) {
2585 ret = start_output_stream(out);
2586 if (ret == 0) {
2587 out->playback_started = true;
2588 }
2589 }
2590 pthread_mutex_unlock(&adev->lock);
2591 return ret;
2592}
2593
Phil Burkbc991042017-02-24 08:06:44 -08002594/*
2595 * Modify config->period_count based on min_size_frames
2596 */
2597static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
2598{
2599 int periodCountRequested = (min_size_frames + config->period_size - 1)
2600 / config->period_size;
2601 int periodCount = MMAP_PERIOD_COUNT_MIN;
2602
2603 ALOGV("%s original config.period_size = %d config.period_count = %d",
2604 __func__, config->period_size, config->period_count);
2605
2606 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
2607 periodCount *= 2;
2608 }
2609 config->period_count = periodCount;
2610
2611 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
2612}
2613
Eric Laurent0e46adf2016-12-16 12:49:24 -08002614static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2615 int32_t min_size_frames,
2616 struct audio_mmap_buffer_info *info)
2617{
2618 struct stream_out *out = (struct stream_out *)stream;
2619 struct audio_device *adev = out->dev;
2620 int ret = 0;
2621 unsigned int offset1;
2622 unsigned int frames1;
2623 const char *step = "";
2624
2625 ALOGV("%s", __func__);
2626 pthread_mutex_lock(&adev->lock);
2627
2628 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002629 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002630 ret = -EINVAL;
2631 goto exit;
2632 }
2633 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08002634 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002635 ret = -ENOSYS;
2636 goto exit;
2637 }
2638 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
2639 if (out->pcm_device_id < 0) {
2640 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2641 __func__, out->pcm_device_id, out->usecase);
2642 ret = -EINVAL;
2643 goto exit;
2644 }
Phil Burkbc991042017-02-24 08:06:44 -08002645
2646 adjust_mmap_period_count(&out->config, min_size_frames);
2647
Eric Laurent0e46adf2016-12-16 12:49:24 -08002648 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2649 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
2650 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2651 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
2652 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2653 step = "open";
2654 ret = -ENODEV;
2655 goto exit;
2656 }
2657 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
2658 if (ret < 0) {
2659 step = "begin";
2660 goto exit;
2661 }
2662 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
2663 info->burst_size_frames = out->config.period_size;
2664 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
2665
2666 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
2667 info->buffer_size_frames));
2668
2669 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
2670 if (ret < 0) {
2671 step = "commit";
2672 goto exit;
2673 }
Phil Burkbc991042017-02-24 08:06:44 -08002674
2675 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002676 ret = 0;
2677
2678 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
2679 __func__, info->shared_memory_address, info->buffer_size_frames);
2680
2681exit:
2682 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002683 if (out->pcm == NULL) {
2684 ALOGE("%s: %s - %d", __func__, step, ret);
2685 } else {
2686 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08002687 pcm_close(out->pcm);
2688 out->pcm = NULL;
2689 }
2690 }
2691 pthread_mutex_unlock(&adev->lock);
2692 return ret;
2693}
2694
2695static int out_get_mmap_position(const struct audio_stream_out *stream,
2696 struct audio_mmap_position *position)
2697{
2698 struct stream_out *out = (struct stream_out *)stream;
2699 ALOGVV("%s", __func__);
2700 if (position == NULL) {
2701 return -EINVAL;
2702 }
2703 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
2704 return -ENOSYS;
2705 }
2706 if (out->pcm == NULL) {
2707 return -ENOSYS;
2708 }
2709
2710 struct timespec ts = { 0, 0 };
2711 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
2712 if (ret < 0) {
2713 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2714 return ret;
2715 }
Andy Hungfc044e12017-03-20 09:24:22 -07002716 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002717 return 0;
2718}
2719
2720
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002721/** audio_stream_in implementation **/
2722static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2723{
2724 struct stream_in *in = (struct stream_in *)stream;
2725
2726 return in->config.rate;
2727}
2728
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002729static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002730{
2731 return -ENOSYS;
2732}
2733
2734static size_t in_get_buffer_size(const struct audio_stream *stream)
2735{
2736 struct stream_in *in = (struct stream_in *)stream;
2737
Haynes Mathew George03c40102016-01-29 17:57:48 -08002738 return in->config.period_size * in->af_period_multiplier *
2739 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002740}
2741
2742static uint32_t in_get_channels(const struct audio_stream *stream)
2743{
2744 struct stream_in *in = (struct stream_in *)stream;
2745
2746 return in->channel_mask;
2747}
2748
vivek mehta4ed66e62016-04-15 23:33:34 -07002749static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002750{
vivek mehta4ed66e62016-04-15 23:33:34 -07002751 struct stream_in *in = (struct stream_in *)stream;
2752 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002753}
2754
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002755static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002756{
2757 return -ENOSYS;
2758}
2759
2760static int in_standby(struct audio_stream *stream)
2761{
2762 struct stream_in *in = (struct stream_in *)stream;
2763 struct audio_device *adev = in->dev;
2764 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08002765 bool do_stop = true;
2766
Eric Laurent994a6932013-07-17 11:51:42 -07002767 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002768
2769 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002770
2771 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08002772 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002773 audio_extn_sound_trigger_stop_lab(in);
2774 in->standby = true;
2775 }
2776
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002777 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002778 if (adev->adm_deregister_stream)
2779 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2780
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002781 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002782 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002783 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002784 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002785 in->capture_started = false;
2786 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002787 if (in->pcm) {
2788 pcm_close(in->pcm);
2789 in->pcm = NULL;
2790 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002791 adev->enable_voicerx = false;
2792 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08002793 if (do_stop) {
2794 status = stop_input_stream(in);
2795 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002796 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002797 }
2798 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002799 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002800 return status;
2801}
2802
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002803static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002804{
2805 return 0;
2806}
2807
2808static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2809{
2810 struct stream_in *in = (struct stream_in *)stream;
2811 struct audio_device *adev = in->dev;
2812 struct str_parms *parms;
2813 char *str;
2814 char value[32];
2815 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07002816 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002817
Eric Laurent994a6932013-07-17 11:51:42 -07002818 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002819 parms = str_parms_create_str(kvpairs);
2820
2821 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2822
Eric Laurenta1478072015-09-21 17:21:52 -07002823 lock_input_stream(in);
2824
Eric Laurent150dbfe2013-02-27 14:31:02 -08002825 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002826 if (ret >= 0) {
2827 val = atoi(value);
2828 /* no audio source uses val == 0 */
2829 if ((in->source != val) && (val != 0)) {
2830 in->source = val;
2831 }
2832 }
2833
2834 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07002835
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002836 if (ret >= 0) {
2837 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002838 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002839 in->device = val;
2840 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002841 if (!in->standby) {
2842 ALOGV("update input routing change");
2843 in->routing_change = true;
2844 select_devices(adev, in->usecase);
2845 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002846 }
2847 }
2848
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002849 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002850 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002851
2852 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002853 ALOGV("%s: exit: status(%d)", __func__, status);
2854 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002855}
2856
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002857static char* in_get_parameters(const struct audio_stream *stream __unused,
2858 const char *keys __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002859{
2860 return strdup("");
2861}
2862
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002863static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002864{
2865 return 0;
2866}
2867
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002868static void in_snd_mon_cb(void * stream, struct str_parms * parms)
2869{
2870 if (!stream || !parms)
2871 return;
2872
2873 struct stream_in *in = (struct stream_in *)stream;
2874 struct audio_device *adev = in->dev;
2875
2876 card_status_t status;
2877 int card;
2878 if (parse_snd_card_status(parms, &card, &status) < 0)
2879 return;
2880
2881 pthread_mutex_lock(&adev->lock);
2882 bool valid_cb = (card == adev->snd_card);
2883 pthread_mutex_unlock(&adev->lock);
2884
2885 if (!valid_cb)
2886 return;
2887
2888 lock_input_stream(in);
2889 if (in->card_status != status)
2890 in->card_status = status;
2891 pthread_mutex_unlock(&in->lock);
2892
2893 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
2894 use_case_table[in->usecase],
2895 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2896
2897 // a better solution would be to report error back to AF and let
2898 // it put the stream to standby
2899 if (status == CARD_STATUS_OFFLINE)
2900 in_standby(&in->stream.common);
2901
2902 return;
2903}
2904
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002905static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2906 size_t bytes)
2907{
2908 struct stream_in *in = (struct stream_in *)stream;
2909 struct audio_device *adev = in->dev;
2910 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07002911 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002912
Eric Laurenta1478072015-09-21 17:21:52 -07002913 lock_input_stream(in);
2914
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002915 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002916 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002917 /* Read from sound trigger HAL */
2918 audio_extn_sound_trigger_read(in, buffer, bytes);
2919 pthread_mutex_unlock(&in->lock);
2920 return bytes;
2921 }
2922
Eric Laurent0e46adf2016-12-16 12:49:24 -08002923 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
2924 ret = -ENOSYS;
2925 goto exit;
2926 }
2927
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002928 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002929 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002930 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002931 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002932 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002933 goto exit;
2934 }
2935 in->standby = 0;
2936 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002937
Haynes Mathew George03c40102016-01-29 17:57:48 -08002938 //what's the duration requested by the client?
2939 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
2940 in->config.rate;
2941 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002942
Haynes Mathew George03c40102016-01-29 17:57:48 -08002943 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002944 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002945 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002946 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07002947 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002948 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002949 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002950 if (ret < 0) {
2951 ALOGE("Failed to read w/err %s", strerror(errno));
2952 ret = -errno;
2953 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002954 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
2955 if (bytes % 4 == 0) {
2956 /* data from DSP comes in 24_8 format, convert it to 8_24 */
2957 int_buf_stream = buffer;
2958 for (size_t itt=0; itt < bytes/4 ; itt++) {
2959 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07002960 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002961 } else {
2962 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
2963 ret = -EINVAL;
2964 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07002965 }
2966 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002967 }
2968
Haynes Mathew George03c40102016-01-29 17:57:48 -08002969 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002970
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002971 /*
2972 * Instead of writing zeroes here, we could trust the hardware
2973 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002974 * 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 -08002975 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002976 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002977 memset(buffer, 0, bytes);
2978
2979exit:
2980 pthread_mutex_unlock(&in->lock);
2981
2982 if (ret != 0) {
2983 in_standby(&in->stream.common);
2984 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Eric Laurentfdf296a2014-07-03 16:41:51 -07002985 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002986 in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08002987 memset(buffer, 0, bytes); // clear return data
2988 }
2989 if (bytes > 0) {
Andy Hung6ebe5962016-01-15 17:46:57 -08002990 in->frames_read += bytes / audio_stream_in_frame_size(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002991 }
2992 return bytes;
2993}
2994
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002995static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002996{
2997 return 0;
2998}
2999
Andy Hung6ebe5962016-01-15 17:46:57 -08003000static int in_get_capture_position(const struct audio_stream_in *stream,
3001 int64_t *frames, int64_t *time)
3002{
3003 if (stream == NULL || frames == NULL || time == NULL) {
3004 return -EINVAL;
3005 }
3006 struct stream_in *in = (struct stream_in *)stream;
3007 int ret = -ENOSYS;
3008
3009 lock_input_stream(in);
3010 if (in->pcm) {
3011 struct timespec timestamp;
3012 unsigned int avail;
3013 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3014 *frames = in->frames_read + avail;
3015 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3016 ret = 0;
3017 }
3018 }
3019 pthread_mutex_unlock(&in->lock);
3020 return ret;
3021}
3022
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003023static int add_remove_audio_effect(const struct audio_stream *stream,
3024 effect_handle_t effect,
3025 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003026{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003027 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003028 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003029 int status = 0;
3030 effect_descriptor_t desc;
3031
3032 status = (*effect)->get_descriptor(effect, &desc);
3033 if (status != 0)
3034 return status;
3035
Eric Laurenta1478072015-09-21 17:21:52 -07003036 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003037 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003038 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003039 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003040 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003041 in->enable_aec != enable &&
3042 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3043 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003044 if (!enable)
3045 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003046 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3047 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3048 adev->enable_voicerx = enable;
3049 struct audio_usecase *usecase;
3050 struct listnode *node;
3051 list_for_each(node, &adev->usecase_list) {
3052 usecase = node_to_item(node, struct audio_usecase, list);
3053 if (usecase->type == PCM_PLAYBACK) {
3054 select_devices(adev, usecase->id);
3055 break;
3056 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003057 }
3058 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003059 if (!in->standby)
3060 select_devices(in->dev, in->usecase);
3061 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003062 if (in->enable_ns != enable &&
3063 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3064 in->enable_ns = enable;
3065 if (!in->standby)
3066 select_devices(in->dev, in->usecase);
3067 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003068 pthread_mutex_unlock(&in->dev->lock);
3069 pthread_mutex_unlock(&in->lock);
3070
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003071 return 0;
3072}
3073
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003074static int in_add_audio_effect(const struct audio_stream *stream,
3075 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003076{
Eric Laurent994a6932013-07-17 11:51:42 -07003077 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003078 return add_remove_audio_effect(stream, effect, true);
3079}
3080
3081static int in_remove_audio_effect(const struct audio_stream *stream,
3082 effect_handle_t effect)
3083{
Eric Laurent994a6932013-07-17 11:51:42 -07003084 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003085 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003086}
3087
Eric Laurent0e46adf2016-12-16 12:49:24 -08003088static int in_stop(const struct audio_stream_in* stream)
3089{
3090 struct stream_in *in = (struct stream_in *)stream;
3091 struct audio_device *adev = in->dev;
3092
3093 int ret = -ENOSYS;
3094 ALOGV("%s", __func__);
3095 pthread_mutex_lock(&adev->lock);
3096 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3097 in->capture_started && in->pcm != NULL) {
3098 pcm_stop(in->pcm);
3099 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003100 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003101 }
3102 pthread_mutex_unlock(&adev->lock);
3103 return ret;
3104}
3105
3106static int in_start(const struct audio_stream_in* stream)
3107{
3108 struct stream_in *in = (struct stream_in *)stream;
3109 struct audio_device *adev = in->dev;
3110 int ret = -ENOSYS;
3111
3112 ALOGV("%s in %p", __func__, in);
3113 pthread_mutex_lock(&adev->lock);
3114 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3115 !in->capture_started && in->pcm != NULL) {
3116 if (!in->capture_started) {
3117 ret = start_input_stream(in);
3118 if (ret == 0) {
3119 in->capture_started = true;
3120 }
3121 }
3122 }
3123 pthread_mutex_unlock(&adev->lock);
3124 return ret;
3125}
3126
3127static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3128 int32_t min_size_frames,
3129 struct audio_mmap_buffer_info *info)
3130{
3131 struct stream_in *in = (struct stream_in *)stream;
3132 struct audio_device *adev = in->dev;
3133 int ret = 0;
3134 unsigned int offset1;
3135 unsigned int frames1;
3136 const char *step = "";
3137
3138 pthread_mutex_lock(&adev->lock);
3139 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003140
Eric Laurent0e46adf2016-12-16 12:49:24 -08003141 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003142 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003143 ret = -EINVAL;
3144 goto exit;
3145 }
3146 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003147 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003148 ALOGV("%s in %p", __func__, in);
3149 ret = -ENOSYS;
3150 goto exit;
3151 }
3152 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3153 if (in->pcm_device_id < 0) {
3154 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3155 __func__, in->pcm_device_id, in->usecase);
3156 ret = -EINVAL;
3157 goto exit;
3158 }
Phil Burkbc991042017-02-24 08:06:44 -08003159
3160 adjust_mmap_period_count(&in->config, min_size_frames);
3161
Eric Laurent0e46adf2016-12-16 12:49:24 -08003162 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3163 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3164 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3165 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3166 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3167 step = "open";
3168 ret = -ENODEV;
3169 goto exit;
3170 }
3171
3172 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3173 if (ret < 0) {
3174 step = "begin";
3175 goto exit;
3176 }
3177 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
3178 info->burst_size_frames = in->config.period_size;
3179 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3180
3181 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(in->pcm,
3182 info->buffer_size_frames));
3183
3184 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3185 if (ret < 0) {
3186 step = "commit";
3187 goto exit;
3188 }
3189
Phil Burkbc991042017-02-24 08:06:44 -08003190 in->standby = false;
3191 ret = 0;
3192
Eric Laurent0e46adf2016-12-16 12:49:24 -08003193 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3194 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003195
3196exit:
3197 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003198 if (in->pcm == NULL) {
3199 ALOGE("%s: %s - %d", __func__, step, ret);
3200 } else {
3201 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003202 pcm_close(in->pcm);
3203 in->pcm = NULL;
3204 }
3205 }
3206 pthread_mutex_unlock(&adev->lock);
3207 return ret;
3208}
3209
3210static int in_get_mmap_position(const struct audio_stream_in *stream,
3211 struct audio_mmap_position *position)
3212{
3213 struct stream_in *in = (struct stream_in *)stream;
3214 ALOGVV("%s", __func__);
3215 if (position == NULL) {
3216 return -EINVAL;
3217 }
3218 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
3219 return -ENOSYS;
3220 }
3221 if (in->pcm == NULL) {
3222 return -ENOSYS;
3223 }
3224 struct timespec ts = { 0, 0 };
3225 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
3226 if (ret < 0) {
3227 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3228 return ret;
3229 }
Andy Hungfc044e12017-03-20 09:24:22 -07003230 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003231 return 0;
3232}
3233
3234
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003235static int adev_open_output_stream(struct audio_hw_device *dev,
3236 audio_io_handle_t handle,
3237 audio_devices_t devices,
3238 audio_output_flags_t flags,
3239 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003240 struct audio_stream_out **stream_out,
3241 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003242{
3243 struct audio_device *adev = (struct audio_device *)dev;
3244 struct stream_out *out;
3245 int i, ret;
3246
Eric Laurent994a6932013-07-17 11:51:42 -07003247 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003248 __func__, config->sample_rate, config->channel_mask, devices, flags);
3249 *stream_out = NULL;
3250 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3251
3252 if (devices == AUDIO_DEVICE_NONE)
3253 devices = AUDIO_DEVICE_OUT_SPEAKER;
3254
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003255 out->flags = flags;
3256 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003257 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003258 out->format = config->format;
3259 out->sample_rate = config->sample_rate;
3260 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3261 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003262 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003263
3264 /* Init use case and pcm_config */
3265 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
Eric Laurent7f245042013-09-30 19:22:50 -07003266 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003267 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003268 pthread_mutex_lock(&adev->lock);
3269 ret = read_hdmi_channel_masks(out);
3270 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003271 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003272 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003273
3274 if (config->sample_rate == 0)
3275 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3276 if (config->channel_mask == 0)
3277 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Eric Laurentad1cec22015-12-16 10:12:27 -08003278 if (config->format == AUDIO_FORMAT_DEFAULT)
3279 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003280
3281 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003282 out->sample_rate = config->sample_rate;
Eric Laurentad1cec22015-12-16 10:12:27 -08003283 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003284 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3285 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003286 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003287 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003288 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003289 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003290 pthread_mutex_lock(&adev->lock);
3291 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3292 pthread_mutex_unlock(&adev->lock);
3293
3294 // reject offload during card offline to allow
3295 // fallback to s/w paths
3296 if (offline) {
3297 ret = -ENODEV;
3298 goto error_open;
3299 }
3300
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003301 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3302 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3303 ALOGE("%s: Unsupported Offload information", __func__);
3304 ret = -EINVAL;
3305 goto error_open;
3306 }
3307 if (!is_supported_format(config->offload_info.format)) {
3308 ALOGE("%s: Unsupported audio format", __func__);
3309 ret = -EINVAL;
3310 goto error_open;
3311 }
3312
3313 out->compr_config.codec = (struct snd_codec *)
3314 calloc(1, sizeof(struct snd_codec));
3315
3316 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3317 if (config->offload_info.channel_mask)
3318 out->channel_mask = config->offload_info.channel_mask;
3319 else if (config->channel_mask)
3320 out->channel_mask = config->channel_mask;
3321 out->format = config->offload_info.format;
3322 out->sample_rate = config->offload_info.sample_rate;
3323
3324 out->stream.set_callback = out_set_callback;
3325 out->stream.pause = out_pause;
3326 out->stream.resume = out_resume;
3327 out->stream.drain = out_drain;
3328 out->stream.flush = out_flush;
3329
3330 out->compr_config.codec->id =
3331 get_snd_codec_id(config->offload_info.format);
3332 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3333 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07003334 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003335 out->compr_config.codec->bit_rate =
3336 config->offload_info.bit_rate;
3337 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003338 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003339 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3340
3341 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3342 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003343
3344 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003345 create_offload_callback_thread(out);
3346 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3347 __func__, config->offload_info.version,
3348 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003349 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3350 if (config->sample_rate == 0)
3351 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3352 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3353 config->sample_rate != 8000) {
3354 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3355 ret = -EINVAL;
3356 goto error_open;
3357 }
3358 out->sample_rate = config->sample_rate;
3359 out->config.rate = config->sample_rate;
3360 if (config->format == AUDIO_FORMAT_DEFAULT)
3361 config->format = AUDIO_FORMAT_PCM_16_BIT;
3362 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3363 config->format = AUDIO_FORMAT_PCM_16_BIT;
3364 ret = -EINVAL;
3365 goto error_open;
3366 }
3367 out->format = config->format;
3368 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3369 out->config = pcm_config_afe_proxy_playback;
3370 adev->voice_tx_output = out;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003371 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003372 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3373 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3374 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003375 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
3376 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3377 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003378 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3379 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003380 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003381 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003382 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3383 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3384 out->config = pcm_config_mmap_playback;
3385 out->stream.start = out_start;
3386 out->stream.stop = out_stop;
3387 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3388 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003389 } else {
3390 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3391 out->config = pcm_config_low_latency;
3392 }
3393 if (config->format != audio_format_from_pcm_format(out->config.format)) {
3394 if (k_enable_extended_precision
3395 && pcm_params_format_test(adev->use_case_table[out->usecase],
3396 pcm_format_from_audio_format(config->format))) {
3397 out->config.format = pcm_format_from_audio_format(config->format);
3398 /* out->format already set to config->format */
3399 } else {
3400 /* deny the externally proposed config format
3401 * and use the one specified in audio_hw layer configuration.
3402 * Note: out->format is returned by out->stream.common.get_format()
3403 * and is used to set config->format in the code several lines below.
3404 */
3405 out->format = audio_format_from_pcm_format(out->config.format);
3406 }
3407 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003408 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003409 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07003410 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3411 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003412
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003413 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003414 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003415 adev->primary_output = out;
3416 else {
3417 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003418 ret = -EEXIST;
3419 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003420 }
3421 }
3422
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003423 /* Check if this usecase is already existing */
3424 pthread_mutex_lock(&adev->lock);
3425 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3426 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003427 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003428 ret = -EEXIST;
3429 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003430 }
3431 pthread_mutex_unlock(&adev->lock);
3432
3433 out->stream.common.get_sample_rate = out_get_sample_rate;
3434 out->stream.common.set_sample_rate = out_set_sample_rate;
3435 out->stream.common.get_buffer_size = out_get_buffer_size;
3436 out->stream.common.get_channels = out_get_channels;
3437 out->stream.common.get_format = out_get_format;
3438 out->stream.common.set_format = out_set_format;
3439 out->stream.common.standby = out_standby;
3440 out->stream.common.dump = out_dump;
3441 out->stream.common.set_parameters = out_set_parameters;
3442 out->stream.common.get_parameters = out_get_parameters;
3443 out->stream.common.add_audio_effect = out_add_audio_effect;
3444 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3445 out->stream.get_latency = out_get_latency;
3446 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003447#ifdef NO_AUDIO_OUT
3448 out->stream.write = out_write_for_no_output;
3449#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003450 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003451#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003452 out->stream.get_render_position = out_get_render_position;
3453 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003454 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003455
Eric Laurent0e46adf2016-12-16 12:49:24 -08003456 if (out->realtime)
3457 out->af_period_multiplier = af_period_multiplier;
3458 else
3459 out->af_period_multiplier = 1;
3460
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003461 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003462 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003463 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003464
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003465 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003466 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003467 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3468
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003469 config->format = out->stream.common.get_format(&out->stream.common);
3470 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3471 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3472
Andy Hungfc044e12017-03-20 09:24:22 -07003473 const size_t POWER_LOG_FRAMES_PER_ENTRY =
3474 config->sample_rate * POWER_LOG_SAMPLING_INTERVAL_MS / 1000;
3475 // power_log may be null if the format is not supported
3476 out->power_log = power_log_create(
3477 config->sample_rate,
3478 audio_channel_count_from_out_mask(config->channel_mask),
3479 config->format,
3480 POWER_LOG_ENTRIES,
3481 POWER_LOG_FRAMES_PER_ENTRY);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003482
3483 /*
3484 By locking output stream before registering, we allow the callback
3485 to update stream's state only after stream's initial state is set to
3486 adev state.
3487 */
3488 lock_output_stream(out);
3489 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3490 pthread_mutex_lock(&adev->lock);
3491 out->card_status = adev->card_status;
3492 pthread_mutex_unlock(&adev->lock);
3493 pthread_mutex_unlock(&out->lock);
3494
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003495 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003496
Eric Laurent994a6932013-07-17 11:51:42 -07003497 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003498 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003499
3500error_open:
3501 free(out);
3502 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003503 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003504 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003505}
3506
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003507static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003508 struct audio_stream_out *stream)
3509{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003510 struct stream_out *out = (struct stream_out *)stream;
3511 struct audio_device *adev = out->dev;
3512
Eric Laurent994a6932013-07-17 11:51:42 -07003513 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003514
3515 // must deregister from sndmonitor first to prevent races
3516 // between the callback and close_stream
3517 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003518 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003519 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3520 destroy_offload_callback_thread(out);
3521
3522 if (out->compr_config.codec != NULL)
3523 free(out->compr_config.codec);
3524 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003525
3526 if (adev->voice_tx_output == out)
3527 adev->voice_tx_output = NULL;
3528
Andy Hungfc044e12017-03-20 09:24:22 -07003529 power_log_destroy(out->power_log);
3530 out->power_log = NULL;
3531
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003532 pthread_cond_destroy(&out->cond);
3533 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003534 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003535 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003536}
3537
3538static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3539{
3540 struct audio_device *adev = (struct audio_device *)dev;
3541 struct str_parms *parms;
3542 char *str;
3543 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003544 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003545 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003546 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003547
Joe Onorato188b6222016-03-01 11:02:27 -08003548 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003549
3550 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003551
3552 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003553 status = voice_set_parameters(adev, parms);
3554 if (status != 0) {
3555 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003556 }
3557
3558 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3559 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003560 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003561 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3562 adev->bluetooth_nrec = true;
3563 else
3564 adev->bluetooth_nrec = false;
3565 }
3566
3567 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3568 if (ret >= 0) {
3569 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3570 adev->screen_off = false;
3571 else
3572 adev->screen_off = true;
3573 }
3574
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003575 ret = str_parms_get_int(parms, "rotation", &val);
3576 if (ret >= 0) {
3577 bool reverse_speakers = false;
3578 switch(val) {
3579 // FIXME: note that the code below assumes that the speakers are in the correct placement
3580 // relative to the user when the device is rotated 90deg from its default rotation. This
3581 // assumption is device-specific, not platform-specific like this code.
3582 case 270:
3583 reverse_speakers = true;
3584 break;
3585 case 0:
3586 case 90:
3587 case 180:
3588 break;
3589 default:
3590 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003591 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003592 }
Eric Laurent03f09432014-03-25 18:09:11 -07003593 if (status == 0) {
Ravi Kumar Alamanda1f60cf82015-04-23 19:45:17 -07003594 platform_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003595 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003596 }
3597
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003598 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3599 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003600 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003601 }
3602
David Linee3fe402017-03-13 10:00:42 -07003603 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3604 if (ret >= 0) {
3605 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
3606 if (device == AUDIO_DEVICE_OUT_USB_DEVICE) {
3607 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3608 if (ret >= 0) {
3609 const int card = atoi(value);
3610 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, card);
3611 }
3612 } else if (device == AUDIO_DEVICE_IN_USB_DEVICE) {
3613 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3614 if (ret >= 0) {
3615 const int card = atoi(value);
3616 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, card);
3617 }
3618 }
3619 }
3620
3621 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3622 if (ret >= 0) {
3623 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
3624 if (device == AUDIO_DEVICE_OUT_USB_DEVICE) {
3625 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3626 if (ret >= 0) {
3627 const int card = atoi(value);
3628
3629 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, card);
3630 }
3631 } else if (device == AUDIO_DEVICE_IN_USB_DEVICE) {
3632 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3633 if (ret >= 0) {
3634 const int card = atoi(value);
3635 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, card);
3636 }
3637 }
3638 }
3639
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08003640 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003641done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003642 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003643 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07003644 ALOGV("%s: exit with code(%d)", __func__, status);
3645 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003646}
3647
3648static char* adev_get_parameters(const struct audio_hw_device *dev,
3649 const char *keys)
3650{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003651 struct audio_device *adev = (struct audio_device *)dev;
3652 struct str_parms *reply = str_parms_create();
3653 struct str_parms *query = str_parms_create_str(keys);
3654 char *str;
3655
3656 pthread_mutex_lock(&adev->lock);
3657
3658 voice_get_parameters(adev, query, reply);
3659 str = str_parms_to_str(reply);
3660 str_parms_destroy(query);
3661 str_parms_destroy(reply);
3662
3663 pthread_mutex_unlock(&adev->lock);
3664 ALOGV("%s: exit: returns - %s", __func__, str);
3665 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003666}
3667
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003668static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003669{
3670 return 0;
3671}
3672
Haynes Mathew George5191a852013-09-11 14:19:36 -07003673static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3674{
3675 int ret;
3676 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003677
Eric Laurent4cc4ce12014-09-10 13:21:01 -05003678 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
3679
Haynes Mathew George5191a852013-09-11 14:19:36 -07003680 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003681 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003682 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003683
Haynes Mathew George5191a852013-09-11 14:19:36 -07003684 return ret;
3685}
3686
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003687static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003688{
3689 return -ENOSYS;
3690}
3691
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003692static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3693 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003694{
3695 return -ENOSYS;
3696}
3697
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003698static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003699{
3700 return -ENOSYS;
3701}
3702
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003703static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003704{
3705 return -ENOSYS;
3706}
3707
3708static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3709{
3710 struct audio_device *adev = (struct audio_device *)dev;
3711
3712 pthread_mutex_lock(&adev->lock);
3713 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07003714 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003715 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07003716 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3717 voice_is_in_call(adev)) {
3718 voice_stop_call(adev);
3719 adev->current_call_output = NULL;
3720 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003721 }
3722 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003723
3724 audio_extn_extspk_set_mode(adev->extspk, mode);
3725
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003726 return 0;
3727}
3728
3729static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3730{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003731 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003732 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003733
Eric Laurent2bafff12016-03-17 12:17:23 -07003734 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003735 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08003736 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
3737 ret = audio_extn_hfp_set_mic_mute(adev, state);
3738 } else {
3739 ret = voice_set_mic_mute(adev, state);
3740 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003741 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00003742 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003743
3744 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003745}
3746
3747static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3748{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003749 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003750 return 0;
3751}
3752
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003753static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003754 const struct audio_config *config)
3755{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003756 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003757
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003758 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3759 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003760}
3761
3762static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003763 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003764 audio_devices_t devices,
3765 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003766 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07003767 audio_input_flags_t flags,
3768 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05003769 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003770{
3771 struct audio_device *adev = (struct audio_device *)dev;
3772 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003773 int ret = 0, buffer_size, frame_size;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003774 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003775 bool is_low_latency = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003776
Eric Laurent994a6932013-07-17 11:51:42 -07003777 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003778 *stream_in = NULL;
3779 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3780 return -EINVAL;
3781
Zheng Zhang6185d572016-12-01 20:35:17 +08003782 if (audio_extn_tfa_98xx_is_supported() && (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08003783 return -EINVAL;
3784
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003785 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
3786
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003787 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003788 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003789
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003790 in->stream.common.get_sample_rate = in_get_sample_rate;
3791 in->stream.common.set_sample_rate = in_set_sample_rate;
3792 in->stream.common.get_buffer_size = in_get_buffer_size;
3793 in->stream.common.get_channels = in_get_channels;
3794 in->stream.common.get_format = in_get_format;
3795 in->stream.common.set_format = in_set_format;
3796 in->stream.common.standby = in_standby;
3797 in->stream.common.dump = in_dump;
3798 in->stream.common.set_parameters = in_set_parameters;
3799 in->stream.common.get_parameters = in_get_parameters;
3800 in->stream.common.add_audio_effect = in_add_audio_effect;
3801 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3802 in->stream.set_gain = in_set_gain;
3803 in->stream.read = in_read;
3804 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08003805 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003806
3807 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003808 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003809 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003810 in->standby = 1;
3811 in->channel_mask = config->channel_mask;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003812 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003813 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003814
vivek mehta57ff9b52016-04-28 14:13:08 -07003815 // restrict 24 bit capture for unprocessed source only
3816 // for other sources if 24 bit requested reject 24 and set 16 bit capture only
3817 if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07003818 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07003819 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
3820 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
3821 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
3822 bool ret_error = false;
3823 /* 24 bit is restricted to UNPROCESSED source only,also format supported
3824 from HAL is 8_24
3825 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
3826 8_24 return error indicating supported format is 8_24
3827 *> In case of any other source requesting 24 bit or float return error
3828 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07003829
vivek mehta57ff9b52016-04-28 14:13:08 -07003830 on error flinger will retry with supported format passed
3831 */
3832 if (source != AUDIO_SOURCE_UNPROCESSED) {
3833 config->format = AUDIO_FORMAT_PCM_16_BIT;
3834 ret_error = true;
3835 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
3836 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
3837 ret_error = true;
3838 }
3839
3840 if (ret_error) {
3841 ret = -EINVAL;
3842 goto err_open;
3843 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003844 }
3845
vivek mehta57ff9b52016-04-28 14:13:08 -07003846 in->format = config->format;
3847
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003848 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003849 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
3850 if (config->sample_rate == 0)
3851 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3852 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3853 config->sample_rate != 8000) {
3854 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3855 ret = -EINVAL;
3856 goto err_open;
3857 }
vivek mehta4ed66e62016-04-15 23:33:34 -07003858
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003859 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3860 config->format = AUDIO_FORMAT_PCM_16_BIT;
3861 ret = -EINVAL;
3862 goto err_open;
3863 }
3864
3865 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3866 in->config = pcm_config_afe_proxy_record;
3867 } else {
3868 in->usecase = USECASE_AUDIO_RECORD;
3869 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08003870 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003871 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07003872#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003873 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07003874#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08003875 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003876 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08003877 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003878 frame_size = audio_stream_in_frame_size(&in->stream);
3879 buffer_size = get_input_buffer_size(config->sample_rate,
3880 config->format,
3881 channel_count,
3882 is_low_latency);
3883 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003884 in->config.rate = config->sample_rate;
3885 in->af_period_multiplier = 1;
3886 } else {
3887 // period size is left untouched for rt mode playback
3888 in->config = pcm_config_audio_capture_rt;
3889 in->af_period_multiplier = af_period_multiplier;
3890 }
3891 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
3892 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
3893 in->usecase = USECASE_AUDIO_RECORD_MMAP;
3894 in->config = pcm_config_mmap_capture;
3895 in->stream.start = in_start;
3896 in->stream.stop = in_stop;
3897 in->stream.create_mmap_buffer = in_create_mmap_buffer;
3898 in->stream.get_mmap_position = in_get_mmap_position;
3899 in->af_period_multiplier = 1;
3900 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
3901 } else {
3902 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003903 frame_size = audio_stream_in_frame_size(&in->stream);
3904 buffer_size = get_input_buffer_size(config->sample_rate,
3905 config->format,
3906 channel_count,
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003907 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003908 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003909 in->config.rate = config->sample_rate;
3910 in->af_period_multiplier = 1;
3911 }
3912 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
3913 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07003914 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003915
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003916 in->config.channels = channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003917
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003918 /* This stream could be for sound trigger lab,
3919 get sound trigger pcm if present */
3920 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003921
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003922 lock_input_stream(in);
3923 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
3924 pthread_mutex_lock(&adev->lock);
3925 in->card_status = adev->card_status;
3926 pthread_mutex_unlock(&adev->lock);
3927 pthread_mutex_unlock(&in->lock);
3928
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003929 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003930 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003931 return 0;
3932
3933err_open:
3934 free(in);
3935 *stream_in = NULL;
3936 return ret;
3937}
3938
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003939static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003940 struct audio_stream_in *stream)
3941{
Eric Laurent994a6932013-07-17 11:51:42 -07003942 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003943
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003944 // must deregister from sndmonitor first to prevent races
3945 // between the callback and close_stream
3946 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003947 in_standby(&stream->common);
3948 free(stream);
3949
3950 return;
3951}
3952
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003953static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003954{
3955 return 0;
3956}
3957
Andy Hung31aca912014-03-20 17:14:59 -07003958/* verifies input and output devices and their capabilities.
3959 *
3960 * This verification is required when enabling extended bit-depth or
3961 * sampling rates, as not all qcom products support it.
3962 *
3963 * Suitable for calling only on initialization such as adev_open().
3964 * It fills the audio_device use_case_table[] array.
3965 *
3966 * Has a side-effect that it needs to configure audio routing / devices
3967 * in order to power up the devices and read the device parameters.
3968 * It does not acquire any hw device lock. Should restore the devices
3969 * back to "normal state" upon completion.
3970 */
3971static int adev_verify_devices(struct audio_device *adev)
3972{
3973 /* enumeration is a bit difficult because one really wants to pull
3974 * the use_case, device id, etc from the hidden pcm_device_table[].
3975 * In this case there are the following use cases and device ids.
3976 *
3977 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
3978 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
3979 * [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
3980 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
3981 * [USECASE_AUDIO_RECORD] = {0, 0},
3982 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
3983 * [USECASE_VOICE_CALL] = {2, 2},
3984 *
3985 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_MULTI_CH omitted.
3986 * USECASE_VOICE_CALL omitted, but possible for either input or output.
3987 */
3988
3989 /* should be the usecases enabled in adev_open_input_stream() */
3990 static const int test_in_usecases[] = {
3991 USECASE_AUDIO_RECORD,
3992 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
3993 };
3994 /* should be the usecases enabled in adev_open_output_stream()*/
3995 static const int test_out_usecases[] = {
3996 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
3997 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
3998 };
3999 static const usecase_type_t usecase_type_by_dir[] = {
4000 PCM_PLAYBACK,
4001 PCM_CAPTURE,
4002 };
4003 static const unsigned flags_by_dir[] = {
4004 PCM_OUT,
4005 PCM_IN,
4006 };
4007
4008 size_t i;
4009 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004010 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07004011 char info[512]; /* for possible debug info */
4012
4013 for (dir = 0; dir < 2; ++dir) {
4014 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
4015 const unsigned flags_dir = flags_by_dir[dir];
4016 const size_t testsize =
4017 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
4018 const int *testcases =
4019 dir ? test_in_usecases : test_out_usecases;
4020 const audio_devices_t audio_device =
4021 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
4022
4023 for (i = 0; i < testsize; ++i) {
4024 const audio_usecase_t audio_usecase = testcases[i];
4025 int device_id;
4026 snd_device_t snd_device;
4027 struct pcm_params **pparams;
4028 struct stream_out out;
4029 struct stream_in in;
4030 struct audio_usecase uc_info;
4031 int retval;
4032
4033 pparams = &adev->use_case_table[audio_usecase];
4034 pcm_params_free(*pparams); /* can accept null input */
4035 *pparams = NULL;
4036
4037 /* find the device ID for the use case (signed, for error) */
4038 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
4039 if (device_id < 0)
4040 continue;
4041
4042 /* prepare structures for device probing */
4043 memset(&uc_info, 0, sizeof(uc_info));
4044 uc_info.id = audio_usecase;
4045 uc_info.type = usecase_type;
4046 if (dir) {
4047 adev->active_input = &in;
4048 memset(&in, 0, sizeof(in));
4049 in.device = audio_device;
4050 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4051 uc_info.stream.in = &in;
4052 } else {
4053 adev->active_input = NULL;
4054 }
4055 memset(&out, 0, sizeof(out));
4056 out.devices = audio_device; /* only field needed in select_devices */
4057 uc_info.stream.out = &out;
4058 uc_info.devices = audio_device;
4059 uc_info.in_snd_device = SND_DEVICE_NONE;
4060 uc_info.out_snd_device = SND_DEVICE_NONE;
4061 list_add_tail(&adev->usecase_list, &uc_info.list);
4062
4063 /* select device - similar to start_(in/out)put_stream() */
4064 retval = select_devices(adev, audio_usecase);
4065 if (retval >= 0) {
4066 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4067#if LOG_NDEBUG == 0
4068 if (*pparams) {
4069 ALOGV("%s: (%s) card %d device %d", __func__,
4070 dir ? "input" : "output", card_id, device_id);
4071 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004072 } else {
4073 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4074 }
4075#endif
4076 }
4077
4078 /* deselect device - similar to stop_(in/out)put_stream() */
4079 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004080 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004081 /* 2. Disable the rx device */
4082 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004083 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004084 list_remove(&uc_info.list);
4085 }
4086 }
4087 adev->active_input = NULL; /* restore adev state */
4088 return 0;
4089}
4090
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004091static int adev_close(hw_device_t *device)
4092{
Andy Hung31aca912014-03-20 17:14:59 -07004093 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004094 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004095
4096 if (!adev)
4097 return 0;
4098
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004099 audio_extn_tfa_98xx_deinit();
4100
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004101 audio_extn_snd_mon_unregister_listener(adev);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004102 pthread_mutex_lock(&adev_init_lock);
4103
4104 if ((--audio_device_ref_count) == 0) {
4105 audio_route_free(adev->audio_route);
4106 free(adev->snd_dev_ref_cnt);
4107 platform_deinit(adev->platform);
4108 audio_extn_extspk_deinit(adev->extspk);
4109 audio_extn_sound_trigger_deinit(adev);
4110 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4111 pcm_params_free(adev->use_case_table[i]);
4112 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004113 if (adev->adm_deinit)
4114 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004115 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004116 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004117
4118 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004119
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004120 return 0;
4121}
4122
Glenn Kasten4f993392014-05-14 07:30:48 -07004123/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4124 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4125 * just that it _might_ work.
4126 */
4127static int period_size_is_plausible_for_low_latency(int period_size)
4128{
4129 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004130 case 48:
4131 case 96:
4132 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004133 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004134 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004135 case 240:
4136 case 320:
4137 case 480:
4138 return 1;
4139 default:
4140 return 0;
4141 }
4142}
4143
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004144static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4145{
4146 int card;
4147 card_status_t status;
4148
4149 if (!parms)
4150 return;
4151
4152 if (parse_snd_card_status(parms, &card, &status) < 0)
4153 return;
4154
4155 pthread_mutex_lock(&adev->lock);
4156 bool valid_cb = (card == adev->snd_card);
4157 if (valid_cb) {
4158 if (adev->card_status != status) {
4159 adev->card_status = status;
4160 platform_snd_card_update(adev->platform, status);
4161 }
4162 }
4163 pthread_mutex_unlock(&adev->lock);
4164 return;
4165}
4166
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004167static int adev_open(const hw_module_t *module, const char *name,
4168 hw_device_t **device)
4169{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004170 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004171
Eric Laurent2bafff12016-03-17 12:17:23 -07004172 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004173 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004174 pthread_mutex_lock(&adev_init_lock);
4175 if (audio_device_ref_count != 0) {
4176 *device = &adev->device.common;
4177 audio_device_ref_count++;
4178 ALOGV("%s: returning existing instance of adev", __func__);
4179 ALOGV("%s: exit", __func__);
4180 pthread_mutex_unlock(&adev_init_lock);
4181 return 0;
4182 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004183 adev = calloc(1, sizeof(struct audio_device));
4184
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004185 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4186
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004187 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4188 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4189 adev->device.common.module = (struct hw_module_t *)module;
4190 adev->device.common.close = adev_close;
4191
4192 adev->device.init_check = adev_init_check;
4193 adev->device.set_voice_volume = adev_set_voice_volume;
4194 adev->device.set_master_volume = adev_set_master_volume;
4195 adev->device.get_master_volume = adev_get_master_volume;
4196 adev->device.set_master_mute = adev_set_master_mute;
4197 adev->device.get_master_mute = adev_get_master_mute;
4198 adev->device.set_mode = adev_set_mode;
4199 adev->device.set_mic_mute = adev_set_mic_mute;
4200 adev->device.get_mic_mute = adev_get_mic_mute;
4201 adev->device.set_parameters = adev_set_parameters;
4202 adev->device.get_parameters = adev_get_parameters;
4203 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4204 adev->device.open_output_stream = adev_open_output_stream;
4205 adev->device.close_output_stream = adev_close_output_stream;
4206 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004207
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004208 adev->device.close_input_stream = adev_close_input_stream;
4209 adev->device.dump = adev_dump;
4210
4211 /* Set the default route before the PCM stream is opened */
4212 pthread_mutex_lock(&adev->lock);
4213 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004214 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004215 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004216 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004217 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004218 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004219 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004220 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004221 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004222 pthread_mutex_unlock(&adev->lock);
4223
4224 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004225 adev->platform = platform_init(adev);
4226 if (!adev->platform) {
4227 free(adev->snd_dev_ref_cnt);
4228 free(adev);
4229 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4230 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004231 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004232 return -EINVAL;
4233 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05004234 adev->extspk = audio_extn_extspk_init(adev);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004235 audio_extn_sound_trigger_init(adev);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004236
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004237 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4238 if (adev->visualizer_lib == NULL) {
4239 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4240 } else {
4241 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4242 adev->visualizer_start_output =
4243 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4244 "visualizer_hal_start_output");
4245 adev->visualizer_stop_output =
4246 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4247 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07004248 }
4249
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004250 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4251 if (adev->offload_effects_lib == NULL) {
4252 ALOGW("%s: DLOPEN failed for %s", __func__,
4253 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4254 } else {
4255 ALOGV("%s: DLOPEN successful for %s", __func__,
4256 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4257 adev->offload_effects_start_output =
4258 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4259 "offload_effects_bundle_hal_start_output");
4260 adev->offload_effects_stop_output =
4261 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4262 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07004263 }
4264
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004265 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4266 if (adev->adm_lib == NULL) {
4267 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4268 } else {
4269 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4270 adev->adm_init = (adm_init_t)
4271 dlsym(adev->adm_lib, "adm_init");
4272 adev->adm_deinit = (adm_deinit_t)
4273 dlsym(adev->adm_lib, "adm_deinit");
4274 adev->adm_register_input_stream = (adm_register_input_stream_t)
4275 dlsym(adev->adm_lib, "adm_register_input_stream");
4276 adev->adm_register_output_stream = (adm_register_output_stream_t)
4277 dlsym(adev->adm_lib, "adm_register_output_stream");
4278 adev->adm_deregister_stream = (adm_deregister_stream_t)
4279 dlsym(adev->adm_lib, "adm_deregister_stream");
4280 adev->adm_request_focus = (adm_request_focus_t)
4281 dlsym(adev->adm_lib, "adm_request_focus");
4282 adev->adm_abandon_focus = (adm_abandon_focus_t)
4283 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08004284 adev->adm_set_config = (adm_set_config_t)
4285 dlsym(adev->adm_lib, "adm_set_config");
4286 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4287 dlsym(adev->adm_lib, "adm_request_focus_v2");
4288 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4289 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4290 adev->adm_on_routing_change = (adm_on_routing_change_t)
4291 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004292 }
4293
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004294 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004295 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004296
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004297 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004298
Andy Hung31aca912014-03-20 17:14:59 -07004299 if (k_enable_extended_precision)
4300 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004301
Glenn Kasten4f993392014-05-14 07:30:48 -07004302 char value[PROPERTY_VALUE_MAX];
4303 int trial;
4304 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4305 trial = atoi(value);
4306 if (period_size_is_plausible_for_low_latency(trial)) {
4307 pcm_config_low_latency.period_size = trial;
4308 pcm_config_low_latency.start_threshold = trial / 4;
4309 pcm_config_low_latency.avail_min = trial / 4;
4310 configured_low_latency_capture_period_size = trial;
4311 }
4312 }
4313 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4314 trial = atoi(value);
4315 if (period_size_is_plausible_for_low_latency(trial)) {
4316 configured_low_latency_capture_period_size = trial;
4317 }
4318 }
4319
Yamit Mehtae3b99562016-09-16 22:44:00 +05304320 audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004321 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004322
4323 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4324 af_period_multiplier = atoi(value);
4325 if (af_period_multiplier < 0) {
4326 af_period_multiplier = 2;
4327 } else if (af_period_multiplier > 4) {
4328 af_period_multiplier = 4;
4329 }
4330 ALOGV("new period_multiplier = %d", af_period_multiplier);
4331 }
4332
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004333 audio_extn_tfa_98xx_init(adev);
4334
vivek mehta1a9b7c02015-06-25 11:49:38 -07004335 pthread_mutex_unlock(&adev_init_lock);
4336
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004337 if (adev->adm_init)
4338 adev->adm_data = adev->adm_init();
4339
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004340 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004341 audio_extn_snd_mon_init();
4342 pthread_mutex_lock(&adev->lock);
4343 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
4344 adev->card_status = CARD_STATUS_ONLINE;
4345 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004346
Eric Laurent2bafff12016-03-17 12:17:23 -07004347 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004348 return 0;
4349}
4350
4351static struct hw_module_methods_t hal_module_methods = {
4352 .open = adev_open,
4353};
4354
4355struct audio_module HAL_MODULE_INFO_SYM = {
4356 .common = {
4357 .tag = HARDWARE_MODULE_TAG,
4358 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4359 .hal_api_version = HARDWARE_HAL_API_VERSION,
4360 .id = AUDIO_HARDWARE_MODULE_ID,
4361 .name = "QCOM Audio HAL",
4362 .author = "Code Aurora Forum",
4363 .methods = &hal_module_methods,
4364 },
4365};