blob: c4e7717dfa652ae0441fd2c8b2a09ca4c1784043 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
vivek mehtaa51fd402016-02-04 19:49:33 -08002 * Copyright (C) 2013-2016 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "audio_hw_primary"
Haynes Mathew George03c40102016-01-29 17:57:48 -080018#define ATRACE_TAG ATRACE_TAG_AUDIO
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080019/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070020/*#define VERY_VERY_VERBOSE_LOGGING*/
21#ifdef VERY_VERY_VERBOSE_LOGGING
22#define ALOGVV ALOGV
23#else
24#define ALOGVV(a...) do { } while(0)
25#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080026
27#include <errno.h>
28#include <pthread.h>
29#include <stdint.h>
30#include <sys/time.h>
31#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080032#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070033#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070034#include <sys/resource.h>
35#include <sys/prctl.h>
Kevin Rocardb5c28192017-05-02 15:30:20 -070036#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080037
38#include <cutils/log.h>
Haynes Mathew George03c40102016-01-29 17:57:48 -080039#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040#include <cutils/str_parms.h>
41#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070042#include <cutils/atomic.h>
43#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080044
Eric Laurentb23d5282013-05-14 15:27:20 -070045#include <hardware/audio_effect.h>
Andy Hung31aca912014-03-20 17:14:59 -070046#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070047#include <system/thread_defs.h>
Phil Burkbc991042017-02-24 08:06:44 -080048#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070049#include <audio_effects/effect_aec.h>
50#include <audio_effects/effect_ns.h>
Andy Hungfc044e12017-03-20 09:24:22 -070051#include <audio_utils/clock.h>
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
vivek mehta4a824772017-06-08 19:05:49 -070068/* treat as unsigned Q1.13 */
69#define APP_TYPE_GAIN_DEFAULT 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070070#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
vivek mehta4a824772017-06-08 19:05:49 -070071
72/* treat as unsigned Q1.13 */
vivek mehtaa68fea62017-06-08 19:04:02 -070073#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070074
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070075#define PROXY_OPEN_RETRY_COUNT 100
76#define PROXY_OPEN_WAIT_TIME 20
77
vivek mehtadae44712015-07-27 14:13:18 -070078#define MIN_CHANNEL_COUNT 1
79#define DEFAULT_CHANNEL_COUNT 2
80
Jean-Michel Trivic0750692015-10-12 12:12:32 -070081#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
82#define MAX_CHANNEL_COUNT 1
83#else
vivek mehtadae44712015-07-27 14:13:18 -070084#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
85#define XSTR(x) STR(x)
86#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070087#endif
Eric Laurent74b55762017-07-09 17:04:53 -070088#define MAX_HIFI_CHANNEL_COUNT 8
vivek mehtadae44712015-07-27 14:13:18 -070089
Haynes Mathew George03c40102016-01-29 17:57:48 -080090#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
91
Glenn Kasten4f993392014-05-14 07:30:48 -070092static unsigned int configured_low_latency_capture_period_size =
93 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
94
Eric Laurent0e46adf2016-12-16 12:49:24 -080095
96#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Phil Burkbc991042017-02-24 08:06:44 -080097#define MMAP_PERIOD_COUNT_MIN 32
98#define MMAP_PERIOD_COUNT_MAX 512
99#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
Eric Laurent0e46adf2016-12-16 12:49:24 -0800100
Andy Hungd13f0d32017-06-12 13:58:37 -0700101static const int64_t NANOS_PER_SECOND = 1000000000;
Eric Laurent0e46adf2016-12-16 12:49:24 -0800102
Andy Hung31aca912014-03-20 17:14:59 -0700103/* This constant enables extended precision handling.
104 * TODO The flag is off until more testing is done.
105 */
106static const bool k_enable_extended_precision = false;
107
Eric Laurentb23d5282013-05-14 15:27:20 -0700108struct pcm_config pcm_config_deep_buffer = {
vivek mehtadae44712015-07-27 14:13:18 -0700109 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700110 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
111 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
112 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
113 .format = PCM_FORMAT_S16_LE,
114 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
115 .stop_threshold = INT_MAX,
116 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
117};
118
119struct pcm_config pcm_config_low_latency = {
vivek mehtadae44712015-07-27 14:13:18 -0700120 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700121 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
122 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
123 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
124 .format = PCM_FORMAT_S16_LE,
125 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
126 .stop_threshold = INT_MAX,
127 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
128};
129
Haynes Mathew George03c40102016-01-29 17:57:48 -0800130static int af_period_multiplier = 4;
131struct pcm_config pcm_config_rt = {
132 .channels = DEFAULT_CHANNEL_COUNT,
133 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
134 .period_size = ULL_PERIOD_SIZE, //1 ms
135 .period_count = 512, //=> buffer size is 512ms
136 .format = PCM_FORMAT_S16_LE,
137 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
138 .stop_threshold = INT_MAX,
139 .silence_threshold = 0,
140 .silence_size = 0,
141 .avail_min = ULL_PERIOD_SIZE, //1 ms
142};
143
Eric Laurentb23d5282013-05-14 15:27:20 -0700144struct pcm_config pcm_config_hdmi_multi = {
145 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
146 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
147 .period_size = HDMI_MULTI_PERIOD_SIZE,
148 .period_count = HDMI_MULTI_PERIOD_COUNT,
149 .format = PCM_FORMAT_S16_LE,
150 .start_threshold = 0,
151 .stop_threshold = INT_MAX,
152 .avail_min = 0,
153};
154
Eric Laurent0e46adf2016-12-16 12:49:24 -0800155struct pcm_config pcm_config_mmap_playback = {
156 .channels = DEFAULT_CHANNEL_COUNT,
157 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
158 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800159 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800160 .format = PCM_FORMAT_S16_LE,
161 .start_threshold = MMAP_PERIOD_SIZE*8,
162 .stop_threshold = INT32_MAX,
163 .silence_threshold = 0,
164 .silence_size = 0,
165 .avail_min = MMAP_PERIOD_SIZE, //1 ms
166};
167
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800168struct pcm_config pcm_config_hifi = {
169 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
170 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
171 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
172 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
173 .format = PCM_FORMAT_S24_3LE,
174 .start_threshold = 0,
175 .stop_threshold = INT_MAX,
176 .avail_min = 0,
177};
178
Eric Laurentb23d5282013-05-14 15:27:20 -0700179struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700180 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700181 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
182 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700183 .stop_threshold = INT_MAX,
184 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700185};
186
Haynes Mathew George03c40102016-01-29 17:57:48 -0800187struct pcm_config pcm_config_audio_capture_rt = {
188 .channels = DEFAULT_CHANNEL_COUNT,
189 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
190 .period_size = ULL_PERIOD_SIZE,
191 .period_count = 512,
192 .format = PCM_FORMAT_S16_LE,
193 .start_threshold = 0,
194 .stop_threshold = INT_MAX,
195 .silence_threshold = 0,
196 .silence_size = 0,
197 .avail_min = ULL_PERIOD_SIZE, //1 ms
198};
199
Eric Laurent0e46adf2016-12-16 12:49:24 -0800200struct pcm_config pcm_config_mmap_capture = {
201 .channels = DEFAULT_CHANNEL_COUNT,
202 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
203 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800204 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800205 .format = PCM_FORMAT_S16_LE,
206 .start_threshold = 0,
207 .stop_threshold = INT_MAX,
208 .silence_threshold = 0,
209 .silence_size = 0,
210 .avail_min = MMAP_PERIOD_SIZE, //1 ms
211};
212
vivek mehtaa68fea62017-06-08 19:04:02 -0700213struct pcm_config pcm_config_voip = {
214 .channels = 1,
215 .period_count = 2,
216 .format = PCM_FORMAT_S16_LE,
217 .stop_threshold = INT_MAX,
218 .avail_min = 0,
219};
220
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700221#define AFE_PROXY_CHANNEL_COUNT 2
222#define AFE_PROXY_SAMPLING_RATE 48000
223
224#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
225#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
226
227struct pcm_config pcm_config_afe_proxy_playback = {
228 .channels = AFE_PROXY_CHANNEL_COUNT,
229 .rate = AFE_PROXY_SAMPLING_RATE,
230 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
231 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
232 .format = PCM_FORMAT_S16_LE,
233 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
234 .stop_threshold = INT_MAX,
235 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
236};
237
238#define AFE_PROXY_RECORD_PERIOD_SIZE 768
239#define AFE_PROXY_RECORD_PERIOD_COUNT 4
240
241struct pcm_config pcm_config_afe_proxy_record = {
242 .channels = AFE_PROXY_CHANNEL_COUNT,
243 .rate = AFE_PROXY_SAMPLING_RATE,
244 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
245 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
246 .format = PCM_FORMAT_S16_LE,
247 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
248 .stop_threshold = INT_MAX,
249 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
250};
251
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700252const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700253 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
254 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800255 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700256 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700257 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700258 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800259 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700260
Eric Laurentb23d5282013-05-14 15:27:20 -0700261 [USECASE_AUDIO_RECORD] = "audio-record",
262 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800263 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George569b7482017-05-08 14:44:27 -0700264 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700265
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800266 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
267 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700268
Eric Laurentb23d5282013-05-14 15:27:20 -0700269 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700270 [USECASE_VOICE2_CALL] = "voice2-call",
271 [USECASE_VOLTE_CALL] = "volte-call",
272 [USECASE_QCHAT_CALL] = "qchat-call",
273 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800274 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
275 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700276
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700277 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
278 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
279
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700280 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
281 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
vivek mehta781065c2017-04-04 12:55:01 -0700282
283 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
284 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
285 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
286
vivek mehtaa68fea62017-06-08 19:04:02 -0700287 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
288 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Eric Laurentb23d5282013-05-14 15:27:20 -0700289};
290
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800291
292#define STRING_TO_ENUM(string) { #string, string }
293
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800294struct string_to_enum {
295 const char *name;
296 uint32_t value;
297};
298
Haynes Mathew George569b7482017-05-08 14:44:27 -0700299static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800300 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
301 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
302 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Eric Laurent74b55762017-07-09 17:04:53 -0700303 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
Haynes Mathew George569b7482017-05-08 14:44:27 -0700304 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
Eric Laurent74b55762017-07-09 17:04:53 -0700305 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
306 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
307 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
308 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
309 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
310 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
311 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
312 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
313 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800314};
315
Haynes Mathew George5191a852013-09-11 14:19:36 -0700316static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700317static struct audio_device *adev = NULL;
Andy Hung9e737de2017-05-22 10:51:22 -0700318static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700319static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700320//cache last MBDRC cal step level
321static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700322
Haynes Mathew George03c40102016-01-29 17:57:48 -0800323static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
324 int flags __unused)
325{
326 int dir = 0;
327 switch (uc_id) {
328 case USECASE_AUDIO_RECORD_LOW_LATENCY:
329 dir = 1;
330 case USECASE_AUDIO_PLAYBACK_ULL:
331 break;
332 default:
333 return false;
334 }
335
336 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
337 PCM_PLAYBACK : PCM_CAPTURE);
338 if (adev->adm_is_noirq_avail)
339 return adev->adm_is_noirq_avail(adev->adm_data,
340 adev->snd_card, dev_id, dir);
341 return false;
342}
343
344static void register_out_stream(struct stream_out *out)
345{
346 struct audio_device *adev = out->dev;
347 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
348 return;
349
350 if (!adev->adm_register_output_stream)
351 return;
352
353 adev->adm_register_output_stream(adev->adm_data,
354 out->handle,
355 out->flags);
356
357 if (!adev->adm_set_config)
358 return;
359
360 if (out->realtime) {
361 adev->adm_set_config(adev->adm_data,
362 out->handle,
363 out->pcm, &out->config);
364 }
365}
366
367static void register_in_stream(struct stream_in *in)
368{
369 struct audio_device *adev = in->dev;
370 if (!adev->adm_register_input_stream)
371 return;
372
373 adev->adm_register_input_stream(adev->adm_data,
374 in->capture_handle,
375 in->flags);
376
377 if (!adev->adm_set_config)
378 return;
379
380 if (in->realtime) {
381 adev->adm_set_config(adev->adm_data,
382 in->capture_handle,
383 in->pcm,
384 &in->config);
385 }
386}
387
388static void request_out_focus(struct stream_out *out, long ns)
389{
390 struct audio_device *adev = out->dev;
391
Haynes Mathew George03c40102016-01-29 17:57:48 -0800392 if (adev->adm_request_focus_v2) {
393 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
394 } else if (adev->adm_request_focus) {
395 adev->adm_request_focus(adev->adm_data, out->handle);
396 }
397}
398
399static void request_in_focus(struct stream_in *in, long ns)
400{
401 struct audio_device *adev = in->dev;
402
Haynes Mathew George03c40102016-01-29 17:57:48 -0800403 if (adev->adm_request_focus_v2) {
404 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
405 } else if (adev->adm_request_focus) {
406 adev->adm_request_focus(adev->adm_data, in->capture_handle);
407 }
408}
409
410static void release_out_focus(struct stream_out *out, long ns __unused)
411{
412 struct audio_device *adev = out->dev;
413
414 if (adev->adm_abandon_focus)
415 adev->adm_abandon_focus(adev->adm_data, out->handle);
416}
417
418static void release_in_focus(struct stream_in *in, long ns __unused)
419{
420 struct audio_device *adev = in->dev;
421 if (adev->adm_abandon_focus)
422 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
423}
424
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700425static int parse_snd_card_status(struct str_parms * parms, int * card,
426 card_status_t * status)
427{
428 char value[32]={0};
429 char state[32]={0};
430
431 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
432
433 if (ret < 0)
434 return -1;
435
436 // sscanf should be okay as value is of max length 32.
437 // same as sizeof state.
438 if (sscanf(value, "%d,%s", card, state) < 2)
439 return -1;
440
441 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
442 CARD_STATUS_OFFLINE;
443 return 0;
444}
445
vivek mehta1a9b7c02015-06-25 11:49:38 -0700446__attribute__ ((visibility ("default")))
447bool audio_hw_send_gain_dep_calibration(int level) {
448 bool ret_val = false;
449 ALOGV("%s: enter ... ", __func__);
450
451 pthread_mutex_lock(&adev_init_lock);
452
453 if (adev != NULL && adev->platform != NULL) {
454 pthread_mutex_lock(&adev->lock);
455 ret_val = platform_send_gain_dep_cal(adev->platform, level);
456 pthread_mutex_unlock(&adev->lock);
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700457
458 // if cal set fails, cache level info
459 // if cal set succeds, reset known last cal set
460 if (!ret_val)
461 last_known_cal_step = level;
462 else if (last_known_cal_step != -1)
463 last_known_cal_step = -1;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700464 } else {
465 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
466 }
467
468 pthread_mutex_unlock(&adev_init_lock);
469
470 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
471 return ret_val;
472}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700473
vivek mehtaa8d7c922016-05-25 14:40:44 -0700474__attribute__ ((visibility ("default")))
475int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
476 int table_size) {
477 int ret_val = 0;
478 ALOGV("%s: enter ... ", __func__);
479
480 pthread_mutex_lock(&adev_init_lock);
481 if (adev == NULL) {
482 ALOGW("%s: adev is NULL .... ", __func__);
483 goto done;
484 }
485
486 pthread_mutex_lock(&adev->lock);
487 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
488 pthread_mutex_unlock(&adev->lock);
489done:
490 pthread_mutex_unlock(&adev_init_lock);
491 ALOGV("%s: exit ... ", __func__);
492 return ret_val;
493}
494
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700495static bool is_supported_format(audio_format_t format)
496{
Eric Laurent8251ac82014-07-23 11:00:25 -0700497 switch (format) {
498 case AUDIO_FORMAT_MP3:
499 case AUDIO_FORMAT_AAC_LC:
500 case AUDIO_FORMAT_AAC_HE_V1:
501 case AUDIO_FORMAT_AAC_HE_V2:
502 return true;
503 default:
504 break;
505 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700506 return false;
507}
508
Haynes Mathew George03c40102016-01-29 17:57:48 -0800509static inline bool is_mmap_usecase(audio_usecase_t uc_id)
510{
511 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
512 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
513}
514
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700515static int get_snd_codec_id(audio_format_t format)
516{
517 int id = 0;
518
Eric Laurent8251ac82014-07-23 11:00:25 -0700519 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700520 case AUDIO_FORMAT_MP3:
521 id = SND_AUDIOCODEC_MP3;
522 break;
523 case AUDIO_FORMAT_AAC:
524 id = SND_AUDIOCODEC_AAC;
525 break;
526 default:
527 ALOGE("%s: Unsupported audio format", __func__);
528 }
529
530 return id;
531}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800532
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800533static int audio_ssr_status(struct audio_device *adev)
534{
535 int ret = 0;
536 struct mixer_ctl *ctl;
537 const char *mixer_ctl_name = "Audio SSR Status";
538
539 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
540 ret = mixer_ctl_get_value(ctl, 0);
541 ALOGD("%s: value: %d", __func__, ret);
542 return ret;
543}
544
vivek mehta4a824772017-06-08 19:05:49 -0700545static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
546{
547 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
548}
549
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800550int enable_audio_route(struct audio_device *adev,
551 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800552{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700553 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800554 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800555
556 if (usecase == NULL)
557 return -EINVAL;
558
559 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
560
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800561 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700562 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800563 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700564 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800565
Yamit Mehtae3b99562016-09-16 22:44:00 +0530566 audio_extn_utils_send_app_type_cfg(adev, usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800567 audio_extn_utils_send_audio_calibration(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800568 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500569 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700570 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700571 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800572
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800573 ALOGV("%s: exit", __func__);
574 return 0;
575}
576
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800577int disable_audio_route(struct audio_device *adev,
578 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800579{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700580 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800581 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800582
583 if (usecase == NULL)
584 return -EINVAL;
585
586 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700587 if (usecase->type == PCM_CAPTURE)
588 snd_device = usecase->in_snd_device;
589 else
590 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800591 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500592 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700593 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700594 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800595
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800596 ALOGV("%s: exit", __func__);
597 return 0;
598}
599
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800600int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700601 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800602{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700603 int i, num_devices = 0;
604 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800605 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800606 if (snd_device < SND_DEVICE_MIN ||
607 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800608 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800609 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800610 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700611
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700612 platform_send_audio_calibration(adev->platform, snd_device);
613
vivek mehtade4849c2016-03-03 17:23:38 -0800614 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700615 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700616 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800617 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700618 }
619
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700620 /* due to the possibility of calibration overwrite between listen
621 and audio, notify sound trigger hal before audio calibration is sent */
622 audio_extn_sound_trigger_update_device_status(snd_device,
623 ST_EVENT_SND_DEVICE_BUSY);
624
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700625 if (audio_extn_spkr_prot_is_enabled())
626 audio_extn_spkr_prot_calib_cancel(adev);
627
zhaoyang yin4211fad2015-06-04 21:13:25 +0800628 audio_extn_dsm_feedback_enable(adev, snd_device, true);
629
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700630 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
631 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
632 audio_extn_spkr_prot_is_enabled()) {
633 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800634 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700635 }
636 if (audio_extn_spkr_prot_start_processing(snd_device)) {
637 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800638 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700639 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700640 } else if (platform_can_split_snd_device(snd_device,
641 &num_devices,
642 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700643 for (i = 0; i < num_devices; i++) {
644 enable_snd_device(adev, new_snd_devices[i]);
645 }
vivek mehtab6506412015-08-07 16:55:17 -0700646 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700647 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800648 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
649 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
650 ALOGE(" %s: Invalid sound device returned", __func__);
651 goto on_error;
652 }
Ed Tam70b5c142016-03-21 19:14:29 -0700653
Eric Laurent2e140aa2016-06-30 17:14:46 -0700654 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800655 audio_route_apply_and_update_path(adev->audio_route, device_name);
656 }
657on_success:
658 adev->snd_dev_ref_cnt[snd_device]++;
659 ret_val = 0;
660on_error:
661 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800662}
663
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800664int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700665 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800666{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700667 int i, num_devices = 0;
668 snd_device_t new_snd_devices[2];
669
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800670 if (snd_device < SND_DEVICE_MIN ||
671 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800672 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800673 return -EINVAL;
674 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700675 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
676 ALOGE("%s: device ref cnt is already 0", __func__);
677 return -EINVAL;
678 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800679 audio_extn_tfa_98xx_disable_speaker(snd_device);
680
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700681 adev->snd_dev_ref_cnt[snd_device]--;
682 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800683 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700684 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700685 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700686 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
687 audio_extn_spkr_prot_is_enabled()) {
688 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700689
690 // when speaker device is disabled, reset swap.
691 // will be renabled on usecase start
692 platform_set_swap_channels(adev, false);
693
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700694 } else if (platform_can_split_snd_device(snd_device,
695 &num_devices,
696 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700697 for (i = 0; i < num_devices; i++) {
698 disable_snd_device(adev, new_snd_devices[i]);
699 }
vivek mehtab6506412015-08-07 16:55:17 -0700700 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700701 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800702 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
703 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
704 ALOGE(" %s: Invalid sound device returned", __func__);
705 return -EINVAL;
706 }
707
Eric Laurent2e140aa2016-06-30 17:14:46 -0700708 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800709 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700710 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700711 audio_extn_sound_trigger_update_device_status(snd_device,
712 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700713 }
vivek mehtab6506412015-08-07 16:55:17 -0700714
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800715 return 0;
716}
717
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700718/*
719 legend:
720 uc - existing usecase
721 new_uc - new usecase
722 d1, d11, d2 - SND_DEVICE enums
723 a1, a2 - corresponding ANDROID device enums
724 B, B1, B2 - backend strings
725
726case 1
727 uc->dev d1 (a1) B1
728 new_uc->dev d1 (a1), d2 (a2) B1, B2
729
730 resolution: disable and enable uc->dev on d1
731
732case 2
733 uc->dev d1 (a1) B1
734 new_uc->dev d11 (a1) B1
735
736 resolution: need to switch uc since d1 and d11 are related
737 (e.g. speaker and voice-speaker)
738 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
739
740case 3
741 uc->dev d1 (a1) B1
742 new_uc->dev d2 (a2) B2
743
744 resolution: no need to switch uc
745
746case 4
747 uc->dev d1 (a1) B
748 new_uc->dev d2 (a2) B
749
750 resolution: disable enable uc-dev on d2 since backends match
751 we cannot enable two streams on two different devices if they
752 share the same backend. e.g. if offload is on speaker device using
753 QUAD_MI2S backend and a low-latency stream is started on voice-handset
754 using the same backend, offload must also be switched to voice-handset.
755
756case 5
757 uc->dev d1 (a1) B
758 new_uc->dev d1 (a1), d2 (a2) B
759
760 resolution: disable enable uc-dev on d2 since backends match
761 we cannot enable two streams on two different devices if they
762 share the same backend.
763
764case 6
765 uc->dev d1 a1 B1
766 new_uc->dev d2 a1 B2
767
768 resolution: no need to switch
769
770case 7
771
772 uc->dev d1 (a1), d2 (a2) B1, B2
773 new_uc->dev d1 B1
774
775 resolution: no need to switch
776
777*/
778static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
779 struct audio_usecase *new_uc,
780 snd_device_t new_snd_device)
781{
782 audio_devices_t a1 = uc->stream.out->devices;
783 audio_devices_t a2 = new_uc->stream.out->devices;
784
785 snd_device_t d1 = uc->out_snd_device;
786 snd_device_t d2 = new_snd_device;
787
788 // Treat as a special case when a1 and a2 are not disjoint
789 if ((a1 != a2) && (a1 & a2)) {
790 snd_device_t d3[2];
791 int num_devices = 0;
792 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
793 &num_devices,
794 d3);
795 if (ret < 0) {
796 if (ret != -ENOSYS) {
797 ALOGW("%s failed to split snd_device %d",
798 __func__,
799 popcount(a1) > 1 ? d1 : d2);
800 }
801 goto end;
802 }
803
804 // NB: case 7 is hypothetical and isn't a practical usecase yet.
805 // But if it does happen, we need to give priority to d2 if
806 // the combo devices active on the existing usecase share a backend.
807 // This is because we cannot have a usecase active on a combo device
808 // and a new usecase requests one device in this combo pair.
809 if (platform_check_backends_match(d3[0], d3[1])) {
810 return d2; // case 5
811 } else {
812 return d1; // case 1
813 }
814 } else {
815 if (platform_check_backends_match(d1, d2)) {
816 return d2; // case 2, 4
817 } else {
818 return d1; // case 6, 3
819 }
820 }
821
822end:
823 return d2; // return whatever was calculated before.
824}
825
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700826static void check_and_route_playback_usecases(struct audio_device *adev,
827 struct audio_usecase *uc_info,
828 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700829{
830 struct listnode *node;
831 struct audio_usecase *usecase;
832 bool switch_device[AUDIO_USECASE_MAX];
833 int i, num_uc_to_switch = 0;
834
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700835 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
836 uc_info,
837 snd_device);
David Linee3fe402017-03-13 10:00:42 -0700838
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700839 /*
840 * This function is to make sure that all the usecases that are active on
841 * the hardware codec backend are always routed to any one device that is
842 * handled by the hardware codec.
843 * For example, if low-latency and deep-buffer usecases are currently active
844 * on speaker and out_set_parameters(headset) is received on low-latency
845 * output, then we have to make sure deep-buffer is also switched to headset,
846 * because of the limitation that both the devices cannot be enabled
847 * at the same time as they share the same backend.
848 */
849 /* Disable all the usecases on the shared backend other than the
850 specified usecase */
851 for (i = 0; i < AUDIO_USECASE_MAX; i++)
852 switch_device[i] = false;
853
854 list_for_each(node, &adev->usecase_list) {
855 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700856 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
857 continue;
858
859 if (force_routing ||
860 (usecase->out_snd_device != snd_device &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -0700861 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
862 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700863 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700864 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
865 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700866 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700867 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700868 switch_device[usecase->id] = true;
869 num_uc_to_switch++;
870 }
871 }
872
873 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700874 list_for_each(node, &adev->usecase_list) {
875 usecase = node_to_item(node, struct audio_usecase, list);
876 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700877 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900878 }
879 }
880
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700881 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900882 list_for_each(node, &adev->usecase_list) {
883 usecase = node_to_item(node, struct audio_usecase, list);
884 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700885 d_device = derive_playback_snd_device(usecase, uc_info,
886 snd_device);
887 enable_snd_device(adev, d_device);
888 /* Update the out_snd_device before enabling the audio route */
889 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700890 }
891 }
892
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700893 /* Re-route all the usecases on the shared backend other than the
894 specified usecase to new snd devices */
895 list_for_each(node, &adev->usecase_list) {
896 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700897 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700898 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700899 }
900 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700901 }
902}
903
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700904static void check_and_route_capture_usecases(struct audio_device *adev,
905 struct audio_usecase *uc_info,
906 snd_device_t snd_device)
907{
908 struct listnode *node;
909 struct audio_usecase *usecase;
910 bool switch_device[AUDIO_USECASE_MAX];
911 int i, num_uc_to_switch = 0;
912
vivek mehta4ed66e62016-04-15 23:33:34 -0700913 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
914
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700915 /*
916 * This function is to make sure that all the active capture usecases
917 * are always routed to the same input sound device.
918 * For example, if audio-record and voice-call usecases are currently
919 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
920 * is received for voice call then we have to make sure that audio-record
921 * usecase is also switched to earpiece i.e. voice-dmic-ef,
922 * because of the limitation that two devices cannot be enabled
923 * at the same time if they share the same backend.
924 */
925 for (i = 0; i < AUDIO_USECASE_MAX; i++)
926 switch_device[i] = false;
927
928 list_for_each(node, &adev->usecase_list) {
929 usecase = node_to_item(node, struct audio_usecase, list);
930 if (usecase->type != PCM_PLAYBACK &&
931 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700932 usecase->in_snd_device != snd_device &&
933 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700934 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
935 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700936 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700937 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700938 switch_device[usecase->id] = true;
939 num_uc_to_switch++;
940 }
941 }
942
943 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700944 list_for_each(node, &adev->usecase_list) {
945 usecase = node_to_item(node, struct audio_usecase, list);
946 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700947 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700948 }
949 }
950
951 list_for_each(node, &adev->usecase_list) {
952 usecase = node_to_item(node, struct audio_usecase, list);
953 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700954 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700955 }
956 }
957
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700958 /* Re-route all the usecases on the shared backend other than the
959 specified usecase to new snd devices */
960 list_for_each(node, &adev->usecase_list) {
961 usecase = node_to_item(node, struct audio_usecase, list);
962 /* Update the in_snd_device only before enabling the audio route */
963 if (switch_device[usecase->id] ) {
964 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700965 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700966 }
967 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700968 }
969}
970
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800971/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700972static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800973{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700974 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700975 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800976
977 switch (channels) {
978 /*
979 * Do not handle stereo output in Multi-channel cases
980 * Stereo case is handled in normal playback path
981 */
982 case 6:
983 ALOGV("%s: HDMI supports 5.1", __func__);
984 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
985 break;
986 case 8:
987 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
988 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
989 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
990 break;
991 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700992 ALOGE("HDMI does not support multi channel playback");
993 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800994 break;
995 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700996 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800997}
998
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -0700999static ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1000 uint32_t *supported_sample_rates __unused,
1001 uint32_t max_rates __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001002{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001003 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1004 supported_sample_rates,
1005 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001006#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001007 for (ssize_t i=0; i<count; i++) {
1008 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1009 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001010 }
1011#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001012 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001013}
1014
Haynes Mathew George569b7482017-05-08 14:44:27 -07001015static int read_usb_sup_channel_masks(bool is_playback,
1016 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001017 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001018{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001019 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001020 int channel_count;
1021 uint32_t num_masks = 0;
1022 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1023 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001024 }
Eric Laurent74b55762017-07-09 17:04:53 -07001025 if (is_playback) {
1026 // For playback we never report mono because the framework always outputs stereo
1027 channel_count = DEFAULT_CHANNEL_COUNT;
1028 // audio_channel_out_mask_from_count() does return positional masks for channel counts
1029 // above 2 but we want indexed masks here. So we
1030 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1031 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1032 }
1033 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1034 supported_channel_masks[num_masks++] =
1035 audio_channel_mask_for_index_assignment_from_count(channel_count);
1036 }
1037 } else {
1038 // For capture we report all supported channel masks from 1 channel up.
1039 channel_count = MIN_CHANNEL_COUNT;
1040 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1041 // indexed mask
1042 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1043 supported_channel_masks[num_masks++] =
1044 audio_channel_in_mask_from_count(channel_count);
1045 }
1046 }
1047 ALOGV("%s: %s supported ch %d supported_channel_masks[0] %08x num_masks %d", __func__,
1048 is_playback ? "P" : "C", channels, supported_channel_masks[0], num_masks);
1049 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001050}
1051
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001052static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001053 audio_format_t *supported_formats,
1054 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001055{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001056 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001057 switch (bitwidth) {
1058 case 24:
1059 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001060 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001061 break;
1062 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001063 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001064 break;
1065 case 16:
1066 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001067 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001068 break;
1069 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001070 ALOGV("%s: %s supported format %d", __func__,
1071 is_playback ? "P" : "C", bitwidth);
1072 return 1;
1073}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001074
Haynes Mathew George569b7482017-05-08 14:44:27 -07001075static int read_usb_sup_params_and_compare(bool is_playback,
1076 audio_format_t *format,
1077 audio_format_t *supported_formats,
1078 uint32_t max_formats,
1079 audio_channel_mask_t *mask,
1080 audio_channel_mask_t *supported_channel_masks,
1081 uint32_t max_masks,
1082 uint32_t *rate,
1083 uint32_t *supported_sample_rates,
1084 uint32_t max_rates) {
1085 int ret = 0;
1086 int num_formats;
1087 int num_masks;
1088 int num_rates;
1089 int i;
1090
1091 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1092 max_formats);
1093 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1094 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001095
Haynes Mathew George569b7482017-05-08 14:44:27 -07001096 num_rates = read_usb_sup_sample_rates(is_playback,
1097 supported_sample_rates, max_rates);
1098
1099#define LUT(table, len, what, dflt) \
1100 for (i=0; i<len && (table[i] != what); i++); \
1101 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1102
1103 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1104 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1105 LUT(supported_sample_rates, num_rates, *rate, 0);
1106
1107#undef LUT
1108 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001109}
1110
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001111static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1112{
1113 struct audio_usecase *usecase;
1114 struct listnode *node;
1115
1116 list_for_each(node, &adev->usecase_list) {
1117 usecase = node_to_item(node, struct audio_usecase, list);
1118 if (usecase->type == VOICE_CALL) {
1119 ALOGV("%s: usecase id %d", __func__, usecase->id);
1120 return usecase->id;
1121 }
1122 }
1123 return USECASE_INVALID;
1124}
1125
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001126struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1127 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001128{
1129 struct audio_usecase *usecase;
1130 struct listnode *node;
1131
1132 list_for_each(node, &adev->usecase_list) {
1133 usecase = node_to_item(node, struct audio_usecase, list);
1134 if (usecase->id == uc_id)
1135 return usecase;
1136 }
1137 return NULL;
1138}
1139
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001140int select_devices(struct audio_device *adev,
1141 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001142{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001143 snd_device_t out_snd_device = SND_DEVICE_NONE;
1144 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001145 struct audio_usecase *usecase = NULL;
1146 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001147 struct audio_usecase *hfp_usecase = NULL;
1148 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001149 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001150 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001151
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001152 usecase = get_usecase_from_list(adev, uc_id);
1153 if (usecase == NULL) {
1154 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1155 return -EINVAL;
1156 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001157
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001158 if ((usecase->type == VOICE_CALL) ||
1159 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001160 out_snd_device = platform_get_output_snd_device(adev->platform,
1161 usecase->stream.out->devices);
1162 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001163 usecase->devices = usecase->stream.out->devices;
1164 } else {
1165 /*
1166 * If the voice call is active, use the sound devices of voice call usecase
1167 * so that it would not result any device switch. All the usecases will
1168 * be switched to new device when select_devices() is called for voice call
1169 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001170 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001171 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001172 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001173 vc_usecase = get_usecase_from_list(adev,
1174 get_voice_usecase_id_from_list(adev));
1175 if ((vc_usecase != NULL) &&
1176 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1177 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001178 in_snd_device = vc_usecase->in_snd_device;
1179 out_snd_device = vc_usecase->out_snd_device;
1180 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001181 } else if (audio_extn_hfp_is_active(adev)) {
1182 hfp_ucid = audio_extn_hfp_get_usecase();
1183 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1184 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1185 in_snd_device = hfp_usecase->in_snd_device;
1186 out_snd_device = hfp_usecase->out_snd_device;
1187 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001188 }
1189 if (usecase->type == PCM_PLAYBACK) {
1190 usecase->devices = usecase->stream.out->devices;
1191 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001192 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001193 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001194 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001195 if (usecase->stream.out == adev->primary_output &&
1196 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001197 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1198 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001199 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001200 select_devices(adev, adev->active_input->usecase);
1201 }
1202 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001203 } else if (usecase->type == PCM_CAPTURE) {
1204 usecase->devices = usecase->stream.in->device;
1205 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001206 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001207 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001208 if (adev->active_input &&
1209 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1210 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001211 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001212 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1213 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
1214 } else if (adev->primary_output) {
1215 out_device = adev->primary_output->devices;
1216 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001217 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001218 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001219 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001220 }
1221 }
1222
1223 if (out_snd_device == usecase->out_snd_device &&
1224 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001225 return 0;
1226 }
1227
Eric Laurent2bafff12016-03-17 12:17:23 -07001228 if (out_snd_device != SND_DEVICE_NONE &&
1229 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1230 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1231 __func__,
1232 use_case_table[uc_id],
1233 adev->last_logged_snd_device[uc_id][0],
1234 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1235 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1236 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1237 -1,
1238 out_snd_device,
1239 platform_get_snd_device_name(out_snd_device),
1240 platform_get_snd_device_acdb_id(out_snd_device));
1241 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1242 }
1243 if (in_snd_device != SND_DEVICE_NONE &&
1244 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1245 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1246 __func__,
1247 use_case_table[uc_id],
1248 adev->last_logged_snd_device[uc_id][1],
1249 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1250 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1251 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1252 -1,
1253 in_snd_device,
1254 platform_get_snd_device_name(in_snd_device),
1255 platform_get_snd_device_acdb_id(in_snd_device));
1256 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1257 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001258
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001259 /*
1260 * Limitation: While in call, to do a device switch we need to disable
1261 * and enable both RX and TX devices though one of them is same as current
1262 * device.
1263 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001264 if ((usecase->type == VOICE_CALL) &&
1265 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1266 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001267 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001268 /* Disable sidetone only if voice call already exists */
1269 if (voice_is_call_state_active(adev))
1270 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001271 }
1272
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001273 /* Disable current sound devices */
1274 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001275 disable_audio_route(adev, usecase);
1276 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001277 }
1278
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001279 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001280 disable_audio_route(adev, usecase);
1281 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001282 }
1283
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001284 /* Applicable only on the targets that has external modem.
1285 * New device information should be sent to modem before enabling
1286 * the devices to reduce in-call device switch time.
1287 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001288 if ((usecase->type == VOICE_CALL) &&
1289 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1290 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001291 status = platform_switch_voice_call_enable_device_config(adev->platform,
1292 out_snd_device,
1293 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001294 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001295
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001296 /* Enable new sound devices */
1297 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001298 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Eric Laurent99dab492017-06-17 15:19:08 -07001299 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001300 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001301 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001302 }
1303
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001304 if (in_snd_device != SND_DEVICE_NONE) {
1305 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001306 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001307 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001308
Eric Laurentb23d5282013-05-14 15:27:20 -07001309 if (usecase->type == VOICE_CALL)
1310 status = platform_switch_voice_call_device_post(adev->platform,
1311 out_snd_device,
1312 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001313
sangwoo170731f2013-06-08 15:36:36 +09001314 usecase->in_snd_device = in_snd_device;
1315 usecase->out_snd_device = out_snd_device;
1316
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001317 audio_extn_tfa_98xx_set_mode();
1318
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001319 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001320
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001321 /* Applicable only on the targets that has external modem.
1322 * Enable device command should be sent to modem only after
1323 * enabling voice call mixer controls
1324 */
vivek mehta765eb642015-08-07 19:46:06 -07001325 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001326 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1327 out_snd_device,
1328 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001329 /* Enable sidetone only if voice call already exists */
1330 if (voice_is_call_state_active(adev))
1331 voice_set_sidetone(adev, out_snd_device, true);
1332 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001333
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001334 return status;
1335}
1336
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001337static int stop_input_stream(struct stream_in *in)
1338{
1339 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001340 struct audio_usecase *uc_info;
1341 struct audio_device *adev = in->dev;
1342
Eric Laurentc8400632013-02-14 19:04:54 -08001343 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001344
Eric Laurent994a6932013-07-17 11:51:42 -07001345 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001346 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001347 uc_info = get_usecase_from_list(adev, in->usecase);
1348 if (uc_info == NULL) {
1349 ALOGE("%s: Could not find the usecase (%d) in the list",
1350 __func__, in->usecase);
1351 return -EINVAL;
1352 }
1353
vivek mehta781065c2017-04-04 12:55:01 -07001354 /* Close in-call recording streams */
1355 voice_check_and_stop_incall_rec_usecase(adev, in);
1356
Eric Laurent150dbfe2013-02-27 14:31:02 -08001357 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001358 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001359
1360 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001361 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001362
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001363 list_remove(&uc_info->list);
1364 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001365
Eric Laurent994a6932013-07-17 11:51:42 -07001366 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001367 return ret;
1368}
1369
1370int start_input_stream(struct stream_in *in)
1371{
1372 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001373 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001374 struct audio_usecase *uc_info;
1375 struct audio_device *adev = in->dev;
1376
Eric Laurent994a6932013-07-17 11:51:42 -07001377 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001378
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001379 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1380 return -EIO;
1381
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001382 if (in->card_status == CARD_STATUS_OFFLINE ||
1383 adev->card_status == CARD_STATUS_OFFLINE) {
1384 ALOGW("in->card_status or adev->card_status offline, try again");
1385 ret = -EAGAIN;
1386 goto error_config;
1387 }
1388
vivek mehta781065c2017-04-04 12:55:01 -07001389 /* Check if source matches incall recording usecase criteria */
1390 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1391 if (ret)
1392 goto error_config;
1393 else
1394 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1395
Eric Laurentb23d5282013-05-14 15:27:20 -07001396 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001397 if (in->pcm_device_id < 0) {
1398 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1399 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001400 ret = -EINVAL;
1401 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001402 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001403
1404 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001405 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1406 uc_info->id = in->usecase;
1407 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001408 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001409 uc_info->devices = in->device;
1410 uc_info->in_snd_device = SND_DEVICE_NONE;
1411 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001412
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001413 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001414
1415 audio_extn_perf_lock_acquire();
1416
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001417 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001418
Eric Laurent0e46adf2016-12-16 12:49:24 -08001419 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001420 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001421 ALOGE("%s: pcm stream not ready", __func__);
1422 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001423 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001424 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001425 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001426 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1427 goto error_open;
1428 }
1429 } else {
1430 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1431 unsigned int pcm_open_retry_count = 0;
1432
1433 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1434 flags |= PCM_MMAP | PCM_NOIRQ;
1435 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1436 } else if (in->realtime) {
1437 flags |= PCM_MMAP | PCM_NOIRQ;
1438 }
1439
1440 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1441 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1442
1443 while (1) {
1444 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1445 flags, &in->config);
1446 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1447 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1448 if (in->pcm != NULL) {
1449 pcm_close(in->pcm);
1450 in->pcm = NULL;
1451 }
1452 if (pcm_open_retry_count-- == 0) {
1453 ret = -EIO;
1454 goto error_open;
1455 }
1456 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1457 continue;
1458 }
1459 break;
1460 }
1461
1462 ALOGV("%s: pcm_prepare", __func__);
1463 ret = pcm_prepare(in->pcm);
1464 if (ret < 0) {
1465 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001466 pcm_close(in->pcm);
1467 in->pcm = NULL;
1468 goto error_open;
1469 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001470 if (in->realtime) {
1471 ret = pcm_start(in->pcm);
1472 if (ret < 0) {
1473 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1474 pcm_close(in->pcm);
1475 in->pcm = NULL;
1476 goto error_open;
1477 }
1478 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001479 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001480 register_in_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001481 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001482 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001483
Eric Laurent0e46adf2016-12-16 12:49:24 -08001484 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001485
1486error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001487 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001488 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001489
1490error_config:
1491 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001492 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001493 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001494}
1495
Eric Laurenta1478072015-09-21 17:21:52 -07001496void lock_input_stream(struct stream_in *in)
1497{
1498 pthread_mutex_lock(&in->pre_lock);
1499 pthread_mutex_lock(&in->lock);
1500 pthread_mutex_unlock(&in->pre_lock);
1501}
1502
1503void lock_output_stream(struct stream_out *out)
1504{
1505 pthread_mutex_lock(&out->pre_lock);
1506 pthread_mutex_lock(&out->lock);
1507 pthread_mutex_unlock(&out->pre_lock);
1508}
1509
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001510/* must be called with out->lock locked */
1511static int send_offload_cmd_l(struct stream_out* out, int command)
1512{
1513 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1514
1515 ALOGVV("%s %d", __func__, command);
1516
1517 cmd->cmd = command;
1518 list_add_tail(&out->offload_cmd_list, &cmd->node);
1519 pthread_cond_signal(&out->offload_cond);
1520 return 0;
1521}
1522
1523/* must be called iwth out->lock locked */
1524static void stop_compressed_output_l(struct stream_out *out)
1525{
1526 out->offload_state = OFFLOAD_STATE_IDLE;
1527 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001528 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001529 if (out->compr != NULL) {
1530 compress_stop(out->compr);
1531 while (out->offload_thread_blocked) {
1532 pthread_cond_wait(&out->cond, &out->lock);
1533 }
1534 }
1535}
1536
1537static void *offload_thread_loop(void *context)
1538{
1539 struct stream_out *out = (struct stream_out *) context;
1540 struct listnode *item;
1541
1542 out->offload_state = OFFLOAD_STATE_IDLE;
1543 out->playback_started = 0;
1544
1545 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1546 set_sched_policy(0, SP_FOREGROUND);
1547 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1548
1549 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001550 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001551 for (;;) {
1552 struct offload_cmd *cmd = NULL;
1553 stream_callback_event_t event;
1554 bool send_callback = false;
1555
1556 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1557 __func__, list_empty(&out->offload_cmd_list),
1558 out->offload_state);
1559 if (list_empty(&out->offload_cmd_list)) {
1560 ALOGV("%s SLEEPING", __func__);
1561 pthread_cond_wait(&out->offload_cond, &out->lock);
1562 ALOGV("%s RUNNING", __func__);
1563 continue;
1564 }
1565
1566 item = list_head(&out->offload_cmd_list);
1567 cmd = node_to_item(item, struct offload_cmd, node);
1568 list_remove(item);
1569
1570 ALOGVV("%s STATE %d CMD %d out->compr %p",
1571 __func__, out->offload_state, cmd->cmd, out->compr);
1572
1573 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1574 free(cmd);
1575 break;
1576 }
1577
1578 if (out->compr == NULL) {
1579 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001580 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001581 pthread_cond_signal(&out->cond);
1582 continue;
1583 }
1584 out->offload_thread_blocked = true;
1585 pthread_mutex_unlock(&out->lock);
1586 send_callback = false;
1587 switch(cmd->cmd) {
1588 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1589 compress_wait(out->compr, -1);
1590 send_callback = true;
1591 event = STREAM_CBK_EVENT_WRITE_READY;
1592 break;
1593 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001594 compress_next_track(out->compr);
1595 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001596 send_callback = true;
1597 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001598 /* Resend the metadata for next iteration */
1599 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001600 break;
1601 case OFFLOAD_CMD_DRAIN:
1602 compress_drain(out->compr);
1603 send_callback = true;
1604 event = STREAM_CBK_EVENT_DRAIN_READY;
1605 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001606 case OFFLOAD_CMD_ERROR:
1607 send_callback = true;
1608 event = STREAM_CBK_EVENT_ERROR;
1609 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001610 default:
1611 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1612 break;
1613 }
Eric Laurenta1478072015-09-21 17:21:52 -07001614 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001615 out->offload_thread_blocked = false;
1616 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001617 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001618 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001619 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001620 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001621 free(cmd);
1622 }
1623
1624 pthread_cond_signal(&out->cond);
1625 while (!list_empty(&out->offload_cmd_list)) {
1626 item = list_head(&out->offload_cmd_list);
1627 list_remove(item);
1628 free(node_to_item(item, struct offload_cmd, node));
1629 }
1630 pthread_mutex_unlock(&out->lock);
1631
1632 return NULL;
1633}
1634
1635static int create_offload_callback_thread(struct stream_out *out)
1636{
1637 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1638 list_init(&out->offload_cmd_list);
1639 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1640 offload_thread_loop, out);
1641 return 0;
1642}
1643
1644static int destroy_offload_callback_thread(struct stream_out *out)
1645{
Eric Laurenta1478072015-09-21 17:21:52 -07001646 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001647 stop_compressed_output_l(out);
1648 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1649
1650 pthread_mutex_unlock(&out->lock);
1651 pthread_join(out->offload_thread, (void **) NULL);
1652 pthread_cond_destroy(&out->offload_cond);
1653
1654 return 0;
1655}
1656
Eric Laurent07eeafd2013-10-06 12:52:49 -07001657static bool allow_hdmi_channel_config(struct audio_device *adev)
1658{
1659 struct listnode *node;
1660 struct audio_usecase *usecase;
1661 bool ret = true;
1662
1663 list_for_each(node, &adev->usecase_list) {
1664 usecase = node_to_item(node, struct audio_usecase, list);
1665 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1666 /*
1667 * If voice call is already existing, do not proceed further to avoid
1668 * disabling/enabling both RX and TX devices, CSD calls, etc.
1669 * Once the voice call done, the HDMI channels can be configured to
1670 * max channels of remaining use cases.
1671 */
1672 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001673 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001674 __func__);
1675 ret = false;
1676 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001677 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1678 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001679 "no change in HDMI channels", __func__);
1680 ret = false;
1681 break;
1682 }
1683 }
1684 }
1685 return ret;
1686}
1687
1688static int check_and_set_hdmi_channels(struct audio_device *adev,
1689 unsigned int channels)
1690{
1691 struct listnode *node;
1692 struct audio_usecase *usecase;
1693
1694 /* Check if change in HDMI channel config is allowed */
1695 if (!allow_hdmi_channel_config(adev))
1696 return 0;
1697
1698 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001699 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001700 return 0;
1701 }
1702
1703 platform_set_hdmi_channels(adev->platform, channels);
1704 adev->cur_hdmi_channels = channels;
1705
1706 /*
1707 * Deroute all the playback streams routed to HDMI so that
1708 * the back end is deactivated. Note that backend will not
1709 * be deactivated if any one stream is connected to it.
1710 */
1711 list_for_each(node, &adev->usecase_list) {
1712 usecase = node_to_item(node, struct audio_usecase, list);
1713 if (usecase->type == PCM_PLAYBACK &&
1714 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001715 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001716 }
1717 }
1718
1719 /*
1720 * Enable all the streams disabled above. Now the HDMI backend
1721 * will be activated with new channel configuration
1722 */
1723 list_for_each(node, &adev->usecase_list) {
1724 usecase = node_to_item(node, struct audio_usecase, list);
1725 if (usecase->type == PCM_PLAYBACK &&
1726 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001727 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001728 }
1729 }
1730
1731 return 0;
1732}
1733
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001734static int stop_output_stream(struct stream_out *out)
1735{
1736 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001737 struct audio_usecase *uc_info;
1738 struct audio_device *adev = out->dev;
1739
Eric Laurent994a6932013-07-17 11:51:42 -07001740 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001741 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001742 uc_info = get_usecase_from_list(adev, out->usecase);
1743 if (uc_info == NULL) {
1744 ALOGE("%s: Could not find the usecase (%d) in the list",
1745 __func__, out->usecase);
1746 return -EINVAL;
1747 }
1748
Haynes Mathew George41f86652014-06-17 14:22:15 -07001749 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1750 if (adev->visualizer_stop_output != NULL)
1751 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1752 if (adev->offload_effects_stop_output != NULL)
1753 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1754 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001755
Eric Laurent150dbfe2013-02-27 14:31:02 -08001756 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001757 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001758
1759 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001760 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001761
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001762 list_remove(&uc_info->list);
1763 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001764
Eric Laurent0499d4f2014-08-25 22:39:29 -05001765 audio_extn_extspk_update(adev->extspk);
1766
Eric Laurent07eeafd2013-10-06 12:52:49 -07001767 /* Must be called after removing the usecase from list */
1768 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1769 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1770
Eric Laurent994a6932013-07-17 11:51:42 -07001771 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001772 return ret;
1773}
1774
1775int start_output_stream(struct stream_out *out)
1776{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001777 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001778 struct audio_usecase *uc_info;
1779 struct audio_device *adev = out->dev;
1780
Eric Laurent994a6932013-07-17 11:51:42 -07001781 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001782 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001783
1784 if (out->card_status == CARD_STATUS_OFFLINE ||
1785 adev->card_status == CARD_STATUS_OFFLINE) {
1786 ALOGW("out->card_status or adev->card_status offline, try again");
1787 ret = -EAGAIN;
1788 goto error_config;
1789 }
1790
Eric Laurentb23d5282013-05-14 15:27:20 -07001791 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001792 if (out->pcm_device_id < 0) {
1793 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1794 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001795 ret = -EINVAL;
1796 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001797 }
1798
1799 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1800 uc_info->id = out->usecase;
1801 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001802 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001803 uc_info->devices = out->devices;
1804 uc_info->in_snd_device = SND_DEVICE_NONE;
1805 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001806
Eric Laurent07eeafd2013-10-06 12:52:49 -07001807 /* This must be called before adding this usecase to the list */
1808 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1809 check_and_set_hdmi_channels(adev, out->config.channels);
1810
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001811 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001812
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001813 audio_extn_perf_lock_acquire();
1814
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001815 select_devices(adev, out->usecase);
1816
Eric Laurent0499d4f2014-08-25 22:39:29 -05001817 audio_extn_extspk_update(adev->extspk);
1818
Andy Hung31aca912014-03-20 17:14:59 -07001819 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001820 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001821 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1822 out->pcm = NULL;
1823 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1824 COMPRESS_IN, &out->compr_config);
1825 if (out->compr && !is_compress_ready(out->compr)) {
1826 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1827 compress_close(out->compr);
1828 out->compr = NULL;
1829 ret = -EIO;
1830 goto error_open;
1831 }
1832 if (out->offload_callback)
1833 compress_nonblock(out->compr, out->non_blocking);
1834
1835 if (adev->visualizer_start_output != NULL)
1836 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1837 if (adev->offload_effects_start_output != NULL)
1838 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
1839 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001840 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001841 ALOGE("%s: pcm stream not ready", __func__);
1842 goto error_open;
1843 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001844 ret = pcm_start(out->pcm);
1845 if (ret < 0) {
1846 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1847 goto error_open;
1848 }
1849 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07001850 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001851 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001852
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001853 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1854 flags |= PCM_MMAP | PCM_NOIRQ;
1855 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001856 } else if (out->realtime) {
1857 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07001858 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001859
1860 while (1) {
1861 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1862 flags, &out->config);
1863 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1864 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1865 if (out->pcm != NULL) {
1866 pcm_close(out->pcm);
1867 out->pcm = NULL;
1868 }
1869 if (pcm_open_retry_count-- == 0) {
1870 ret = -EIO;
1871 goto error_open;
1872 }
1873 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1874 continue;
1875 }
1876 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001877 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001878 ALOGV("%s: pcm_prepare", __func__);
1879 if (pcm_is_ready(out->pcm)) {
1880 ret = pcm_prepare(out->pcm);
1881 if (ret < 0) {
1882 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1883 pcm_close(out->pcm);
1884 out->pcm = NULL;
1885 goto error_open;
1886 }
1887 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001888 if (out->realtime) {
1889 ret = pcm_start(out->pcm);
1890 if (ret < 0) {
1891 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1892 pcm_close(out->pcm);
1893 out->pcm = NULL;
1894 goto error_open;
1895 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001896 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001897 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001898 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001899 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001900 audio_extn_tfa_98xx_enable_speaker();
vivek mehta4a824772017-06-08 19:05:49 -07001901 audio_extn_utils_send_app_type_gain(out->dev,
1902 out->app_type_cfg.app_type,
1903 &out->app_type_cfg.gain[0]);
vivek mehtae59cfb22017-06-16 15:57:11 -07001904
1905 // consider a scenario where on pause lower layers are tear down.
1906 // so on resume, swap mixer control need to be sent only when
1907 // backend is active, hence rather than sending from enable device
1908 // sending it from start of streamtream
1909
1910 platform_set_swap_channels(adev, true);
1911
Eric Laurent994a6932013-07-17 11:51:42 -07001912 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001913 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001914error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001915 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001916 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001917error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001918 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001919}
1920
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001921static int check_input_parameters(uint32_t sample_rate,
1922 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07001923 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001924{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001925 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
1926 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07001927 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
1928 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07001929 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1930 return -EINVAL;
1931 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001932
Eric Laurent74b55762017-07-09 17:04:53 -07001933 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
1934 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001935 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07001936 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07001937 return -EINVAL;
1938 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001939
1940 switch (sample_rate) {
1941 case 8000:
1942 case 11025:
1943 case 12000:
1944 case 16000:
1945 case 22050:
1946 case 24000:
1947 case 32000:
1948 case 44100:
1949 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001950 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001951 break;
1952 default:
vivek mehtadae44712015-07-27 14:13:18 -07001953 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001954 return -EINVAL;
1955 }
1956
1957 return 0;
1958}
1959
vivek mehtaa68fea62017-06-08 19:04:02 -07001960static size_t get_stream_buffer_size(size_t duration_ms,
1961 uint32_t sample_rate,
1962 audio_format_t format,
1963 int channel_count,
1964 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001965{
1966 size_t size = 0;
1967
vivek mehtaa68fea62017-06-08 19:04:02 -07001968 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001969 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001970 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07001971
1972 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001973
Glenn Kasten4f993392014-05-14 07:30:48 -07001974 /* make sure the size is multiple of 32 bytes
1975 * At 48 kHz mono 16-bit PCM:
1976 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1977 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1978 */
1979 size += 0x1f;
1980 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001981
1982 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001983}
1984
1985static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1986{
1987 struct stream_out *out = (struct stream_out *)stream;
1988
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001989 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001990}
1991
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001992static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001993{
1994 return -ENOSYS;
1995}
1996
1997static size_t out_get_buffer_size(const struct audio_stream *stream)
1998{
1999 struct stream_out *out = (struct stream_out *)stream;
2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002001 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2002 return out->compr_config.fragment_size;
2003 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002004 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002005 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002006}
2007
2008static uint32_t out_get_channels(const struct audio_stream *stream)
2009{
2010 struct stream_out *out = (struct stream_out *)stream;
2011
2012 return out->channel_mask;
2013}
2014
2015static audio_format_t out_get_format(const struct audio_stream *stream)
2016{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002017 struct stream_out *out = (struct stream_out *)stream;
2018
2019 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002020}
2021
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002022static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002023{
2024 return -ENOSYS;
2025}
2026
2027static int out_standby(struct audio_stream *stream)
2028{
2029 struct stream_out *out = (struct stream_out *)stream;
2030 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002031 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002032
Eric Laurent994a6932013-07-17 11:51:42 -07002033 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002034 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002035
Eric Laurenta1478072015-09-21 17:21:52 -07002036 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002037 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002038 if (adev->adm_deregister_stream)
2039 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002040 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002041 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002042 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2043 if (out->pcm) {
2044 pcm_close(out->pcm);
2045 out->pcm = NULL;
2046 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002047 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002048 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002049 out->playback_started = false;
2050 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002051 } else {
2052 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002053 out->gapless_mdata.encoder_delay = 0;
2054 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002055 if (out->compr != NULL) {
2056 compress_close(out->compr);
2057 out->compr = NULL;
2058 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002059 }
Phil Burkbc991042017-02-24 08:06:44 -08002060 if (do_stop) {
2061 stop_output_stream(out);
2062 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002063 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002064 }
2065 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002066 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002067 return 0;
2068}
2069
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002070static int out_on_error(struct audio_stream *stream)
2071{
2072 struct stream_out *out = (struct stream_out *)stream;
2073 struct audio_device *adev = out->dev;
2074 bool do_standby = false;
2075
2076 lock_output_stream(out);
2077 if (!out->standby) {
2078 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2079 stop_compressed_output_l(out);
2080 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2081 } else
2082 do_standby = true;
2083 }
2084 pthread_mutex_unlock(&out->lock);
2085
2086 if (do_standby)
2087 return out_standby(&out->stream.common);
2088
2089 return 0;
2090}
2091
Andy Hung7401c7c2016-09-21 12:41:21 -07002092static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002093{
Andy Hung7401c7c2016-09-21 12:41:21 -07002094 struct stream_out *out = (struct stream_out *)stream;
2095
2096 // We try to get the lock for consistency,
2097 // but it isn't necessary for these variables.
2098 // If we're not in standby, we may be blocked on a write.
2099 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2100 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2101 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2102
2103 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002104 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002105 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002106
2107 // dump error info
2108 (void)error_log_dump(
2109 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002110
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002111 return 0;
2112}
2113
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002114static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2115{
2116 int ret = 0;
2117 char value[32];
2118 struct compr_gapless_mdata tmp_mdata;
2119
2120 if (!out || !parms) {
2121 return -EINVAL;
2122 }
2123
2124 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2125 if (ret >= 0) {
2126 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2127 } else {
2128 return -EINVAL;
2129 }
2130
2131 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2132 if (ret >= 0) {
2133 tmp_mdata.encoder_padding = atoi(value);
2134 } else {
2135 return -EINVAL;
2136 }
2137
2138 out->gapless_mdata = tmp_mdata;
2139 out->send_new_metadata = 1;
2140 ALOGV("%s new encoder delay %u and padding %u", __func__,
2141 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2142
2143 return 0;
2144}
2145
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002146static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2147{
2148 return out == adev->primary_output || out == adev->voice_tx_output;
2149}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002150
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002151static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2152{
2153 struct stream_out *out = (struct stream_out *)stream;
2154 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002155 struct audio_usecase *usecase;
2156 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002157 struct str_parms *parms;
2158 char value[32];
2159 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002160 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002161 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002162
Eric Laurent2e140aa2016-06-30 17:14:46 -07002163 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002164 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002165 parms = str_parms_create_str(kvpairs);
2166 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2167 if (ret >= 0) {
2168 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07002169 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002170 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002171
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002172 /*
2173 * When HDMI cable is unplugged the music playback is paused and
2174 * the policy manager sends routing=0. But the audioflinger
2175 * continues to write data until standby time (3sec).
2176 * As the HDMI core is turned off, the write gets blocked.
2177 * Avoid this by routing audio to speaker until standby.
2178 */
2179 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2180 val == AUDIO_DEVICE_NONE) {
2181 val = AUDIO_DEVICE_OUT_SPEAKER;
2182 }
2183
2184 /*
2185 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002186 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002187 * the select_devices(). But how do we undo this?
2188 *
2189 * For example, music playback is active on headset (deep-buffer usecase)
2190 * and if we go to ringtones and select a ringtone, low-latency usecase
2191 * will be started on headset+speaker. As we can't enable headset+speaker
2192 * and headset devices at the same time, select_devices() switches the music
2193 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2194 * So when the ringtone playback is completed, how do we undo the same?
2195 *
2196 * We are relying on the out_set_parameters() call on deep-buffer output,
2197 * once the ringtone playback is ended.
2198 * NOTE: We should not check if the current devices are same as new devices.
2199 * Because select_devices() must be called to switch back the music
2200 * playback to headset.
2201 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002202 audio_devices_t new_dev = val;
2203 if (new_dev != AUDIO_DEVICE_NONE) {
2204 bool same_dev = out->devices == new_dev;
2205 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002206
Eric Laurenta7657192014-10-09 21:09:33 -07002207 if (output_drives_call(adev, out)) {
2208 if (!voice_is_in_call(adev)) {
2209 if (adev->mode == AUDIO_MODE_IN_CALL) {
2210 adev->current_call_output = out;
2211 ret = voice_start_call(adev);
2212 }
2213 } else {
2214 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002215 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002216 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002217 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002218
2219 if (!out->standby) {
2220 if (!same_dev) {
2221 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002222 // inform adm before actual routing to prevent glitches.
2223 if (adev->adm_on_routing_change) {
2224 adev->adm_on_routing_change(adev->adm_data,
2225 out->handle);
2226 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002227 }
2228 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002229 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002230
2231 // on device switch force swap, lower functions will make sure
2232 // to check if swap is allowed or not.
2233
2234 if (!same_dev)
2235 platform_set_swap_channels(adev, true);
vivek mehta0d3637a2016-07-24 09:32:02 -07002236 }
2237
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002238 }
2239
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002240 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002241 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002242
2243 /*handles device and call state changes*/
2244 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002245 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002246
2247 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2248 parse_compress_metadata(out, parms);
2249 }
2250
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002251 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002252 ALOGV("%s: exit: code(%d)", __func__, status);
2253 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002254}
2255
Haynes Mathew George569b7482017-05-08 14:44:27 -07002256static bool stream_get_parameter_channels(struct str_parms *query,
2257 struct str_parms *reply,
2258 audio_channel_mask_t *supported_channel_masks) {
2259 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002260 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002261 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002262 size_t i, j;
2263
2264 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2265 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002266 value[0] = '\0';
2267 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002268 while (supported_channel_masks[i] != 0) {
2269 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2270 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002271 if (!first) {
2272 strcat(value, "|");
2273 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002274 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002275 first = false;
2276 break;
2277 }
2278 }
2279 i++;
2280 }
2281 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002282 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002283 return ret >= 0;
2284}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002285
Haynes Mathew George569b7482017-05-08 14:44:27 -07002286static bool stream_get_parameter_formats(struct str_parms *query,
2287 struct str_parms *reply,
2288 audio_format_t *supported_formats) {
2289 int ret = -1;
2290 char value[256];
2291 int i;
2292
2293 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2294 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002295 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002296 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002297 case AUDIO_FORMAT_PCM_16_BIT:
2298 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2299 break;
2300 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2301 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2302 break;
2303 case AUDIO_FORMAT_PCM_32_BIT:
2304 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2305 break;
2306 default:
2307 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002308 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002309 break;
2310 }
2311 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002312 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002313 return ret >= 0;
2314}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002315
Haynes Mathew George569b7482017-05-08 14:44:27 -07002316static bool stream_get_parameter_rates(struct str_parms *query,
2317 struct str_parms *reply,
2318 uint32_t *supported_sample_rates) {
2319
2320 int i;
2321 char value[256];
2322 int ret = -1;
2323 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2324 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002325 value[0] = '\0';
2326 i=0;
2327 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002328 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002329 int avail = sizeof(value) - cursor;
2330 ret = snprintf(value + cursor, avail, "%s%d",
2331 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002332 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002333 if (ret < 0 || ret >= avail) {
2334 // if cursor is at the last element of the array
2335 // overwrite with \0 is duplicate work as
2336 // snprintf already put a \0 in place.
2337 // else
2338 // we had space to write the '|' at value[cursor]
2339 // (which will be overwritten) or no space to fill
2340 // the first element (=> cursor == 0)
2341 value[cursor] = '\0';
2342 break;
2343 }
2344 cursor += ret;
2345 ++i;
2346 }
2347 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2348 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002349 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002350 return ret >= 0;
2351}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002352
Haynes Mathew George569b7482017-05-08 14:44:27 -07002353static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2354{
2355 struct stream_out *out = (struct stream_out *)stream;
2356 struct str_parms *query = str_parms_create_str(keys);
2357 char *str;
2358 struct str_parms *reply = str_parms_create();
2359 bool replied = false;
2360 ALOGV("%s: enter: keys - %s", __func__, keys);
2361
2362 replied |= stream_get_parameter_channels(query, reply,
2363 &out->supported_channel_masks[0]);
2364 replied |= stream_get_parameter_formats(query, reply,
2365 &out->supported_formats[0]);
2366 replied |= stream_get_parameter_rates(query, reply,
2367 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002368 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002369 str = str_parms_to_str(reply);
2370 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002371 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002372 }
2373 str_parms_destroy(query);
2374 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002375 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002376 return str;
2377}
2378
2379static uint32_t out_get_latency(const struct audio_stream_out *stream)
2380{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002381 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002382 struct stream_out *out = (struct stream_out *)stream;
2383
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002384 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2385 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002386 else if ((out->realtime) ||
2387 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002388 // since the buffer won't be filled up faster than realtime,
2389 // return a smaller number
2390 period_ms = (out->af_period_multiplier * out->config.period_size *
2391 1000) / (out->config.rate);
2392 hw_delay = platform_render_latency(out->usecase)/1000;
2393 return period_ms + hw_delay;
2394 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002395
2396 return (out->config.period_count * out->config.period_size * 1000) /
2397 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002398}
2399
2400static int out_set_volume(struct audio_stream_out *stream, float left,
2401 float right)
2402{
Eric Laurenta9024de2013-04-04 09:19:12 -07002403 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002404 int volume[2];
2405
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002406 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002407 /* only take left channel into account: the API is for stereo anyway */
2408 out->muted = (left == 0.0f);
2409 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002410 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2411 const char *mixer_ctl_name = "Compress Playback Volume";
2412 struct audio_device *adev = out->dev;
2413 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002414 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2415 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002416 /* try with the control based on device id */
2417 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2418 PCM_PLAYBACK);
2419 char ctl_name[128] = {0};
2420 snprintf(ctl_name, sizeof(ctl_name),
2421 "Compress Playback %d Volume", pcm_device_id);
2422 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2423 if (!ctl) {
2424 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2425 return -EINVAL;
2426 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002427 }
2428 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2429 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2430 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2431 return 0;
vivek mehtaa68fea62017-06-08 19:04:02 -07002432 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002433 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2434 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2435 if (!out->standby) {
2436 // if in standby, cached volume will be sent after stream is opened
2437 audio_extn_utils_send_app_type_gain(out->dev,
2438 out->app_type_cfg.app_type,
2439 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002440 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002441 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002442 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002443
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002444 return -ENOSYS;
2445}
2446
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002447// note: this call is safe only if the stream_cb is
2448// removed first in close_output_stream (as is done now).
2449static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2450{
2451 if (!stream || !parms)
2452 return;
2453
2454 struct stream_out *out = (struct stream_out *)stream;
2455 struct audio_device *adev = out->dev;
2456
2457 card_status_t status;
2458 int card;
2459 if (parse_snd_card_status(parms, &card, &status) < 0)
2460 return;
2461
2462 pthread_mutex_lock(&adev->lock);
2463 bool valid_cb = (card == adev->snd_card);
2464 pthread_mutex_unlock(&adev->lock);
2465
2466 if (!valid_cb)
2467 return;
2468
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002469 lock_output_stream(out);
2470 if (out->card_status != status)
2471 out->card_status = status;
2472 pthread_mutex_unlock(&out->lock);
2473
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002474 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2475 use_case_table[out->usecase],
2476 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2477
2478 if (status == CARD_STATUS_OFFLINE)
2479 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002480
2481 return;
2482}
2483
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002484#ifdef NO_AUDIO_OUT
2485static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002486 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002487{
2488 struct stream_out *out = (struct stream_out *)stream;
2489
2490 /* No Output device supported other than BT for playback.
2491 * Sleep for the amount of buffer duration
2492 */
Eric Laurenta1478072015-09-21 17:21:52 -07002493 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002494 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2495 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002496 out_get_sample_rate(&out->stream.common));
2497 pthread_mutex_unlock(&out->lock);
2498 return bytes;
2499}
2500#endif
2501
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002502static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2503 size_t bytes)
2504{
2505 struct stream_out *out = (struct stream_out *)stream;
2506 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002507 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002508 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002509
Eric Laurenta1478072015-09-21 17:21:52 -07002510 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002511 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07002512 const size_t frame_size = audio_stream_out_frame_size(stream);
2513 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002514
Eric Laurent0e46adf2016-12-16 12:49:24 -08002515 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2516 error_code = ERROR_CODE_WRITE;
2517 goto exit;
2518 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002519 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002520 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002521 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002522 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002523 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002524 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002525 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002526 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002527 goto exit;
2528 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002529
2530 if (last_known_cal_step != -1) {
2531 ALOGD("%s: retry previous failed cal level set", __func__);
2532 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2533 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002534 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002535
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002536 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002537 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002538 if (out->send_new_metadata) {
2539 ALOGVV("send new gapless metadata");
2540 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2541 out->send_new_metadata = 0;
2542 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002543 unsigned int avail;
2544 struct timespec tstamp;
2545 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2546 /* Do not limit write size if the available frames count is unknown */
2547 if (ret != 0) {
2548 avail = bytes;
2549 }
2550 if (avail == 0) {
2551 ret = 0;
2552 } else {
2553 if (avail > bytes) {
2554 avail = bytes;
2555 }
2556 ret = compress_write(out->compr, buffer, avail);
2557 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2558 __func__, avail, ret);
2559 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002560
Eric Laurent6e895242013-09-05 16:10:57 -07002561 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002562 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2563 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002564 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002565 compress_start(out->compr);
2566 out->playback_started = 1;
2567 out->offload_state = OFFLOAD_STATE_PLAYING;
2568 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002569 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002570 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002571 } else {
2572 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002573 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002574 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002575 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002576 return ret;
2577 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002578 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002579 if (out->pcm) {
2580 if (out->muted)
2581 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002582
Eric Laurent0e46adf2016-12-16 12:49:24 -08002583 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002584
Haynes Mathew George03c40102016-01-29 17:57:48 -08002585 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2586 out->config.rate;
2587 request_out_focus(out, ns);
2588
2589 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2590 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002591 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002592 else
2593 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002594
Haynes Mathew George03c40102016-01-29 17:57:48 -08002595 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002596 } else {
2597 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002598 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002599 }
2600
2601exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002602 // For PCM we always consume the buffer and return #bytes regardless of ret.
2603 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07002604 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07002605 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002606 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07002607
Andy Hung7401c7c2016-09-21 12:41:21 -07002608 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07002609 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07002610 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2611 ALOGE_IF(out->pcm != NULL,
2612 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07002613 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002614 // usleep not guaranteed for values over 1 second but we don't limit here.
2615 }
2616 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002617
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002618 pthread_mutex_unlock(&out->lock);
2619
2620 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002621 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002622 if (sleeptime_us != 0)
2623 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002624 }
2625 return bytes;
2626}
2627
2628static int out_get_render_position(const struct audio_stream_out *stream,
2629 uint32_t *dsp_frames)
2630{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002631 struct stream_out *out = (struct stream_out *)stream;
2632 *dsp_frames = 0;
2633 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002634 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002635 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002636 unsigned long frames = 0;
2637 // TODO: check return value
2638 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2639 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002640 ALOGVV("%s rendered frames %d sample_rate %d",
2641 __func__, *dsp_frames, out->sample_rate);
2642 }
2643 pthread_mutex_unlock(&out->lock);
2644 return 0;
2645 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002646 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002647}
2648
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002649static int out_add_audio_effect(const struct audio_stream *stream __unused,
2650 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002651{
2652 return 0;
2653}
2654
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002655static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2656 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002657{
2658 return 0;
2659}
2660
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002661static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2662 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002663{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002664 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002665}
2666
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002667static int out_get_presentation_position(const struct audio_stream_out *stream,
2668 uint64_t *frames, struct timespec *timestamp)
2669{
2670 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002671 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07002672 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002673
Eric Laurenta1478072015-09-21 17:21:52 -07002674 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002675
Eric Laurent949a0892013-09-20 09:20:13 -07002676 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2677 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002678 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002679 compress_get_tstamp(out->compr, &dsp_frames,
2680 &out->sample_rate);
2681 ALOGVV("%s rendered frames %ld sample_rate %d",
2682 __func__, dsp_frames, out->sample_rate);
2683 *frames = dsp_frames;
2684 ret = 0;
2685 /* this is the best we can do */
2686 clock_gettime(CLOCK_MONOTONIC, timestamp);
2687 }
2688 } else {
2689 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002690 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002691 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2692 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002693 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002694 // This adjustment accounts for buffering after app processor.
2695 // It is based on estimated DSP latency per use case, rather than exact.
2696 signed_frames -=
2697 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2698
Eric Laurent949a0892013-09-20 09:20:13 -07002699 // It would be unusual for this value to be negative, but check just in case ...
2700 if (signed_frames >= 0) {
2701 *frames = signed_frames;
2702 ret = 0;
2703 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002704 }
2705 }
2706 }
2707
2708 pthread_mutex_unlock(&out->lock);
2709
2710 return ret;
2711}
2712
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002713static int out_set_callback(struct audio_stream_out *stream,
2714 stream_callback_t callback, void *cookie)
2715{
2716 struct stream_out *out = (struct stream_out *)stream;
2717
2718 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002719 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002720 out->offload_callback = callback;
2721 out->offload_cookie = cookie;
2722 pthread_mutex_unlock(&out->lock);
2723 return 0;
2724}
2725
2726static int out_pause(struct audio_stream_out* stream)
2727{
2728 struct stream_out *out = (struct stream_out *)stream;
2729 int status = -ENOSYS;
2730 ALOGV("%s", __func__);
2731 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002732 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002733 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2734 status = compress_pause(out->compr);
2735 out->offload_state = OFFLOAD_STATE_PAUSED;
2736 }
2737 pthread_mutex_unlock(&out->lock);
2738 }
2739 return status;
2740}
2741
2742static int out_resume(struct audio_stream_out* stream)
2743{
2744 struct stream_out *out = (struct stream_out *)stream;
2745 int status = -ENOSYS;
2746 ALOGV("%s", __func__);
2747 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2748 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002749 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002750 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2751 status = compress_resume(out->compr);
2752 out->offload_state = OFFLOAD_STATE_PLAYING;
2753 }
2754 pthread_mutex_unlock(&out->lock);
2755 }
2756 return status;
2757}
2758
2759static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2760{
2761 struct stream_out *out = (struct stream_out *)stream;
2762 int status = -ENOSYS;
2763 ALOGV("%s", __func__);
2764 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002765 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002766 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2767 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2768 else
2769 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2770 pthread_mutex_unlock(&out->lock);
2771 }
2772 return status;
2773}
2774
2775static int out_flush(struct audio_stream_out* stream)
2776{
2777 struct stream_out *out = (struct stream_out *)stream;
2778 ALOGV("%s", __func__);
2779 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002780 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002781 stop_compressed_output_l(out);
2782 pthread_mutex_unlock(&out->lock);
2783 return 0;
2784 }
2785 return -ENOSYS;
2786}
2787
Eric Laurent0e46adf2016-12-16 12:49:24 -08002788static int out_stop(const struct audio_stream_out* stream)
2789{
2790 struct stream_out *out = (struct stream_out *)stream;
2791 struct audio_device *adev = out->dev;
2792 int ret = -ENOSYS;
2793
2794 ALOGV("%s", __func__);
2795 pthread_mutex_lock(&adev->lock);
2796 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2797 out->playback_started && out->pcm != NULL) {
2798 pcm_stop(out->pcm);
2799 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08002800 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002801 }
2802 pthread_mutex_unlock(&adev->lock);
2803 return ret;
2804}
2805
2806static int out_start(const struct audio_stream_out* stream)
2807{
2808 struct stream_out *out = (struct stream_out *)stream;
2809 struct audio_device *adev = out->dev;
2810 int ret = -ENOSYS;
2811
2812 ALOGV("%s", __func__);
2813 pthread_mutex_lock(&adev->lock);
2814 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2815 !out->playback_started && out->pcm != NULL) {
2816 ret = start_output_stream(out);
2817 if (ret == 0) {
2818 out->playback_started = true;
2819 }
2820 }
2821 pthread_mutex_unlock(&adev->lock);
2822 return ret;
2823}
2824
Phil Burkbc991042017-02-24 08:06:44 -08002825/*
2826 * Modify config->period_count based on min_size_frames
2827 */
2828static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
2829{
2830 int periodCountRequested = (min_size_frames + config->period_size - 1)
2831 / config->period_size;
2832 int periodCount = MMAP_PERIOD_COUNT_MIN;
2833
2834 ALOGV("%s original config.period_size = %d config.period_count = %d",
2835 __func__, config->period_size, config->period_count);
2836
2837 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
2838 periodCount *= 2;
2839 }
2840 config->period_count = periodCount;
2841
2842 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
2843}
2844
Eric Laurent0e46adf2016-12-16 12:49:24 -08002845static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2846 int32_t min_size_frames,
2847 struct audio_mmap_buffer_info *info)
2848{
2849 struct stream_out *out = (struct stream_out *)stream;
2850 struct audio_device *adev = out->dev;
2851 int ret = 0;
2852 unsigned int offset1;
2853 unsigned int frames1;
2854 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07002855 uint32_t mmap_size;
2856 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002857
2858 ALOGV("%s", __func__);
2859 pthread_mutex_lock(&adev->lock);
2860
2861 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002862 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002863 ret = -EINVAL;
2864 goto exit;
2865 }
2866 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08002867 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002868 ret = -ENOSYS;
2869 goto exit;
2870 }
2871 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
2872 if (out->pcm_device_id < 0) {
2873 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2874 __func__, out->pcm_device_id, out->usecase);
2875 ret = -EINVAL;
2876 goto exit;
2877 }
Phil Burkbc991042017-02-24 08:06:44 -08002878
2879 adjust_mmap_period_count(&out->config, min_size_frames);
2880
Eric Laurent0e46adf2016-12-16 12:49:24 -08002881 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2882 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
2883 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2884 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
2885 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2886 step = "open";
2887 ret = -ENODEV;
2888 goto exit;
2889 }
2890 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
2891 if (ret < 0) {
2892 step = "begin";
2893 goto exit;
2894 }
2895 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07002896 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002897 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07002898 ret = platform_get_mmap_data_fd(adev->platform,
2899 out->pcm_device_id, 0 /*playback*/,
2900 &info->shared_memory_fd,
2901 &mmap_size);
2902 if (ret < 0) {
2903 // Fall back to non exclusive mode
2904 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
2905 } else {
2906 if (mmap_size < buffer_size) {
2907 step = "mmap";
2908 goto exit;
2909 }
2910 // FIXME: indicate exclusive mode support by returning a negative buffer size
2911 info->buffer_size_frames *= -1;
2912 }
2913 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002914
2915 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
2916 if (ret < 0) {
2917 step = "commit";
2918 goto exit;
2919 }
Phil Burkbc991042017-02-24 08:06:44 -08002920
2921 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002922 ret = 0;
2923
2924 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
2925 __func__, info->shared_memory_address, info->buffer_size_frames);
2926
2927exit:
2928 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002929 if (out->pcm == NULL) {
2930 ALOGE("%s: %s - %d", __func__, step, ret);
2931 } else {
2932 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08002933 pcm_close(out->pcm);
2934 out->pcm = NULL;
2935 }
2936 }
2937 pthread_mutex_unlock(&adev->lock);
2938 return ret;
2939}
2940
2941static int out_get_mmap_position(const struct audio_stream_out *stream,
2942 struct audio_mmap_position *position)
2943{
2944 struct stream_out *out = (struct stream_out *)stream;
2945 ALOGVV("%s", __func__);
2946 if (position == NULL) {
2947 return -EINVAL;
2948 }
2949 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
2950 return -ENOSYS;
2951 }
2952 if (out->pcm == NULL) {
2953 return -ENOSYS;
2954 }
2955
2956 struct timespec ts = { 0, 0 };
2957 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
2958 if (ret < 0) {
2959 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2960 return ret;
2961 }
Andy Hungfc044e12017-03-20 09:24:22 -07002962 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002963 return 0;
2964}
2965
2966
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002967/** audio_stream_in implementation **/
2968static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2969{
2970 struct stream_in *in = (struct stream_in *)stream;
2971
2972 return in->config.rate;
2973}
2974
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002975static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002976{
2977 return -ENOSYS;
2978}
2979
2980static size_t in_get_buffer_size(const struct audio_stream *stream)
2981{
2982 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002983 return in->config.period_size * in->af_period_multiplier *
2984 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002985}
2986
2987static uint32_t in_get_channels(const struct audio_stream *stream)
2988{
2989 struct stream_in *in = (struct stream_in *)stream;
2990
2991 return in->channel_mask;
2992}
2993
vivek mehta4ed66e62016-04-15 23:33:34 -07002994static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002995{
vivek mehta4ed66e62016-04-15 23:33:34 -07002996 struct stream_in *in = (struct stream_in *)stream;
2997 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002998}
2999
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003000static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003001{
3002 return -ENOSYS;
3003}
3004
3005static int in_standby(struct audio_stream *stream)
3006{
3007 struct stream_in *in = (struct stream_in *)stream;
3008 struct audio_device *adev = in->dev;
3009 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003010 bool do_stop = true;
3011
Eric Laurent994a6932013-07-17 11:51:42 -07003012 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003013
3014 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003015
3016 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003017 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003018 audio_extn_sound_trigger_stop_lab(in);
3019 in->standby = true;
3020 }
3021
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003022 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003023 if (adev->adm_deregister_stream)
3024 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3025
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003026 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003027 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003028 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003029 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003030 in->capture_started = false;
3031 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003032 if (in->pcm) {
3033 pcm_close(in->pcm);
3034 in->pcm = NULL;
3035 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003036 adev->enable_voicerx = false;
3037 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003038 if (do_stop) {
3039 status = stop_input_stream(in);
3040 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003041 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003042 }
3043 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003044 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003045 return status;
3046}
3047
Andy Hungd13f0d32017-06-12 13:58:37 -07003048static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003049{
Andy Hungd13f0d32017-06-12 13:58:37 -07003050 struct stream_in *in = (struct stream_in *)stream;
3051
3052 // We try to get the lock for consistency,
3053 // but it isn't necessary for these variables.
3054 // If we're not in standby, we may be blocked on a read.
3055 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3056 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3057 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3058 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3059
3060 if (locked) {
3061 pthread_mutex_unlock(&in->lock);
3062 }
3063
3064 // dump error info
3065 (void)error_log_dump(
3066 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003067 return 0;
3068}
3069
3070static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3071{
3072 struct stream_in *in = (struct stream_in *)stream;
3073 struct audio_device *adev = in->dev;
3074 struct str_parms *parms;
3075 char *str;
3076 char value[32];
3077 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003078 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003079
Eric Laurent994a6932013-07-17 11:51:42 -07003080 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003081 parms = str_parms_create_str(kvpairs);
3082
3083 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3084
Eric Laurenta1478072015-09-21 17:21:52 -07003085 lock_input_stream(in);
3086
Eric Laurent150dbfe2013-02-27 14:31:02 -08003087 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003088 if (ret >= 0) {
3089 val = atoi(value);
3090 /* no audio source uses val == 0 */
3091 if ((in->source != val) && (val != 0)) {
3092 in->source = val;
3093 }
3094 }
3095
3096 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003097
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003098 if (ret >= 0) {
3099 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003100 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003101 in->device = val;
3102 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08003103 if (!in->standby) {
3104 ALOGV("update input routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003105 // inform adm before actual routing to prevent glitches.
3106 if (adev->adm_on_routing_change) {
3107 adev->adm_on_routing_change(adev->adm_data,
3108 in->capture_handle);
3109 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003110 select_devices(adev, in->usecase);
3111 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003112 }
3113 }
3114
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003115 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003116 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003117
3118 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003119 ALOGV("%s: exit: status(%d)", __func__, status);
3120 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003121}
3122
Haynes Mathew George569b7482017-05-08 14:44:27 -07003123static char* in_get_parameters(const struct audio_stream *stream,
3124 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003125{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003126 struct stream_in *in = (struct stream_in *)stream;
3127 struct str_parms *query = str_parms_create_str(keys);
3128 char *str;
3129 struct str_parms *reply = str_parms_create();
3130 bool replied = false;
3131
3132 ALOGV("%s: enter: keys - %s", __func__, keys);
3133 replied |= stream_get_parameter_channels(query, reply,
3134 &in->supported_channel_masks[0]);
3135 replied |= stream_get_parameter_formats(query, reply,
3136 &in->supported_formats[0]);
3137 replied |= stream_get_parameter_rates(query, reply,
3138 &in->supported_sample_rates[0]);
3139 if (replied) {
3140 str = str_parms_to_str(reply);
3141 } else {
3142 str = strdup(keys);
3143 }
3144 str_parms_destroy(query);
3145 str_parms_destroy(reply);
3146 ALOGV("%s: exit: returns - %s", __func__, str);
3147 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003148}
3149
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003150static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003151{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003152 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003153}
3154
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003155static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3156{
3157 if (!stream || !parms)
3158 return;
3159
3160 struct stream_in *in = (struct stream_in *)stream;
3161 struct audio_device *adev = in->dev;
3162
3163 card_status_t status;
3164 int card;
3165 if (parse_snd_card_status(parms, &card, &status) < 0)
3166 return;
3167
3168 pthread_mutex_lock(&adev->lock);
3169 bool valid_cb = (card == adev->snd_card);
3170 pthread_mutex_unlock(&adev->lock);
3171
3172 if (!valid_cb)
3173 return;
3174
3175 lock_input_stream(in);
3176 if (in->card_status != status)
3177 in->card_status = status;
3178 pthread_mutex_unlock(&in->lock);
3179
3180 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3181 use_case_table[in->usecase],
3182 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3183
3184 // a better solution would be to report error back to AF and let
3185 // it put the stream to standby
3186 if (status == CARD_STATUS_OFFLINE)
3187 in_standby(&in->stream.common);
3188
3189 return;
3190}
3191
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003192static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3193 size_t bytes)
3194{
3195 struct stream_in *in = (struct stream_in *)stream;
3196 struct audio_device *adev = in->dev;
3197 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003198 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003199 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003200
Eric Laurenta1478072015-09-21 17:21:52 -07003201 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003202 const size_t frame_size = audio_stream_in_frame_size(stream);
3203 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003204
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003205 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003206 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003207 /* Read from sound trigger HAL */
3208 audio_extn_sound_trigger_read(in, buffer, bytes);
3209 pthread_mutex_unlock(&in->lock);
3210 return bytes;
3211 }
3212
Eric Laurent0e46adf2016-12-16 12:49:24 -08003213 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3214 ret = -ENOSYS;
3215 goto exit;
3216 }
3217
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003218 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003219 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003220 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003221 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003222 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003223 goto exit;
3224 }
3225 in->standby = 0;
3226 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003227
Andy Hungd13f0d32017-06-12 13:58:37 -07003228 // errors that occur here are read errors.
3229 error_code = ERROR_CODE_READ;
3230
Haynes Mathew George03c40102016-01-29 17:57:48 -08003231 //what's the duration requested by the client?
3232 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3233 in->config.rate;
3234 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003235
Haynes Mathew George03c40102016-01-29 17:57:48 -08003236 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003237 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003238 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003239 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003240 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003241 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003242 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003243 if (ret < 0) {
3244 ALOGE("Failed to read w/err %s", strerror(errno));
3245 ret = -errno;
3246 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003247 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3248 if (bytes % 4 == 0) {
3249 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3250 int_buf_stream = buffer;
3251 for (size_t itt=0; itt < bytes/4 ; itt++) {
3252 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003253 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003254 } else {
3255 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3256 ret = -EINVAL;
3257 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003258 }
3259 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003260 }
3261
Haynes Mathew George03c40102016-01-29 17:57:48 -08003262 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003263
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003264 /*
3265 * Instead of writing zeroes here, we could trust the hardware
3266 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003267 * 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 -08003268 */
Andy Hungd13f0d32017-06-12 13:58:37 -07003269 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003270 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07003271 in->frames_muted += frames;
3272 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003273
3274exit:
3275 pthread_mutex_unlock(&in->lock);
3276
3277 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07003278 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003279 in_standby(&in->stream.common);
3280 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003281 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003282 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07003283 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08003284 }
3285 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003286 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003287 }
3288 return bytes;
3289}
3290
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003291static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003292{
3293 return 0;
3294}
3295
Andy Hung6ebe5962016-01-15 17:46:57 -08003296static int in_get_capture_position(const struct audio_stream_in *stream,
3297 int64_t *frames, int64_t *time)
3298{
3299 if (stream == NULL || frames == NULL || time == NULL) {
3300 return -EINVAL;
3301 }
3302 struct stream_in *in = (struct stream_in *)stream;
3303 int ret = -ENOSYS;
3304
3305 lock_input_stream(in);
3306 if (in->pcm) {
3307 struct timespec timestamp;
3308 unsigned int avail;
3309 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3310 *frames = in->frames_read + avail;
3311 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3312 ret = 0;
3313 }
3314 }
3315 pthread_mutex_unlock(&in->lock);
3316 return ret;
3317}
3318
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003319static int add_remove_audio_effect(const struct audio_stream *stream,
3320 effect_handle_t effect,
3321 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003322{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003323 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003324 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003325 int status = 0;
3326 effect_descriptor_t desc;
3327
3328 status = (*effect)->get_descriptor(effect, &desc);
3329 if (status != 0)
3330 return status;
3331
Eric Laurenta1478072015-09-21 17:21:52 -07003332 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003333 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003334 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003335 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003336 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003337 in->enable_aec != enable &&
3338 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3339 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003340 if (!enable)
3341 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003342 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3343 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3344 adev->enable_voicerx = enable;
3345 struct audio_usecase *usecase;
3346 struct listnode *node;
3347 list_for_each(node, &adev->usecase_list) {
3348 usecase = node_to_item(node, struct audio_usecase, list);
3349 if (usecase->type == PCM_PLAYBACK) {
3350 select_devices(adev, usecase->id);
3351 break;
3352 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003353 }
3354 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003355 if (!in->standby)
3356 select_devices(in->dev, in->usecase);
3357 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003358 if (in->enable_ns != enable &&
3359 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3360 in->enable_ns = enable;
3361 if (!in->standby)
3362 select_devices(in->dev, in->usecase);
3363 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003364 pthread_mutex_unlock(&in->dev->lock);
3365 pthread_mutex_unlock(&in->lock);
3366
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003367 return 0;
3368}
3369
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003370static int in_add_audio_effect(const struct audio_stream *stream,
3371 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003372{
Eric Laurent994a6932013-07-17 11:51:42 -07003373 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003374 return add_remove_audio_effect(stream, effect, true);
3375}
3376
3377static int in_remove_audio_effect(const struct audio_stream *stream,
3378 effect_handle_t effect)
3379{
Eric Laurent994a6932013-07-17 11:51:42 -07003380 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003381 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003382}
3383
Eric Laurent0e46adf2016-12-16 12:49:24 -08003384static int in_stop(const struct audio_stream_in* stream)
3385{
3386 struct stream_in *in = (struct stream_in *)stream;
3387 struct audio_device *adev = in->dev;
3388
3389 int ret = -ENOSYS;
3390 ALOGV("%s", __func__);
3391 pthread_mutex_lock(&adev->lock);
3392 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3393 in->capture_started && in->pcm != NULL) {
3394 pcm_stop(in->pcm);
3395 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003396 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003397 }
3398 pthread_mutex_unlock(&adev->lock);
3399 return ret;
3400}
3401
3402static int in_start(const struct audio_stream_in* stream)
3403{
3404 struct stream_in *in = (struct stream_in *)stream;
3405 struct audio_device *adev = in->dev;
3406 int ret = -ENOSYS;
3407
3408 ALOGV("%s in %p", __func__, in);
3409 pthread_mutex_lock(&adev->lock);
3410 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3411 !in->capture_started && in->pcm != NULL) {
3412 if (!in->capture_started) {
3413 ret = start_input_stream(in);
3414 if (ret == 0) {
3415 in->capture_started = true;
3416 }
3417 }
3418 }
3419 pthread_mutex_unlock(&adev->lock);
3420 return ret;
3421}
3422
3423static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3424 int32_t min_size_frames,
3425 struct audio_mmap_buffer_info *info)
3426{
3427 struct stream_in *in = (struct stream_in *)stream;
3428 struct audio_device *adev = in->dev;
3429 int ret = 0;
3430 unsigned int offset1;
3431 unsigned int frames1;
3432 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003433 uint32_t mmap_size;
3434 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003435
3436 pthread_mutex_lock(&adev->lock);
3437 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003438
Eric Laurent0e46adf2016-12-16 12:49:24 -08003439 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003440 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003441 ret = -EINVAL;
3442 goto exit;
3443 }
3444 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003445 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003446 ALOGV("%s in %p", __func__, in);
3447 ret = -ENOSYS;
3448 goto exit;
3449 }
3450 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3451 if (in->pcm_device_id < 0) {
3452 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3453 __func__, in->pcm_device_id, in->usecase);
3454 ret = -EINVAL;
3455 goto exit;
3456 }
Phil Burkbc991042017-02-24 08:06:44 -08003457
3458 adjust_mmap_period_count(&in->config, min_size_frames);
3459
Eric Laurent0e46adf2016-12-16 12:49:24 -08003460 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3461 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3462 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3463 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3464 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3465 step = "open";
3466 ret = -ENODEV;
3467 goto exit;
3468 }
3469
3470 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3471 if (ret < 0) {
3472 step = "begin";
3473 goto exit;
3474 }
3475 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003476 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003477 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003478 ret = platform_get_mmap_data_fd(adev->platform,
3479 in->pcm_device_id, 1 /*capture*/,
3480 &info->shared_memory_fd,
3481 &mmap_size);
3482 if (ret < 0) {
3483 // Fall back to non exclusive mode
3484 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3485 } else {
3486 if (mmap_size < buffer_size) {
3487 step = "mmap";
3488 goto exit;
3489 }
3490 // FIXME: indicate exclusive mode support by returning a negative buffer size
3491 info->buffer_size_frames *= -1;
3492 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08003493
Haynes Mathew George96483a22017-03-28 14:52:47 -07003494 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003495
3496 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3497 if (ret < 0) {
3498 step = "commit";
3499 goto exit;
3500 }
3501
Phil Burkbc991042017-02-24 08:06:44 -08003502 in->standby = false;
3503 ret = 0;
3504
Eric Laurent0e46adf2016-12-16 12:49:24 -08003505 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3506 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003507
3508exit:
3509 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003510 if (in->pcm == NULL) {
3511 ALOGE("%s: %s - %d", __func__, step, ret);
3512 } else {
3513 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003514 pcm_close(in->pcm);
3515 in->pcm = NULL;
3516 }
3517 }
3518 pthread_mutex_unlock(&adev->lock);
3519 return ret;
3520}
3521
3522static int in_get_mmap_position(const struct audio_stream_in *stream,
3523 struct audio_mmap_position *position)
3524{
3525 struct stream_in *in = (struct stream_in *)stream;
3526 ALOGVV("%s", __func__);
3527 if (position == NULL) {
3528 return -EINVAL;
3529 }
3530 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
3531 return -ENOSYS;
3532 }
3533 if (in->pcm == NULL) {
3534 return -ENOSYS;
3535 }
3536 struct timespec ts = { 0, 0 };
3537 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
3538 if (ret < 0) {
3539 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3540 return ret;
3541 }
Andy Hungfc044e12017-03-20 09:24:22 -07003542 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003543 return 0;
3544}
3545
3546
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003547static int adev_open_output_stream(struct audio_hw_device *dev,
3548 audio_io_handle_t handle,
3549 audio_devices_t devices,
3550 audio_output_flags_t flags,
3551 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003552 struct audio_stream_out **stream_out,
3553 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003554{
3555 struct audio_device *adev = (struct audio_device *)dev;
3556 struct stream_out *out;
3557 int i, ret;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003558 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
3559 bool is_usb_dev = audio_is_usb_out_device(devices) &&
3560 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
3561 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003562
Eric Laurent994a6932013-07-17 11:51:42 -07003563 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003564 __func__, config->sample_rate, config->channel_mask, devices, flags);
3565 *stream_out = NULL;
3566 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3567
3568 if (devices == AUDIO_DEVICE_NONE)
3569 devices = AUDIO_DEVICE_OUT_SPEAKER;
3570
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003571 out->flags = flags;
3572 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003573 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003574 out->format = config->format;
3575 out->sample_rate = config->sample_rate;
3576 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3577 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003578 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003579
3580 /* Init use case and pcm_config */
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003581 if (audio_is_linear_pcm(out->format) &&
3582 (out->flags == AUDIO_OUTPUT_FLAG_NONE ||
Haynes Mathew George569b7482017-05-08 14:44:27 -07003583 out->flags == AUDIO_OUTPUT_FLAG_DIRECT) && direct_dev) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003584 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003585 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003586 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003587 if (config->sample_rate == 0)
3588 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3589 if (config->channel_mask == 0)
3590 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3591 if (config->format == AUDIO_FORMAT_DEFAULT)
3592 config->format = AUDIO_FORMAT_PCM_16_BIT;
3593 } else if (is_usb_dev) {
3594 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
3595 &config->format,
3596 &out->supported_formats[0],
3597 MAX_SUPPORTED_FORMATS,
3598 &config->channel_mask,
3599 &out->supported_channel_masks[0],
3600 MAX_SUPPORTED_CHANNEL_MASKS,
3601 &config->sample_rate,
3602 &out->supported_sample_rates[0],
3603 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003604 ALOGV("plugged dev USB ret %d", ret);
3605 } else {
3606 ret = -1;
3607 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003608 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003609 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003610 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003611
Haynes Mathew George569b7482017-05-08 14:44:27 -07003612 out->channel_mask = config->channel_mask;
3613 out->sample_rate = config->sample_rate;
3614 out->format = config->format;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003615 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3616 // does this change?
Haynes Mathew George569b7482017-05-08 14:44:27 -07003617 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003618 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003619 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Andy Hung928efbe2017-06-12 14:05:22 -07003620 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
3621 audio_bytes_per_sample(config->format));
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003622 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003623 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003624 pthread_mutex_lock(&adev->lock);
3625 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3626 pthread_mutex_unlock(&adev->lock);
3627
3628 // reject offload during card offline to allow
3629 // fallback to s/w paths
3630 if (offline) {
3631 ret = -ENODEV;
3632 goto error_open;
3633 }
3634
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003635 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3636 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3637 ALOGE("%s: Unsupported Offload information", __func__);
3638 ret = -EINVAL;
3639 goto error_open;
3640 }
3641 if (!is_supported_format(config->offload_info.format)) {
3642 ALOGE("%s: Unsupported audio format", __func__);
3643 ret = -EINVAL;
3644 goto error_open;
3645 }
3646
3647 out->compr_config.codec = (struct snd_codec *)
3648 calloc(1, sizeof(struct snd_codec));
3649
3650 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3651 if (config->offload_info.channel_mask)
3652 out->channel_mask = config->offload_info.channel_mask;
3653 else if (config->channel_mask)
3654 out->channel_mask = config->channel_mask;
3655 out->format = config->offload_info.format;
3656 out->sample_rate = config->offload_info.sample_rate;
3657
3658 out->stream.set_callback = out_set_callback;
3659 out->stream.pause = out_pause;
3660 out->stream.resume = out_resume;
3661 out->stream.drain = out_drain;
3662 out->stream.flush = out_flush;
3663
3664 out->compr_config.codec->id =
3665 get_snd_codec_id(config->offload_info.format);
3666 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3667 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07003668 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003669 out->compr_config.codec->bit_rate =
3670 config->offload_info.bit_rate;
3671 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003672 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003673 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3674
3675 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3676 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003677
3678 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003679 create_offload_callback_thread(out);
3680 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3681 __func__, config->offload_info.version,
3682 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003683 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07003684 switch (config->sample_rate) {
3685 case 8000:
3686 case 16000:
3687 case 48000:
3688 out->sample_rate = config->sample_rate;
3689 break;
3690 default:
3691 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003692 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003693 out->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003694 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3695 out->config = pcm_config_afe_proxy_playback;
3696 adev->voice_tx_output = out;
David Lin6b00c232017-07-26 00:20:16 -07003697 } else if (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT |
3698 AUDIO_OUTPUT_FLAG_VOIP_RX)) {
vivek mehtaa68fea62017-06-08 19:04:02 -07003699 uint32_t buffer_size, frame_size;
3700 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
3701 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
3702 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
3703 out->config = pcm_config_voip;
3704 out->config.format = pcm_format_from_audio_format(config->format);
3705 out->config.rate = config->sample_rate;
3706 out->config.channels =
3707 audio_channel_count_from_out_mask(config->channel_mask);
3708 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
3709 config->sample_rate,
3710 config->format,
3711 out->config.channels,
3712 false /*is_low_latency*/);
3713 frame_size = audio_bytes_per_sample(config->format) * out->config.channels;
3714 out->config.period_size = buffer_size / frame_size;
3715 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
3716 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003717 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003718 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3719 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3720 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003721 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
3722 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3723 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003724 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3725 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003726 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003727 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003728 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3729 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3730 out->config = pcm_config_mmap_playback;
3731 out->stream.start = out_start;
3732 out->stream.stop = out_stop;
3733 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3734 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003735 } else {
3736 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3737 out->config = pcm_config_low_latency;
3738 }
3739 if (config->format != audio_format_from_pcm_format(out->config.format)) {
Haynes Mathew Georgedf0f8862017-06-28 13:36:40 -07003740 out->config.format = pcm_format_from_audio_format(config->format);
Andy Hung6fcba9c2014-03-18 11:53:32 -07003741 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003742 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003743 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003744
3745 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
3746 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
3747 (config->channel_mask != 0 && config->channel_mask != out->channel_mask)) {
3748 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
3749 __func__, config->sample_rate, config->format, config->channel_mask);
3750 config->sample_rate = out->sample_rate;
3751 config->format = out->format;
3752 config->channel_mask = out->channel_mask;
3753 ret = -EINVAL;
3754 goto error_open;
3755 }
3756
Andy Hung6fcba9c2014-03-18 11:53:32 -07003757 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3758 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003759
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003760 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003761 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003762 adev->primary_output = out;
3763 else {
3764 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003765 ret = -EEXIST;
3766 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003767 }
3768 }
3769
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003770 /* Check if this usecase is already existing */
3771 pthread_mutex_lock(&adev->lock);
3772 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3773 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003774 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003775 ret = -EEXIST;
3776 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003777 }
3778 pthread_mutex_unlock(&adev->lock);
3779
3780 out->stream.common.get_sample_rate = out_get_sample_rate;
3781 out->stream.common.set_sample_rate = out_set_sample_rate;
3782 out->stream.common.get_buffer_size = out_get_buffer_size;
3783 out->stream.common.get_channels = out_get_channels;
3784 out->stream.common.get_format = out_get_format;
3785 out->stream.common.set_format = out_set_format;
3786 out->stream.common.standby = out_standby;
3787 out->stream.common.dump = out_dump;
3788 out->stream.common.set_parameters = out_set_parameters;
3789 out->stream.common.get_parameters = out_get_parameters;
3790 out->stream.common.add_audio_effect = out_add_audio_effect;
3791 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3792 out->stream.get_latency = out_get_latency;
3793 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003794#ifdef NO_AUDIO_OUT
3795 out->stream.write = out_write_for_no_output;
3796#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003797 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003798#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003799 out->stream.get_render_position = out_get_render_position;
3800 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003801 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003802
Eric Laurent0e46adf2016-12-16 12:49:24 -08003803 if (out->realtime)
3804 out->af_period_multiplier = af_period_multiplier;
3805 else
3806 out->af_period_multiplier = 1;
3807
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003808 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003809 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003810 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003811
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003812 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003813 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003814 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3815
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003816 config->format = out->stream.common.get_format(&out->stream.common);
3817 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3818 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3819
Andy Hunga452b0a2017-03-15 14:51:15 -07003820 out->error_log = error_log_create(
3821 ERROR_LOG_ENTRIES,
3822 1000000000 /* aggregate consecutive identical errors within one second in ns */);
3823
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003824 /*
3825 By locking output stream before registering, we allow the callback
3826 to update stream's state only after stream's initial state is set to
3827 adev state.
3828 */
3829 lock_output_stream(out);
3830 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3831 pthread_mutex_lock(&adev->lock);
3832 out->card_status = adev->card_status;
3833 pthread_mutex_unlock(&adev->lock);
3834 pthread_mutex_unlock(&out->lock);
3835
vivek mehta4a824772017-06-08 19:05:49 -07003836 stream_app_type_cfg_init(&out->app_type_cfg);
3837
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003838 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003839
Eric Laurent994a6932013-07-17 11:51:42 -07003840 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003841 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003842
3843error_open:
3844 free(out);
3845 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003846 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003847 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003848}
3849
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003850static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003851 struct audio_stream_out *stream)
3852{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003853 struct stream_out *out = (struct stream_out *)stream;
3854 struct audio_device *adev = out->dev;
3855
Eric Laurent994a6932013-07-17 11:51:42 -07003856 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003857
3858 // must deregister from sndmonitor first to prevent races
3859 // between the callback and close_stream
3860 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003861 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003862 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3863 destroy_offload_callback_thread(out);
3864
3865 if (out->compr_config.codec != NULL)
3866 free(out->compr_config.codec);
3867 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003868
3869 if (adev->voice_tx_output == out)
3870 adev->voice_tx_output = NULL;
3871
Andy Hunga452b0a2017-03-15 14:51:15 -07003872 error_log_destroy(out->error_log);
3873 out->error_log = NULL;
3874
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003875 pthread_cond_destroy(&out->cond);
3876 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003877 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003878 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003879}
3880
3881static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3882{
3883 struct audio_device *adev = (struct audio_device *)dev;
3884 struct str_parms *parms;
3885 char *str;
3886 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003887 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003888 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003889 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003890
Joe Onorato188b6222016-03-01 11:02:27 -08003891 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003892
3893 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003894
3895 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003896 status = voice_set_parameters(adev, parms);
3897 if (status != 0) {
3898 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003899 }
3900
3901 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3902 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003903 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003904 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3905 adev->bluetooth_nrec = true;
3906 else
3907 adev->bluetooth_nrec = false;
3908 }
3909
3910 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3911 if (ret >= 0) {
3912 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3913 adev->screen_off = false;
3914 else
3915 adev->screen_off = true;
3916 }
3917
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003918 ret = str_parms_get_int(parms, "rotation", &val);
3919 if (ret >= 0) {
3920 bool reverse_speakers = false;
3921 switch(val) {
3922 // FIXME: note that the code below assumes that the speakers are in the correct placement
3923 // relative to the user when the device is rotated 90deg from its default rotation. This
3924 // assumption is device-specific, not platform-specific like this code.
3925 case 270:
3926 reverse_speakers = true;
3927 break;
3928 case 0:
3929 case 90:
3930 case 180:
3931 break;
3932 default:
3933 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003934 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003935 }
Eric Laurent03f09432014-03-25 18:09:11 -07003936 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07003937 // check and set swap
3938 // - check if orientation changed and speaker active
3939 // - set rotation and cache the rotation value
3940 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003941 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003942 }
3943
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003944 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3945 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003946 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003947 }
3948
David Linee3fe402017-03-13 10:00:42 -07003949 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3950 if (ret >= 0) {
3951 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07003952 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003953 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3954 if (ret >= 0) {
3955 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07003956 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003957 }
Eric Laurent99dab492017-06-17 15:19:08 -07003958 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003959 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3960 if (ret >= 0) {
3961 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07003962 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003963 }
3964 }
3965 }
3966
3967 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3968 if (ret >= 0) {
3969 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07003970 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003971 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3972 if (ret >= 0) {
3973 const int card = atoi(value);
3974
Eric Laurent99dab492017-06-17 15:19:08 -07003975 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003976 }
Eric Laurent99dab492017-06-17 15:19:08 -07003977 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003978 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3979 if (ret >= 0) {
3980 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07003981 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003982 }
3983 }
3984 }
3985
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08003986 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003987done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003988 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003989 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07003990 ALOGV("%s: exit with code(%d)", __func__, status);
3991 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003992}
3993
3994static char* adev_get_parameters(const struct audio_hw_device *dev,
3995 const char *keys)
3996{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003997 struct audio_device *adev = (struct audio_device *)dev;
3998 struct str_parms *reply = str_parms_create();
3999 struct str_parms *query = str_parms_create_str(keys);
4000 char *str;
4001
4002 pthread_mutex_lock(&adev->lock);
4003
4004 voice_get_parameters(adev, query, reply);
4005 str = str_parms_to_str(reply);
4006 str_parms_destroy(query);
4007 str_parms_destroy(reply);
4008
4009 pthread_mutex_unlock(&adev->lock);
4010 ALOGV("%s: exit: returns - %s", __func__, str);
4011 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004012}
4013
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004014static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004015{
4016 return 0;
4017}
4018
Haynes Mathew George5191a852013-09-11 14:19:36 -07004019static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4020{
4021 int ret;
4022 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004023
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004024 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4025
Haynes Mathew George5191a852013-09-11 14:19:36 -07004026 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004027 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004028 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004029
Haynes Mathew George5191a852013-09-11 14:19:36 -07004030 return ret;
4031}
4032
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004033static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004034{
4035 return -ENOSYS;
4036}
4037
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004038static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4039 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004040{
4041 return -ENOSYS;
4042}
4043
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004044static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004045{
4046 return -ENOSYS;
4047}
4048
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004049static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004050{
4051 return -ENOSYS;
4052}
4053
4054static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4055{
4056 struct audio_device *adev = (struct audio_device *)dev;
4057
4058 pthread_mutex_lock(&adev->lock);
4059 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004060 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004061 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004062 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4063 voice_is_in_call(adev)) {
4064 voice_stop_call(adev);
4065 adev->current_call_output = NULL;
4066 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004067 }
4068 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004069
4070 audio_extn_extspk_set_mode(adev->extspk, mode);
4071
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004072 return 0;
4073}
4074
4075static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4076{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004077 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004078 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004079
Eric Laurent2bafff12016-03-17 12:17:23 -07004080 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004081 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004082 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4083 ret = audio_extn_hfp_set_mic_mute(adev, state);
4084 } else {
4085 ret = voice_set_mic_mute(adev, state);
4086 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004087 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004088 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004089
4090 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004091}
4092
4093static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4094{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004095 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004096 return 0;
4097}
4098
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004099static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004100 const struct audio_config *config)
4101{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004102 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004103
Eric Laurent74b55762017-07-09 17:04:53 -07004104 /* Don't know if USB HIFI in this context so use true to be conservative */
4105 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4106 true /*is_usb_hifi */) != 0)
4107 return 0;
4108
vivek mehtaa68fea62017-06-08 19:04:02 -07004109 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4110 config->sample_rate, config->format,
4111 channel_count,
4112 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004113}
4114
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004115static bool adev_input_allow_hifi_record(struct audio_device *adev,
4116 audio_devices_t devices,
4117 audio_input_flags_t flags,
4118 audio_source_t source) {
4119 const bool allowed = true;
4120
4121 if (!audio_is_usb_in_device(devices))
4122 return !allowed;
4123
4124 switch (flags) {
4125 case AUDIO_INPUT_FLAG_NONE:
4126 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4127 break;
4128 default:
4129 return !allowed;
4130 }
4131
4132 switch (source) {
4133 case AUDIO_SOURCE_DEFAULT:
4134 case AUDIO_SOURCE_MIC:
4135 case AUDIO_SOURCE_UNPROCESSED:
4136 break;
4137 default:
4138 return !allowed;
4139 }
4140
4141 switch (adev->mode) {
4142 case 0:
4143 break;
4144 default:
4145 return !allowed;
4146 }
4147
4148 return allowed;
4149}
4150
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004151static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004152 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004153 audio_devices_t devices,
4154 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004155 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004156 audio_input_flags_t flags,
4157 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004158 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004159{
4160 struct audio_device *adev = (struct audio_device *)dev;
4161 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004162 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004163 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004164 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004165 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004166 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4167 devices,
4168 flags,
4169 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004170 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004171 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004172
Eric Laurent74b55762017-07-09 17:04:53 -07004173 if (!(is_usb_dev && may_use_hifi_record)) {
4174 if (config->sample_rate == 0)
4175 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4176 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4177 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4178 if (config->format == AUDIO_FORMAT_DEFAULT)
4179 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004180
Eric Laurent74b55762017-07-09 17:04:53 -07004181 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
4182
4183 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
4184 return -EINVAL;
4185 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004186
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004187 if (audio_extn_tfa_98xx_is_supported() &&
4188 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004189 return -EINVAL;
4190
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004191 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4192
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004193 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004194 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004195
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004196 in->stream.common.get_sample_rate = in_get_sample_rate;
4197 in->stream.common.set_sample_rate = in_set_sample_rate;
4198 in->stream.common.get_buffer_size = in_get_buffer_size;
4199 in->stream.common.get_channels = in_get_channels;
4200 in->stream.common.get_format = in_get_format;
4201 in->stream.common.set_format = in_set_format;
4202 in->stream.common.standby = in_standby;
4203 in->stream.common.dump = in_dump;
4204 in->stream.common.set_parameters = in_set_parameters;
4205 in->stream.common.get_parameters = in_get_parameters;
4206 in->stream.common.add_audio_effect = in_add_audio_effect;
4207 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4208 in->stream.set_gain = in_set_gain;
4209 in->stream.read = in_read;
4210 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08004211 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004212
4213 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004214 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004215 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004216 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004217 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004218 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004219
Haynes Mathew George569b7482017-05-08 14:44:27 -07004220 if (is_usb_dev && may_use_hifi_record) {
4221 /* HiFi record selects an appropriate format, channel, rate combo
4222 depending on sink capabilities*/
4223 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
4224 &config->format,
4225 &in->supported_formats[0],
4226 MAX_SUPPORTED_FORMATS,
4227 &config->channel_mask,
4228 &in->supported_channel_masks[0],
4229 MAX_SUPPORTED_CHANNEL_MASKS,
4230 &config->sample_rate,
4231 &in->supported_sample_rates[0],
4232 MAX_SUPPORTED_SAMPLE_RATES);
4233 if (ret != 0) {
4234 ret = -EINVAL;
4235 goto err_open;
4236 }
Eric Laurent74b55762017-07-09 17:04:53 -07004237 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004238 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07004239 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07004240 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
4241 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
4242 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4243 bool ret_error = false;
4244 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4245 from HAL is 8_24
4246 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4247 8_24 return error indicating supported format is 8_24
4248 *> In case of any other source requesting 24 bit or float return error
4249 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07004250
vivek mehta57ff9b52016-04-28 14:13:08 -07004251 on error flinger will retry with supported format passed
4252 */
4253 if (source != AUDIO_SOURCE_UNPROCESSED) {
4254 config->format = AUDIO_FORMAT_PCM_16_BIT;
4255 ret_error = true;
4256 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
4257 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
4258 ret_error = true;
4259 }
4260
4261 if (ret_error) {
4262 ret = -EINVAL;
4263 goto err_open;
4264 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004265 }
4266
vivek mehta57ff9b52016-04-28 14:13:08 -07004267 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07004268 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07004269
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004270 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004271 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
4272 if (config->sample_rate == 0)
4273 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4274 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4275 config->sample_rate != 8000) {
4276 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4277 ret = -EINVAL;
4278 goto err_open;
4279 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004280
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004281 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4282 config->format = AUDIO_FORMAT_PCM_16_BIT;
4283 ret = -EINVAL;
4284 goto err_open;
4285 }
4286
4287 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4288 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07004289 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004290 } else if (is_usb_dev && may_use_hifi_record) {
4291 in->usecase = USECASE_AUDIO_RECORD_HIFI;
4292 in->config = pcm_config_audio_capture;
4293 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004294 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4295 config->sample_rate,
4296 config->format,
4297 channel_count,
4298 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004299 in->config.period_size = buffer_size / frame_size;
4300 in->config.rate = config->sample_rate;
4301 in->af_period_multiplier = 1;
4302 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004303 } else {
4304 in->usecase = USECASE_AUDIO_RECORD;
4305 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08004306 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004307 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07004308#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004309 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07004310#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08004311 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004312 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08004313 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004314 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004315 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4316 config->sample_rate,
4317 config->format,
4318 channel_count,
4319 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004320 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004321 in->config.rate = config->sample_rate;
4322 in->af_period_multiplier = 1;
4323 } else {
4324 // period size is left untouched for rt mode playback
4325 in->config = pcm_config_audio_capture_rt;
4326 in->af_period_multiplier = af_period_multiplier;
4327 }
4328 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
4329 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004330 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08004331 in->usecase = USECASE_AUDIO_RECORD_MMAP;
4332 in->config = pcm_config_mmap_capture;
4333 in->stream.start = in_start;
4334 in->stream.stop = in_stop;
4335 in->stream.create_mmap_buffer = in_create_mmap_buffer;
4336 in->stream.get_mmap_position = in_get_mmap_position;
4337 in->af_period_multiplier = 1;
4338 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07004339 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07004340 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07004341 (config->sample_rate == 8000 ||
4342 config->sample_rate == 16000 ||
4343 config->sample_rate == 32000 ||
4344 config->sample_rate == 48000) &&
4345 channel_count == 1) {
4346 in->usecase = USECASE_AUDIO_RECORD_VOIP;
4347 in->config = pcm_config_audio_capture;
4348 frame_size = audio_stream_in_frame_size(&in->stream);
4349 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
4350 config->sample_rate,
4351 config->format,
4352 channel_count, false /*is_low_latency*/);
4353 in->config.period_size = buffer_size / frame_size;
4354 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
4355 in->config.rate = config->sample_rate;
4356 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004357 } else {
4358 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004359 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004360 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4361 config->sample_rate,
4362 config->format,
4363 channel_count,
4364 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004365 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004366 in->config.rate = config->sample_rate;
4367 in->af_period_multiplier = 1;
4368 }
4369 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
4370 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004371 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004372
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004373 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07004374 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004375
Andy Hungd13f0d32017-06-12 13:58:37 -07004376 in->error_log = error_log_create(
4377 ERROR_LOG_ENTRIES,
4378 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
4379
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004380 /* This stream could be for sound trigger lab,
4381 get sound trigger pcm if present */
4382 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004383
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004384 lock_input_stream(in);
4385 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
4386 pthread_mutex_lock(&adev->lock);
4387 in->card_status = adev->card_status;
4388 pthread_mutex_unlock(&adev->lock);
4389 pthread_mutex_unlock(&in->lock);
4390
vivek mehta4a824772017-06-08 19:05:49 -07004391 stream_app_type_cfg_init(&in->app_type_cfg);
4392
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004393 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004394 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004395 return 0;
4396
4397err_open:
4398 free(in);
4399 *stream_in = NULL;
4400 return ret;
4401}
4402
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004403static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004404 struct audio_stream_in *stream)
4405{
Andy Hungd13f0d32017-06-12 13:58:37 -07004406 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004407 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004408
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004409 // must deregister from sndmonitor first to prevent races
4410 // between the callback and close_stream
4411 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004412 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07004413
4414 error_log_destroy(in->error_log);
4415 in->error_log = NULL;
4416
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004417 free(stream);
4418
4419 return;
4420}
4421
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004422static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004423{
4424 return 0;
4425}
4426
Andy Hung31aca912014-03-20 17:14:59 -07004427/* verifies input and output devices and their capabilities.
4428 *
4429 * This verification is required when enabling extended bit-depth or
4430 * sampling rates, as not all qcom products support it.
4431 *
4432 * Suitable for calling only on initialization such as adev_open().
4433 * It fills the audio_device use_case_table[] array.
4434 *
4435 * Has a side-effect that it needs to configure audio routing / devices
4436 * in order to power up the devices and read the device parameters.
4437 * It does not acquire any hw device lock. Should restore the devices
4438 * back to "normal state" upon completion.
4439 */
4440static int adev_verify_devices(struct audio_device *adev)
4441{
4442 /* enumeration is a bit difficult because one really wants to pull
4443 * the use_case, device id, etc from the hidden pcm_device_table[].
4444 * In this case there are the following use cases and device ids.
4445 *
4446 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
4447 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004448 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07004449 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
4450 * [USECASE_AUDIO_RECORD] = {0, 0},
4451 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
4452 * [USECASE_VOICE_CALL] = {2, 2},
4453 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004454 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07004455 * USECASE_VOICE_CALL omitted, but possible for either input or output.
4456 */
4457
4458 /* should be the usecases enabled in adev_open_input_stream() */
4459 static const int test_in_usecases[] = {
4460 USECASE_AUDIO_RECORD,
4461 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
4462 };
4463 /* should be the usecases enabled in adev_open_output_stream()*/
4464 static const int test_out_usecases[] = {
4465 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
4466 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
4467 };
4468 static const usecase_type_t usecase_type_by_dir[] = {
4469 PCM_PLAYBACK,
4470 PCM_CAPTURE,
4471 };
4472 static const unsigned flags_by_dir[] = {
4473 PCM_OUT,
4474 PCM_IN,
4475 };
4476
4477 size_t i;
4478 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004479 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07004480 char info[512]; /* for possible debug info */
4481
4482 for (dir = 0; dir < 2; ++dir) {
4483 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
4484 const unsigned flags_dir = flags_by_dir[dir];
4485 const size_t testsize =
4486 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
4487 const int *testcases =
4488 dir ? test_in_usecases : test_out_usecases;
4489 const audio_devices_t audio_device =
4490 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
4491
4492 for (i = 0; i < testsize; ++i) {
4493 const audio_usecase_t audio_usecase = testcases[i];
4494 int device_id;
4495 snd_device_t snd_device;
4496 struct pcm_params **pparams;
4497 struct stream_out out;
4498 struct stream_in in;
4499 struct audio_usecase uc_info;
4500 int retval;
4501
4502 pparams = &adev->use_case_table[audio_usecase];
4503 pcm_params_free(*pparams); /* can accept null input */
4504 *pparams = NULL;
4505
4506 /* find the device ID for the use case (signed, for error) */
4507 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
4508 if (device_id < 0)
4509 continue;
4510
4511 /* prepare structures for device probing */
4512 memset(&uc_info, 0, sizeof(uc_info));
4513 uc_info.id = audio_usecase;
4514 uc_info.type = usecase_type;
4515 if (dir) {
4516 adev->active_input = &in;
4517 memset(&in, 0, sizeof(in));
4518 in.device = audio_device;
4519 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4520 uc_info.stream.in = &in;
4521 } else {
4522 adev->active_input = NULL;
4523 }
4524 memset(&out, 0, sizeof(out));
4525 out.devices = audio_device; /* only field needed in select_devices */
4526 uc_info.stream.out = &out;
4527 uc_info.devices = audio_device;
4528 uc_info.in_snd_device = SND_DEVICE_NONE;
4529 uc_info.out_snd_device = SND_DEVICE_NONE;
4530 list_add_tail(&adev->usecase_list, &uc_info.list);
4531
4532 /* select device - similar to start_(in/out)put_stream() */
4533 retval = select_devices(adev, audio_usecase);
4534 if (retval >= 0) {
4535 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4536#if LOG_NDEBUG == 0
4537 if (*pparams) {
4538 ALOGV("%s: (%s) card %d device %d", __func__,
4539 dir ? "input" : "output", card_id, device_id);
4540 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004541 } else {
4542 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4543 }
4544#endif
4545 }
4546
4547 /* deselect device - similar to stop_(in/out)put_stream() */
4548 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004549 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004550 /* 2. Disable the rx device */
4551 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004552 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004553 list_remove(&uc_info.list);
4554 }
4555 }
4556 adev->active_input = NULL; /* restore adev state */
4557 return 0;
4558}
4559
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004560static int adev_close(hw_device_t *device)
4561{
Andy Hung31aca912014-03-20 17:14:59 -07004562 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004563 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004564
4565 if (!adev)
4566 return 0;
4567
4568 pthread_mutex_lock(&adev_init_lock);
4569
4570 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004571 audio_extn_snd_mon_unregister_listener(adev);
4572 audio_extn_tfa_98xx_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004573 audio_route_free(adev->audio_route);
4574 free(adev->snd_dev_ref_cnt);
4575 platform_deinit(adev->platform);
4576 audio_extn_extspk_deinit(adev->extspk);
4577 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004578 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004579 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4580 pcm_params_free(adev->use_case_table[i]);
4581 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004582 if (adev->adm_deinit)
4583 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004584 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004585 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004586
4587 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004588
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004589 return 0;
4590}
4591
Glenn Kasten4f993392014-05-14 07:30:48 -07004592/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4593 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4594 * just that it _might_ work.
4595 */
4596static int period_size_is_plausible_for_low_latency(int period_size)
4597{
4598 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004599 case 48:
4600 case 96:
4601 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004602 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004603 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004604 case 240:
4605 case 320:
4606 case 480:
4607 return 1;
4608 default:
4609 return 0;
4610 }
4611}
4612
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004613static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4614{
4615 int card;
4616 card_status_t status;
4617
4618 if (!parms)
4619 return;
4620
4621 if (parse_snd_card_status(parms, &card, &status) < 0)
4622 return;
4623
4624 pthread_mutex_lock(&adev->lock);
4625 bool valid_cb = (card == adev->snd_card);
4626 if (valid_cb) {
4627 if (adev->card_status != status) {
4628 adev->card_status = status;
4629 platform_snd_card_update(adev->platform, status);
4630 }
4631 }
4632 pthread_mutex_unlock(&adev->lock);
4633 return;
4634}
4635
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004636static int adev_open(const hw_module_t *module, const char *name,
4637 hw_device_t **device)
4638{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004639 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004640
Eric Laurent2bafff12016-03-17 12:17:23 -07004641 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004642 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004643 pthread_mutex_lock(&adev_init_lock);
4644 if (audio_device_ref_count != 0) {
4645 *device = &adev->device.common;
4646 audio_device_ref_count++;
4647 ALOGV("%s: returning existing instance of adev", __func__);
4648 ALOGV("%s: exit", __func__);
4649 pthread_mutex_unlock(&adev_init_lock);
4650 return 0;
4651 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004652 adev = calloc(1, sizeof(struct audio_device));
4653
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004654 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4655
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004656 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4657 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4658 adev->device.common.module = (struct hw_module_t *)module;
4659 adev->device.common.close = adev_close;
4660
4661 adev->device.init_check = adev_init_check;
4662 adev->device.set_voice_volume = adev_set_voice_volume;
4663 adev->device.set_master_volume = adev_set_master_volume;
4664 adev->device.get_master_volume = adev_get_master_volume;
4665 adev->device.set_master_mute = adev_set_master_mute;
4666 adev->device.get_master_mute = adev_get_master_mute;
4667 adev->device.set_mode = adev_set_mode;
4668 adev->device.set_mic_mute = adev_set_mic_mute;
4669 adev->device.get_mic_mute = adev_get_mic_mute;
4670 adev->device.set_parameters = adev_set_parameters;
4671 adev->device.get_parameters = adev_get_parameters;
4672 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4673 adev->device.open_output_stream = adev_open_output_stream;
4674 adev->device.close_output_stream = adev_close_output_stream;
4675 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004676
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004677 adev->device.close_input_stream = adev_close_input_stream;
4678 adev->device.dump = adev_dump;
4679
4680 /* Set the default route before the PCM stream is opened */
4681 pthread_mutex_lock(&adev->lock);
4682 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004683 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004684 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004685 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004686 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004687 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004688 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004689 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004690 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004691 pthread_mutex_unlock(&adev->lock);
4692
4693 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004694 adev->platform = platform_init(adev);
4695 if (!adev->platform) {
4696 free(adev->snd_dev_ref_cnt);
4697 free(adev);
4698 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4699 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004700 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004701 return -EINVAL;
4702 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05004703 adev->extspk = audio_extn_extspk_init(adev);
4704
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004705 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4706 if (adev->visualizer_lib == NULL) {
4707 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4708 } else {
4709 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4710 adev->visualizer_start_output =
4711 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4712 "visualizer_hal_start_output");
4713 adev->visualizer_stop_output =
4714 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4715 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07004716 }
4717
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004718 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4719 if (adev->offload_effects_lib == NULL) {
4720 ALOGW("%s: DLOPEN failed for %s", __func__,
4721 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4722 } else {
4723 ALOGV("%s: DLOPEN successful for %s", __func__,
4724 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4725 adev->offload_effects_start_output =
4726 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4727 "offload_effects_bundle_hal_start_output");
4728 adev->offload_effects_stop_output =
4729 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4730 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07004731 }
4732
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004733 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4734 if (adev->adm_lib == NULL) {
4735 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4736 } else {
4737 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4738 adev->adm_init = (adm_init_t)
4739 dlsym(adev->adm_lib, "adm_init");
4740 adev->adm_deinit = (adm_deinit_t)
4741 dlsym(adev->adm_lib, "adm_deinit");
4742 adev->adm_register_input_stream = (adm_register_input_stream_t)
4743 dlsym(adev->adm_lib, "adm_register_input_stream");
4744 adev->adm_register_output_stream = (adm_register_output_stream_t)
4745 dlsym(adev->adm_lib, "adm_register_output_stream");
4746 adev->adm_deregister_stream = (adm_deregister_stream_t)
4747 dlsym(adev->adm_lib, "adm_deregister_stream");
4748 adev->adm_request_focus = (adm_request_focus_t)
4749 dlsym(adev->adm_lib, "adm_request_focus");
4750 adev->adm_abandon_focus = (adm_abandon_focus_t)
4751 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08004752 adev->adm_set_config = (adm_set_config_t)
4753 dlsym(adev->adm_lib, "adm_set_config");
4754 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4755 dlsym(adev->adm_lib, "adm_request_focus_v2");
4756 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4757 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4758 adev->adm_on_routing_change = (adm_on_routing_change_t)
4759 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004760 }
4761
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004762 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004763 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004764
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004765 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004766
Andy Hung31aca912014-03-20 17:14:59 -07004767 if (k_enable_extended_precision)
4768 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004769
Glenn Kasten4f993392014-05-14 07:30:48 -07004770 char value[PROPERTY_VALUE_MAX];
4771 int trial;
4772 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4773 trial = atoi(value);
4774 if (period_size_is_plausible_for_low_latency(trial)) {
4775 pcm_config_low_latency.period_size = trial;
4776 pcm_config_low_latency.start_threshold = trial / 4;
4777 pcm_config_low_latency.avail_min = trial / 4;
4778 configured_low_latency_capture_period_size = trial;
4779 }
4780 }
4781 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4782 trial = atoi(value);
4783 if (period_size_is_plausible_for_low_latency(trial)) {
4784 configured_low_latency_capture_period_size = trial;
4785 }
4786 }
4787
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004788 // commented as full set of app type cfg is sent from platform
4789 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004790 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004791
4792 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4793 af_period_multiplier = atoi(value);
4794 if (af_period_multiplier < 0) {
4795 af_period_multiplier = 2;
4796 } else if (af_period_multiplier > 4) {
4797 af_period_multiplier = 4;
4798 }
4799 ALOGV("new period_multiplier = %d", af_period_multiplier);
4800 }
4801
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004802 audio_extn_tfa_98xx_init(adev);
4803
vivek mehta1a9b7c02015-06-25 11:49:38 -07004804 pthread_mutex_unlock(&adev_init_lock);
4805
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004806 if (adev->adm_init)
4807 adev->adm_data = adev->adm_init();
4808
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004809 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004810 audio_extn_snd_mon_init();
4811 pthread_mutex_lock(&adev->lock);
4812 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
4813 adev->card_status = CARD_STATUS_ONLINE;
4814 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004815 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004816
Eric Laurent2bafff12016-03-17 12:17:23 -07004817 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004818 return 0;
4819}
4820
4821static struct hw_module_methods_t hal_module_methods = {
4822 .open = adev_open,
4823};
4824
4825struct audio_module HAL_MODULE_INFO_SYM = {
4826 .common = {
4827 .tag = HARDWARE_MODULE_TAG,
4828 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4829 .hal_api_version = HARDWARE_HAL_API_VERSION,
4830 .id = AUDIO_HARDWARE_MODULE_ID,
4831 .name = "QCOM Audio HAL",
4832 .author = "Code Aurora Forum",
4833 .methods = &hal_module_methods,
4834 },
4835};