blob: 5b5a434015b01274f9f743204437efe891a003d5 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
vivek mehtaa51fd402016-02-04 19:49:33 -08002 * Copyright (C) 2013-2016 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "audio_hw_primary"
Haynes Mathew George03c40102016-01-29 17:57:48 -080018#define ATRACE_TAG ATRACE_TAG_AUDIO
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080019/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070020/*#define VERY_VERY_VERBOSE_LOGGING*/
21#ifdef VERY_VERY_VERBOSE_LOGGING
22#define ALOGVV ALOGV
23#else
24#define ALOGVV(a...) do { } while(0)
25#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080026
27#include <errno.h>
28#include <pthread.h>
29#include <stdint.h>
30#include <sys/time.h>
31#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080032#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070033#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070034#include <sys/resource.h>
35#include <sys/prctl.h>
Kevin Rocardb5c28192017-05-02 15:30:20 -070036#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080037
38#include <cutils/log.h>
Haynes Mathew George03c40102016-01-29 17:57:48 -080039#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040#include <cutils/str_parms.h>
41#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070042#include <cutils/atomic.h>
43#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080044
Eric Laurentb23d5282013-05-14 15:27:20 -070045#include <hardware/audio_effect.h>
Andy Hung31aca912014-03-20 17:14:59 -070046#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070047#include <system/thread_defs.h>
Phil Burkbc991042017-02-24 08:06:44 -080048#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070049#include <audio_effects/effect_aec.h>
50#include <audio_effects/effect_ns.h>
Andy Hungfc044e12017-03-20 09:24:22 -070051#include <audio_utils/clock.h>
52#include <audio_utils/power.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include "audio_hw.h"
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -080054#include "audio_extn.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070055#include "platform_api.h"
56#include <platform.h>
Vineeta Srivastava4b89e372014-06-19 14:21:42 -070057#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080058
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070059#include "sound/compress_params.h"
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -080060#include "audio_extn/tfa_98xx.h"
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070061
Eric Laurent397db572016-05-11 11:31:47 -070062/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
63 * COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
Marco Nelissen32093f52015-04-08 15:14:02 -070064#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070065// 2 buffers causes problems with high bitrate files
66#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070067/* ToDo: Check and update a proper value in msec */
68#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
vivek mehta4a824772017-06-08 19:05:49 -070069/* treat as unsigned Q1.13 */
70#define APP_TYPE_GAIN_DEFAULT 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070071#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
vivek mehta4a824772017-06-08 19:05:49 -070072
73/* treat as unsigned Q1.13 */
vivek mehtaa68fea62017-06-08 19:04:02 -070074#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070075
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070076#define PROXY_OPEN_RETRY_COUNT 100
77#define PROXY_OPEN_WAIT_TIME 20
78
vivek mehtadae44712015-07-27 14:13:18 -070079#define MIN_CHANNEL_COUNT 1
80#define DEFAULT_CHANNEL_COUNT 2
81
Jean-Michel Trivic0750692015-10-12 12:12:32 -070082#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
83#define MAX_CHANNEL_COUNT 1
84#else
vivek mehtadae44712015-07-27 14:13:18 -070085#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
86#define XSTR(x) STR(x)
87#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070088#endif
Eric Laurent74b55762017-07-09 17:04:53 -070089#define MAX_HIFI_CHANNEL_COUNT 8
vivek mehtadae44712015-07-27 14:13:18 -070090
Haynes Mathew George03c40102016-01-29 17:57:48 -080091#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
92
Glenn Kasten4f993392014-05-14 07:30:48 -070093static unsigned int configured_low_latency_capture_period_size =
94 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
95
Eric Laurent0e46adf2016-12-16 12:49:24 -080096
97#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Phil Burkbc991042017-02-24 08:06:44 -080098#define MMAP_PERIOD_COUNT_MIN 32
99#define MMAP_PERIOD_COUNT_MAX 512
100#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
Eric Laurent0e46adf2016-12-16 12:49:24 -0800101
102
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
Andy Hung9e737de2017-05-22 10:51:22 -0700323// TODO: Consider moving this to a pthread_once() if we have more
324// static initialization required.
325static bool is_userdebug_or_eng_build() {
326 char value[PROPERTY_VALUE_MAX];
327 (void)property_get("ro.build.type", value, "unknown"); // ignore actual length
328 return strcmp(value, "userdebug") == 0 || strcmp(value, "eng") == 0;
329}
330
Haynes Mathew George03c40102016-01-29 17:57:48 -0800331static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
332 int flags __unused)
333{
334 int dir = 0;
335 switch (uc_id) {
336 case USECASE_AUDIO_RECORD_LOW_LATENCY:
337 dir = 1;
338 case USECASE_AUDIO_PLAYBACK_ULL:
339 break;
340 default:
341 return false;
342 }
343
344 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
345 PCM_PLAYBACK : PCM_CAPTURE);
346 if (adev->adm_is_noirq_avail)
347 return adev->adm_is_noirq_avail(adev->adm_data,
348 adev->snd_card, dev_id, dir);
349 return false;
350}
351
352static void register_out_stream(struct stream_out *out)
353{
354 struct audio_device *adev = out->dev;
355 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
356 return;
357
358 if (!adev->adm_register_output_stream)
359 return;
360
361 adev->adm_register_output_stream(adev->adm_data,
362 out->handle,
363 out->flags);
364
365 if (!adev->adm_set_config)
366 return;
367
368 if (out->realtime) {
369 adev->adm_set_config(adev->adm_data,
370 out->handle,
371 out->pcm, &out->config);
372 }
373}
374
375static void register_in_stream(struct stream_in *in)
376{
377 struct audio_device *adev = in->dev;
378 if (!adev->adm_register_input_stream)
379 return;
380
381 adev->adm_register_input_stream(adev->adm_data,
382 in->capture_handle,
383 in->flags);
384
385 if (!adev->adm_set_config)
386 return;
387
388 if (in->realtime) {
389 adev->adm_set_config(adev->adm_data,
390 in->capture_handle,
391 in->pcm,
392 &in->config);
393 }
394}
395
396static void request_out_focus(struct stream_out *out, long ns)
397{
398 struct audio_device *adev = out->dev;
399
Haynes Mathew George03c40102016-01-29 17:57:48 -0800400 if (adev->adm_request_focus_v2) {
401 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
402 } else if (adev->adm_request_focus) {
403 adev->adm_request_focus(adev->adm_data, out->handle);
404 }
405}
406
407static void request_in_focus(struct stream_in *in, long ns)
408{
409 struct audio_device *adev = in->dev;
410
Haynes Mathew George03c40102016-01-29 17:57:48 -0800411 if (adev->adm_request_focus_v2) {
412 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
413 } else if (adev->adm_request_focus) {
414 adev->adm_request_focus(adev->adm_data, in->capture_handle);
415 }
416}
417
418static void release_out_focus(struct stream_out *out, long ns __unused)
419{
420 struct audio_device *adev = out->dev;
421
422 if (adev->adm_abandon_focus)
423 adev->adm_abandon_focus(adev->adm_data, out->handle);
424}
425
426static void release_in_focus(struct stream_in *in, long ns __unused)
427{
428 struct audio_device *adev = in->dev;
429 if (adev->adm_abandon_focus)
430 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
431}
432
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700433static int parse_snd_card_status(struct str_parms * parms, int * card,
434 card_status_t * status)
435{
436 char value[32]={0};
437 char state[32]={0};
438
439 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
440
441 if (ret < 0)
442 return -1;
443
444 // sscanf should be okay as value is of max length 32.
445 // same as sizeof state.
446 if (sscanf(value, "%d,%s", card, state) < 2)
447 return -1;
448
449 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
450 CARD_STATUS_OFFLINE;
451 return 0;
452}
453
vivek mehta1a9b7c02015-06-25 11:49:38 -0700454__attribute__ ((visibility ("default")))
455bool audio_hw_send_gain_dep_calibration(int level) {
456 bool ret_val = false;
457 ALOGV("%s: enter ... ", __func__);
458
459 pthread_mutex_lock(&adev_init_lock);
460
461 if (adev != NULL && adev->platform != NULL) {
462 pthread_mutex_lock(&adev->lock);
463 ret_val = platform_send_gain_dep_cal(adev->platform, level);
464 pthread_mutex_unlock(&adev->lock);
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700465
466 // if cal set fails, cache level info
467 // if cal set succeds, reset known last cal set
468 if (!ret_val)
469 last_known_cal_step = level;
470 else if (last_known_cal_step != -1)
471 last_known_cal_step = -1;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700472 } else {
473 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
474 }
475
476 pthread_mutex_unlock(&adev_init_lock);
477
478 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
479 return ret_val;
480}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700481
vivek mehtaa8d7c922016-05-25 14:40:44 -0700482__attribute__ ((visibility ("default")))
483int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
484 int table_size) {
485 int ret_val = 0;
486 ALOGV("%s: enter ... ", __func__);
487
488 pthread_mutex_lock(&adev_init_lock);
489 if (adev == NULL) {
490 ALOGW("%s: adev is NULL .... ", __func__);
491 goto done;
492 }
493
494 pthread_mutex_lock(&adev->lock);
495 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
496 pthread_mutex_unlock(&adev->lock);
497done:
498 pthread_mutex_unlock(&adev_init_lock);
499 ALOGV("%s: exit ... ", __func__);
500 return ret_val;
501}
502
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700503static bool is_supported_format(audio_format_t format)
504{
Eric Laurent8251ac82014-07-23 11:00:25 -0700505 switch (format) {
506 case AUDIO_FORMAT_MP3:
507 case AUDIO_FORMAT_AAC_LC:
508 case AUDIO_FORMAT_AAC_HE_V1:
509 case AUDIO_FORMAT_AAC_HE_V2:
510 return true;
511 default:
512 break;
513 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700514 return false;
515}
516
Haynes Mathew George03c40102016-01-29 17:57:48 -0800517static inline bool is_mmap_usecase(audio_usecase_t uc_id)
518{
519 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
520 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
521}
522
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700523static int get_snd_codec_id(audio_format_t format)
524{
525 int id = 0;
526
Eric Laurent8251ac82014-07-23 11:00:25 -0700527 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700528 case AUDIO_FORMAT_MP3:
529 id = SND_AUDIOCODEC_MP3;
530 break;
531 case AUDIO_FORMAT_AAC:
532 id = SND_AUDIOCODEC_AAC;
533 break;
534 default:
535 ALOGE("%s: Unsupported audio format", __func__);
536 }
537
538 return id;
539}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800540
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800541static int audio_ssr_status(struct audio_device *adev)
542{
543 int ret = 0;
544 struct mixer_ctl *ctl;
545 const char *mixer_ctl_name = "Audio SSR Status";
546
547 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
548 ret = mixer_ctl_get_value(ctl, 0);
549 ALOGD("%s: value: %d", __func__, ret);
550 return ret;
551}
552
vivek mehta4a824772017-06-08 19:05:49 -0700553static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
554{
555 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
556}
557
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800558int enable_audio_route(struct audio_device *adev,
559 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800560{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700561 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800562 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800563
564 if (usecase == NULL)
565 return -EINVAL;
566
567 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
568
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800569 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700570 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800571 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700572 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800573
Yamit Mehtae3b99562016-09-16 22:44:00 +0530574 audio_extn_utils_send_app_type_cfg(adev, usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800575 audio_extn_utils_send_audio_calibration(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800576 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500577 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700578 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700579 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800580
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800581 ALOGV("%s: exit", __func__);
582 return 0;
583}
584
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800585int disable_audio_route(struct audio_device *adev,
586 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800587{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700588 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800589 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800590
591 if (usecase == NULL)
592 return -EINVAL;
593
594 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700595 if (usecase->type == PCM_CAPTURE)
596 snd_device = usecase->in_snd_device;
597 else
598 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800599 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500600 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700601 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700602 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800603
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800604 ALOGV("%s: exit", __func__);
605 return 0;
606}
607
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800608int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700609 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800610{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700611 int i, num_devices = 0;
612 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800613 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800614 if (snd_device < SND_DEVICE_MIN ||
615 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800616 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800617 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800618 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700619
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700620 platform_send_audio_calibration(adev->platform, snd_device);
621
vivek mehtade4849c2016-03-03 17:23:38 -0800622 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700623 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700624 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800625 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700626 }
627
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700628 /* due to the possibility of calibration overwrite between listen
629 and audio, notify sound trigger hal before audio calibration is sent */
630 audio_extn_sound_trigger_update_device_status(snd_device,
631 ST_EVENT_SND_DEVICE_BUSY);
632
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700633 if (audio_extn_spkr_prot_is_enabled())
634 audio_extn_spkr_prot_calib_cancel(adev);
635
zhaoyang yin4211fad2015-06-04 21:13:25 +0800636 audio_extn_dsm_feedback_enable(adev, snd_device, true);
637
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700638 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
639 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
640 audio_extn_spkr_prot_is_enabled()) {
641 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800642 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700643 }
644 if (audio_extn_spkr_prot_start_processing(snd_device)) {
645 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800646 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700647 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700648 } else if (platform_can_split_snd_device(snd_device,
649 &num_devices,
650 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700651 for (i = 0; i < num_devices; i++) {
652 enable_snd_device(adev, new_snd_devices[i]);
653 }
vivek mehtab6506412015-08-07 16:55:17 -0700654 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700655 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800656 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
657 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
658 ALOGE(" %s: Invalid sound device returned", __func__);
659 goto on_error;
660 }
Ed Tam70b5c142016-03-21 19:14:29 -0700661
Eric Laurent2e140aa2016-06-30 17:14:46 -0700662 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800663 audio_route_apply_and_update_path(adev->audio_route, device_name);
664 }
665on_success:
666 adev->snd_dev_ref_cnt[snd_device]++;
667 ret_val = 0;
668on_error:
669 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800670}
671
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800672int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700673 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800674{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700675 int i, num_devices = 0;
676 snd_device_t new_snd_devices[2];
677
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800678 if (snd_device < SND_DEVICE_MIN ||
679 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800680 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800681 return -EINVAL;
682 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700683 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
684 ALOGE("%s: device ref cnt is already 0", __func__);
685 return -EINVAL;
686 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800687 audio_extn_tfa_98xx_disable_speaker(snd_device);
688
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700689 adev->snd_dev_ref_cnt[snd_device]--;
690 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800691 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700692 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700693 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700694 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
695 audio_extn_spkr_prot_is_enabled()) {
696 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700697
698 // when speaker device is disabled, reset swap.
699 // will be renabled on usecase start
700 platform_set_swap_channels(adev, false);
701
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700702 } else if (platform_can_split_snd_device(snd_device,
703 &num_devices,
704 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700705 for (i = 0; i < num_devices; i++) {
706 disable_snd_device(adev, new_snd_devices[i]);
707 }
vivek mehtab6506412015-08-07 16:55:17 -0700708 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700709 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800710 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
711 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
712 ALOGE(" %s: Invalid sound device returned", __func__);
713 return -EINVAL;
714 }
715
Eric Laurent2e140aa2016-06-30 17:14:46 -0700716 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800717 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700718 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700719 audio_extn_sound_trigger_update_device_status(snd_device,
720 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700721 }
vivek mehtab6506412015-08-07 16:55:17 -0700722
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800723 return 0;
724}
725
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700726/*
727 legend:
728 uc - existing usecase
729 new_uc - new usecase
730 d1, d11, d2 - SND_DEVICE enums
731 a1, a2 - corresponding ANDROID device enums
732 B, B1, B2 - backend strings
733
734case 1
735 uc->dev d1 (a1) B1
736 new_uc->dev d1 (a1), d2 (a2) B1, B2
737
738 resolution: disable and enable uc->dev on d1
739
740case 2
741 uc->dev d1 (a1) B1
742 new_uc->dev d11 (a1) B1
743
744 resolution: need to switch uc since d1 and d11 are related
745 (e.g. speaker and voice-speaker)
746 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
747
748case 3
749 uc->dev d1 (a1) B1
750 new_uc->dev d2 (a2) B2
751
752 resolution: no need to switch uc
753
754case 4
755 uc->dev d1 (a1) B
756 new_uc->dev d2 (a2) B
757
758 resolution: disable enable uc-dev on d2 since backends match
759 we cannot enable two streams on two different devices if they
760 share the same backend. e.g. if offload is on speaker device using
761 QUAD_MI2S backend and a low-latency stream is started on voice-handset
762 using the same backend, offload must also be switched to voice-handset.
763
764case 5
765 uc->dev d1 (a1) B
766 new_uc->dev d1 (a1), d2 (a2) B
767
768 resolution: disable enable uc-dev on d2 since backends match
769 we cannot enable two streams on two different devices if they
770 share the same backend.
771
772case 6
773 uc->dev d1 a1 B1
774 new_uc->dev d2 a1 B2
775
776 resolution: no need to switch
777
778case 7
779
780 uc->dev d1 (a1), d2 (a2) B1, B2
781 new_uc->dev d1 B1
782
783 resolution: no need to switch
784
785*/
786static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
787 struct audio_usecase *new_uc,
788 snd_device_t new_snd_device)
789{
790 audio_devices_t a1 = uc->stream.out->devices;
791 audio_devices_t a2 = new_uc->stream.out->devices;
792
793 snd_device_t d1 = uc->out_snd_device;
794 snd_device_t d2 = new_snd_device;
795
796 // Treat as a special case when a1 and a2 are not disjoint
797 if ((a1 != a2) && (a1 & a2)) {
798 snd_device_t d3[2];
799 int num_devices = 0;
800 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
801 &num_devices,
802 d3);
803 if (ret < 0) {
804 if (ret != -ENOSYS) {
805 ALOGW("%s failed to split snd_device %d",
806 __func__,
807 popcount(a1) > 1 ? d1 : d2);
808 }
809 goto end;
810 }
811
812 // NB: case 7 is hypothetical and isn't a practical usecase yet.
813 // But if it does happen, we need to give priority to d2 if
814 // the combo devices active on the existing usecase share a backend.
815 // This is because we cannot have a usecase active on a combo device
816 // and a new usecase requests one device in this combo pair.
817 if (platform_check_backends_match(d3[0], d3[1])) {
818 return d2; // case 5
819 } else {
820 return d1; // case 1
821 }
822 } else {
823 if (platform_check_backends_match(d1, d2)) {
824 return d2; // case 2, 4
825 } else {
826 return d1; // case 6, 3
827 }
828 }
829
830end:
831 return d2; // return whatever was calculated before.
832}
833
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700834static void check_and_route_playback_usecases(struct audio_device *adev,
835 struct audio_usecase *uc_info,
836 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700837{
838 struct listnode *node;
839 struct audio_usecase *usecase;
840 bool switch_device[AUDIO_USECASE_MAX];
841 int i, num_uc_to_switch = 0;
842
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700843 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
844 uc_info,
845 snd_device);
David Linee3fe402017-03-13 10:00:42 -0700846
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700847 /*
848 * This function is to make sure that all the usecases that are active on
849 * the hardware codec backend are always routed to any one device that is
850 * handled by the hardware codec.
851 * For example, if low-latency and deep-buffer usecases are currently active
852 * on speaker and out_set_parameters(headset) is received on low-latency
853 * output, then we have to make sure deep-buffer is also switched to headset,
854 * because of the limitation that both the devices cannot be enabled
855 * at the same time as they share the same backend.
856 */
857 /* Disable all the usecases on the shared backend other than the
858 specified usecase */
859 for (i = 0; i < AUDIO_USECASE_MAX; i++)
860 switch_device[i] = false;
861
862 list_for_each(node, &adev->usecase_list) {
863 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700864 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
865 continue;
866
867 if (force_routing ||
868 (usecase->out_snd_device != snd_device &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -0700869 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
870 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700871 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700872 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
873 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700874 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700875 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700876 switch_device[usecase->id] = true;
877 num_uc_to_switch++;
878 }
879 }
880
881 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700882 list_for_each(node, &adev->usecase_list) {
883 usecase = node_to_item(node, struct audio_usecase, list);
884 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700885 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900886 }
887 }
888
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700889 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900890 list_for_each(node, &adev->usecase_list) {
891 usecase = node_to_item(node, struct audio_usecase, list);
892 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700893 d_device = derive_playback_snd_device(usecase, uc_info,
894 snd_device);
895 enable_snd_device(adev, d_device);
896 /* Update the out_snd_device before enabling the audio route */
897 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700898 }
899 }
900
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700901 /* Re-route all the usecases on the shared backend other than the
902 specified usecase to new snd devices */
903 list_for_each(node, &adev->usecase_list) {
904 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700905 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700906 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700907 }
908 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700909 }
910}
911
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700912static void check_and_route_capture_usecases(struct audio_device *adev,
913 struct audio_usecase *uc_info,
914 snd_device_t snd_device)
915{
916 struct listnode *node;
917 struct audio_usecase *usecase;
918 bool switch_device[AUDIO_USECASE_MAX];
919 int i, num_uc_to_switch = 0;
920
vivek mehta4ed66e62016-04-15 23:33:34 -0700921 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
922
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700923 /*
924 * This function is to make sure that all the active capture usecases
925 * are always routed to the same input sound device.
926 * For example, if audio-record and voice-call usecases are currently
927 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
928 * is received for voice call then we have to make sure that audio-record
929 * usecase is also switched to earpiece i.e. voice-dmic-ef,
930 * because of the limitation that two devices cannot be enabled
931 * at the same time if they share the same backend.
932 */
933 for (i = 0; i < AUDIO_USECASE_MAX; i++)
934 switch_device[i] = false;
935
936 list_for_each(node, &adev->usecase_list) {
937 usecase = node_to_item(node, struct audio_usecase, list);
938 if (usecase->type != PCM_PLAYBACK &&
939 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700940 usecase->in_snd_device != snd_device &&
941 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700942 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
943 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700944 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700945 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700946 switch_device[usecase->id] = true;
947 num_uc_to_switch++;
948 }
949 }
950
951 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700952 list_for_each(node, &adev->usecase_list) {
953 usecase = node_to_item(node, struct audio_usecase, list);
954 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700955 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700956 }
957 }
958
959 list_for_each(node, &adev->usecase_list) {
960 usecase = node_to_item(node, struct audio_usecase, list);
961 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700962 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700963 }
964 }
965
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700966 /* Re-route all the usecases on the shared backend other than the
967 specified usecase to new snd devices */
968 list_for_each(node, &adev->usecase_list) {
969 usecase = node_to_item(node, struct audio_usecase, list);
970 /* Update the in_snd_device only before enabling the audio route */
971 if (switch_device[usecase->id] ) {
972 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700973 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700974 }
975 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700976 }
977}
978
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800979/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700980static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800981{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700982 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700983 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800984
985 switch (channels) {
986 /*
987 * Do not handle stereo output in Multi-channel cases
988 * Stereo case is handled in normal playback path
989 */
990 case 6:
991 ALOGV("%s: HDMI supports 5.1", __func__);
992 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
993 break;
994 case 8:
995 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
996 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
997 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
998 break;
999 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001000 ALOGE("HDMI does not support multi channel playback");
1001 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001002 break;
1003 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001004 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001005}
1006
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001007static ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1008 uint32_t *supported_sample_rates __unused,
1009 uint32_t max_rates __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001010{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001011 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1012 supported_sample_rates,
1013 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001014#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001015 for (ssize_t i=0; i<count; i++) {
1016 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1017 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001018 }
1019#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001020 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001021}
1022
Haynes Mathew George569b7482017-05-08 14:44:27 -07001023static int read_usb_sup_channel_masks(bool is_playback,
1024 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001025 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001026{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001027 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001028 int channel_count;
1029 uint32_t num_masks = 0;
1030 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1031 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001032 }
Eric Laurent74b55762017-07-09 17:04:53 -07001033 if (is_playback) {
1034 // For playback we never report mono because the framework always outputs stereo
1035 channel_count = DEFAULT_CHANNEL_COUNT;
1036 // audio_channel_out_mask_from_count() does return positional masks for channel counts
1037 // above 2 but we want indexed masks here. So we
1038 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1039 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1040 }
1041 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1042 supported_channel_masks[num_masks++] =
1043 audio_channel_mask_for_index_assignment_from_count(channel_count);
1044 }
1045 } else {
1046 // For capture we report all supported channel masks from 1 channel up.
1047 channel_count = MIN_CHANNEL_COUNT;
1048 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1049 // indexed mask
1050 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1051 supported_channel_masks[num_masks++] =
1052 audio_channel_in_mask_from_count(channel_count);
1053 }
1054 }
1055 ALOGV("%s: %s supported ch %d supported_channel_masks[0] %08x num_masks %d", __func__,
1056 is_playback ? "P" : "C", channels, supported_channel_masks[0], num_masks);
1057 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001058}
1059
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001060static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001061 audio_format_t *supported_formats,
1062 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001063{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001064 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001065 switch (bitwidth) {
1066 case 24:
1067 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001068 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001069 break;
1070 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001071 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001072 break;
1073 case 16:
1074 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001075 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001076 break;
1077 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001078 ALOGV("%s: %s supported format %d", __func__,
1079 is_playback ? "P" : "C", bitwidth);
1080 return 1;
1081}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001082
Haynes Mathew George569b7482017-05-08 14:44:27 -07001083static int read_usb_sup_params_and_compare(bool is_playback,
1084 audio_format_t *format,
1085 audio_format_t *supported_formats,
1086 uint32_t max_formats,
1087 audio_channel_mask_t *mask,
1088 audio_channel_mask_t *supported_channel_masks,
1089 uint32_t max_masks,
1090 uint32_t *rate,
1091 uint32_t *supported_sample_rates,
1092 uint32_t max_rates) {
1093 int ret = 0;
1094 int num_formats;
1095 int num_masks;
1096 int num_rates;
1097 int i;
1098
1099 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1100 max_formats);
1101 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1102 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001103
Haynes Mathew George569b7482017-05-08 14:44:27 -07001104 num_rates = read_usb_sup_sample_rates(is_playback,
1105 supported_sample_rates, max_rates);
1106
1107#define LUT(table, len, what, dflt) \
1108 for (i=0; i<len && (table[i] != what); i++); \
1109 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1110
1111 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1112 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1113 LUT(supported_sample_rates, num_rates, *rate, 0);
1114
1115#undef LUT
1116 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001117}
1118
Andy Hungd9653bd2017-08-01 19:31:39 -07001119static bool is_usb_ready(struct audio_device *adev, bool is_playback)
1120{
1121 // Check if usb is ready.
1122 // The usb device may have been removed quickly after insertion and hence
1123 // no longer available. This will show up as empty channel masks, or rates.
1124
1125 pthread_mutex_lock(&adev->lock);
1126 uint32_t supported_sample_rate;
1127
1128 // we consider usb ready if we can fetch at least one sample rate.
1129 const bool ready = read_usb_sup_sample_rates(
1130 is_playback, &supported_sample_rate, 1 /* max_rates */) > 0;
1131 pthread_mutex_unlock(&adev->lock);
1132 return ready;
1133}
1134
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001135static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1136{
1137 struct audio_usecase *usecase;
1138 struct listnode *node;
1139
1140 list_for_each(node, &adev->usecase_list) {
1141 usecase = node_to_item(node, struct audio_usecase, list);
1142 if (usecase->type == VOICE_CALL) {
1143 ALOGV("%s: usecase id %d", __func__, usecase->id);
1144 return usecase->id;
1145 }
1146 }
1147 return USECASE_INVALID;
1148}
1149
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001150struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1151 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001152{
1153 struct audio_usecase *usecase;
1154 struct listnode *node;
1155
1156 list_for_each(node, &adev->usecase_list) {
1157 usecase = node_to_item(node, struct audio_usecase, list);
1158 if (usecase->id == uc_id)
1159 return usecase;
1160 }
1161 return NULL;
1162}
1163
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001164int select_devices(struct audio_device *adev,
1165 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001166{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001167 snd_device_t out_snd_device = SND_DEVICE_NONE;
1168 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001169 struct audio_usecase *usecase = NULL;
1170 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001171 struct audio_usecase *hfp_usecase = NULL;
1172 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001173 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001174 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001175
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001176 usecase = get_usecase_from_list(adev, uc_id);
1177 if (usecase == NULL) {
1178 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1179 return -EINVAL;
1180 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001181
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001182 if ((usecase->type == VOICE_CALL) ||
1183 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001184 out_snd_device = platform_get_output_snd_device(adev->platform,
1185 usecase->stream.out->devices);
1186 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001187 usecase->devices = usecase->stream.out->devices;
1188 } else {
1189 /*
1190 * If the voice call is active, use the sound devices of voice call usecase
1191 * so that it would not result any device switch. All the usecases will
1192 * be switched to new device when select_devices() is called for voice call
1193 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001194 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001195 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001196 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001197 vc_usecase = get_usecase_from_list(adev,
1198 get_voice_usecase_id_from_list(adev));
1199 if ((vc_usecase != NULL) &&
1200 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1201 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001202 in_snd_device = vc_usecase->in_snd_device;
1203 out_snd_device = vc_usecase->out_snd_device;
1204 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001205 } else if (audio_extn_hfp_is_active(adev)) {
1206 hfp_ucid = audio_extn_hfp_get_usecase();
1207 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1208 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1209 in_snd_device = hfp_usecase->in_snd_device;
1210 out_snd_device = hfp_usecase->out_snd_device;
1211 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001212 }
1213 if (usecase->type == PCM_PLAYBACK) {
1214 usecase->devices = usecase->stream.out->devices;
1215 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001216 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001217 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001218 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001219 if (usecase->stream.out == adev->primary_output &&
1220 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001221 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1222 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001223 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001224 select_devices(adev, adev->active_input->usecase);
1225 }
1226 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001227 } else if (usecase->type == PCM_CAPTURE) {
1228 usecase->devices = usecase->stream.in->device;
1229 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001230 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001231 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001232 if (adev->active_input &&
1233 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1234 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001235 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001236 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1237 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
1238 } else if (adev->primary_output) {
1239 out_device = adev->primary_output->devices;
1240 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001241 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001242 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001243 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001244 }
1245 }
1246
1247 if (out_snd_device == usecase->out_snd_device &&
1248 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001249 return 0;
1250 }
1251
Eric Laurent2bafff12016-03-17 12:17:23 -07001252 if (out_snd_device != SND_DEVICE_NONE &&
1253 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1254 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1255 __func__,
1256 use_case_table[uc_id],
1257 adev->last_logged_snd_device[uc_id][0],
1258 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1259 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1260 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1261 -1,
1262 out_snd_device,
1263 platform_get_snd_device_name(out_snd_device),
1264 platform_get_snd_device_acdb_id(out_snd_device));
1265 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1266 }
1267 if (in_snd_device != SND_DEVICE_NONE &&
1268 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1269 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1270 __func__,
1271 use_case_table[uc_id],
1272 adev->last_logged_snd_device[uc_id][1],
1273 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1274 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1275 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1276 -1,
1277 in_snd_device,
1278 platform_get_snd_device_name(in_snd_device),
1279 platform_get_snd_device_acdb_id(in_snd_device));
1280 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1281 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001282
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001283 /*
1284 * Limitation: While in call, to do a device switch we need to disable
1285 * and enable both RX and TX devices though one of them is same as current
1286 * device.
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)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001291 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001292 /* Disable sidetone only if voice call already exists */
1293 if (voice_is_call_state_active(adev))
1294 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001295 }
1296
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001297 /* Disable current sound devices */
1298 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001299 disable_audio_route(adev, usecase);
1300 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001301 }
1302
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001303 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001304 disable_audio_route(adev, usecase);
1305 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001306 }
1307
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001308 /* Applicable only on the targets that has external modem.
1309 * New device information should be sent to modem before enabling
1310 * the devices to reduce in-call device switch time.
1311 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001312 if ((usecase->type == VOICE_CALL) &&
1313 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1314 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001315 status = platform_switch_voice_call_enable_device_config(adev->platform,
1316 out_snd_device,
1317 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001318 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001319
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001320 /* Enable new sound devices */
1321 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001322 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Eric Laurent99dab492017-06-17 15:19:08 -07001323 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001324 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001325 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001326 }
1327
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001328 if (in_snd_device != SND_DEVICE_NONE) {
1329 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001330 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001331 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001332
Eric Laurentb23d5282013-05-14 15:27:20 -07001333 if (usecase->type == VOICE_CALL)
1334 status = platform_switch_voice_call_device_post(adev->platform,
1335 out_snd_device,
1336 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001337
sangwoo170731f2013-06-08 15:36:36 +09001338 usecase->in_snd_device = in_snd_device;
1339 usecase->out_snd_device = out_snd_device;
1340
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001341 audio_extn_tfa_98xx_set_mode();
1342
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001343 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001344
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001345 /* Applicable only on the targets that has external modem.
1346 * Enable device command should be sent to modem only after
1347 * enabling voice call mixer controls
1348 */
vivek mehta765eb642015-08-07 19:46:06 -07001349 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001350 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1351 out_snd_device,
1352 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001353 /* Enable sidetone only if voice call already exists */
1354 if (voice_is_call_state_active(adev))
1355 voice_set_sidetone(adev, out_snd_device, true);
1356 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001357
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001358 return status;
1359}
1360
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001361static int stop_input_stream(struct stream_in *in)
1362{
1363 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001364 struct audio_usecase *uc_info;
1365 struct audio_device *adev = in->dev;
1366
Eric Laurent994a6932013-07-17 11:51:42 -07001367 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001368 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001369
1370 if (adev->active_input) {
1371 if (adev->active_input->usecase == in->usecase) {
1372 adev->active_input = NULL;
1373 } else {
1374 ALOGW("%s adev->active_input->usecase %s, v/s in->usecase %s",
1375 __func__,
1376 use_case_table[adev->active_input->usecase],
1377 use_case_table[in->usecase]);
1378 }
1379 }
1380
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001381 uc_info = get_usecase_from_list(adev, in->usecase);
1382 if (uc_info == NULL) {
1383 ALOGE("%s: Could not find the usecase (%d) in the list",
1384 __func__, in->usecase);
1385 return -EINVAL;
1386 }
1387
vivek mehta781065c2017-04-04 12:55:01 -07001388 /* Close in-call recording streams */
1389 voice_check_and_stop_incall_rec_usecase(adev, in);
1390
Eric Laurent150dbfe2013-02-27 14:31:02 -08001391 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001392 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001393
1394 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001395 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001396
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001397 list_remove(&uc_info->list);
1398 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001399
Eric Laurent994a6932013-07-17 11:51:42 -07001400 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001401 return ret;
1402}
1403
1404int start_input_stream(struct stream_in *in)
1405{
1406 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001407 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001408 struct audio_usecase *uc_info;
1409 struct audio_device *adev = in->dev;
1410
Eric Laurent994a6932013-07-17 11:51:42 -07001411 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001412
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001413 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1414 return -EIO;
1415
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001416 if (in->card_status == CARD_STATUS_OFFLINE ||
1417 adev->card_status == CARD_STATUS_OFFLINE) {
1418 ALOGW("in->card_status or adev->card_status offline, try again");
1419 ret = -EAGAIN;
1420 goto error_config;
1421 }
1422
vivek mehta781065c2017-04-04 12:55:01 -07001423 /* Check if source matches incall recording usecase criteria */
1424 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1425 if (ret)
1426 goto error_config;
1427 else
1428 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1429
Eric Laurentb23d5282013-05-14 15:27:20 -07001430 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001431 if (in->pcm_device_id < 0) {
1432 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1433 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001434 ret = -EINVAL;
1435 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001436 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001437
1438 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001439 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1440 uc_info->id = in->usecase;
1441 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001442 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001443 uc_info->devices = in->device;
1444 uc_info->in_snd_device = SND_DEVICE_NONE;
1445 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001446
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001447 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001448
1449 audio_extn_perf_lock_acquire();
1450
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001451 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001452
Eric Laurent0e46adf2016-12-16 12:49:24 -08001453 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001454 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001455 ALOGE("%s: pcm stream not ready", __func__);
1456 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001457 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001458 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001459 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001460 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1461 goto error_open;
1462 }
1463 } else {
1464 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1465 unsigned int pcm_open_retry_count = 0;
1466
1467 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1468 flags |= PCM_MMAP | PCM_NOIRQ;
1469 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1470 } else if (in->realtime) {
1471 flags |= PCM_MMAP | PCM_NOIRQ;
1472 }
1473
1474 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1475 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1476
1477 while (1) {
1478 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1479 flags, &in->config);
1480 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1481 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1482 if (in->pcm != NULL) {
1483 pcm_close(in->pcm);
1484 in->pcm = NULL;
1485 }
1486 if (pcm_open_retry_count-- == 0) {
1487 ret = -EIO;
1488 goto error_open;
1489 }
1490 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1491 continue;
1492 }
1493 break;
1494 }
1495
1496 ALOGV("%s: pcm_prepare", __func__);
1497 ret = pcm_prepare(in->pcm);
1498 if (ret < 0) {
1499 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001500 pcm_close(in->pcm);
1501 in->pcm = NULL;
1502 goto error_open;
1503 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001504 if (in->realtime) {
1505 ret = pcm_start(in->pcm);
1506 if (ret < 0) {
1507 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1508 pcm_close(in->pcm);
1509 in->pcm = NULL;
1510 goto error_open;
1511 }
1512 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001513 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001514 register_in_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001515 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001516 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001517
Eric Laurent0e46adf2016-12-16 12:49:24 -08001518 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001519
1520error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001521 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001522 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001523
1524error_config:
1525 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001526 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001527 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001528}
1529
Eric Laurenta1478072015-09-21 17:21:52 -07001530void lock_input_stream(struct stream_in *in)
1531{
1532 pthread_mutex_lock(&in->pre_lock);
1533 pthread_mutex_lock(&in->lock);
1534 pthread_mutex_unlock(&in->pre_lock);
1535}
1536
1537void lock_output_stream(struct stream_out *out)
1538{
1539 pthread_mutex_lock(&out->pre_lock);
1540 pthread_mutex_lock(&out->lock);
1541 pthread_mutex_unlock(&out->pre_lock);
1542}
1543
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001544/* must be called with out->lock locked */
1545static int send_offload_cmd_l(struct stream_out* out, int command)
1546{
1547 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1548
1549 ALOGVV("%s %d", __func__, command);
1550
1551 cmd->cmd = command;
1552 list_add_tail(&out->offload_cmd_list, &cmd->node);
1553 pthread_cond_signal(&out->offload_cond);
1554 return 0;
1555}
1556
1557/* must be called iwth out->lock locked */
1558static void stop_compressed_output_l(struct stream_out *out)
1559{
1560 out->offload_state = OFFLOAD_STATE_IDLE;
1561 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001562 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001563 if (out->compr != NULL) {
1564 compress_stop(out->compr);
1565 while (out->offload_thread_blocked) {
1566 pthread_cond_wait(&out->cond, &out->lock);
1567 }
1568 }
1569}
1570
1571static void *offload_thread_loop(void *context)
1572{
1573 struct stream_out *out = (struct stream_out *) context;
1574 struct listnode *item;
1575
1576 out->offload_state = OFFLOAD_STATE_IDLE;
1577 out->playback_started = 0;
1578
1579 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1580 set_sched_policy(0, SP_FOREGROUND);
1581 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1582
1583 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001584 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001585 for (;;) {
1586 struct offload_cmd *cmd = NULL;
1587 stream_callback_event_t event;
1588 bool send_callback = false;
1589
1590 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1591 __func__, list_empty(&out->offload_cmd_list),
1592 out->offload_state);
1593 if (list_empty(&out->offload_cmd_list)) {
1594 ALOGV("%s SLEEPING", __func__);
1595 pthread_cond_wait(&out->offload_cond, &out->lock);
1596 ALOGV("%s RUNNING", __func__);
1597 continue;
1598 }
1599
1600 item = list_head(&out->offload_cmd_list);
1601 cmd = node_to_item(item, struct offload_cmd, node);
1602 list_remove(item);
1603
1604 ALOGVV("%s STATE %d CMD %d out->compr %p",
1605 __func__, out->offload_state, cmd->cmd, out->compr);
1606
1607 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1608 free(cmd);
1609 break;
1610 }
1611
1612 if (out->compr == NULL) {
1613 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001614 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001615 pthread_cond_signal(&out->cond);
1616 continue;
1617 }
1618 out->offload_thread_blocked = true;
1619 pthread_mutex_unlock(&out->lock);
1620 send_callback = false;
1621 switch(cmd->cmd) {
1622 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1623 compress_wait(out->compr, -1);
1624 send_callback = true;
1625 event = STREAM_CBK_EVENT_WRITE_READY;
1626 break;
1627 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001628 compress_next_track(out->compr);
1629 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001630 send_callback = true;
1631 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001632 /* Resend the metadata for next iteration */
1633 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001634 break;
1635 case OFFLOAD_CMD_DRAIN:
1636 compress_drain(out->compr);
1637 send_callback = true;
1638 event = STREAM_CBK_EVENT_DRAIN_READY;
1639 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001640 case OFFLOAD_CMD_ERROR:
1641 send_callback = true;
1642 event = STREAM_CBK_EVENT_ERROR;
1643 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001644 default:
1645 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1646 break;
1647 }
Eric Laurenta1478072015-09-21 17:21:52 -07001648 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001649 out->offload_thread_blocked = false;
1650 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001651 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001652 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001653 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001654 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001655 free(cmd);
1656 }
1657
1658 pthread_cond_signal(&out->cond);
1659 while (!list_empty(&out->offload_cmd_list)) {
1660 item = list_head(&out->offload_cmd_list);
1661 list_remove(item);
1662 free(node_to_item(item, struct offload_cmd, node));
1663 }
1664 pthread_mutex_unlock(&out->lock);
1665
1666 return NULL;
1667}
1668
1669static int create_offload_callback_thread(struct stream_out *out)
1670{
1671 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1672 list_init(&out->offload_cmd_list);
1673 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1674 offload_thread_loop, out);
1675 return 0;
1676}
1677
1678static int destroy_offload_callback_thread(struct stream_out *out)
1679{
Eric Laurenta1478072015-09-21 17:21:52 -07001680 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001681 stop_compressed_output_l(out);
1682 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1683
1684 pthread_mutex_unlock(&out->lock);
1685 pthread_join(out->offload_thread, (void **) NULL);
1686 pthread_cond_destroy(&out->offload_cond);
1687
1688 return 0;
1689}
1690
Eric Laurent07eeafd2013-10-06 12:52:49 -07001691static bool allow_hdmi_channel_config(struct audio_device *adev)
1692{
1693 struct listnode *node;
1694 struct audio_usecase *usecase;
1695 bool ret = true;
1696
1697 list_for_each(node, &adev->usecase_list) {
1698 usecase = node_to_item(node, struct audio_usecase, list);
1699 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1700 /*
1701 * If voice call is already existing, do not proceed further to avoid
1702 * disabling/enabling both RX and TX devices, CSD calls, etc.
1703 * Once the voice call done, the HDMI channels can be configured to
1704 * max channels of remaining use cases.
1705 */
1706 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001707 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001708 __func__);
1709 ret = false;
1710 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001711 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1712 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001713 "no change in HDMI channels", __func__);
1714 ret = false;
1715 break;
1716 }
1717 }
1718 }
1719 return ret;
1720}
1721
1722static int check_and_set_hdmi_channels(struct audio_device *adev,
1723 unsigned int channels)
1724{
1725 struct listnode *node;
1726 struct audio_usecase *usecase;
1727
1728 /* Check if change in HDMI channel config is allowed */
1729 if (!allow_hdmi_channel_config(adev))
1730 return 0;
1731
1732 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001733 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001734 return 0;
1735 }
1736
1737 platform_set_hdmi_channels(adev->platform, channels);
1738 adev->cur_hdmi_channels = channels;
1739
1740 /*
1741 * Deroute all the playback streams routed to HDMI so that
1742 * the back end is deactivated. Note that backend will not
1743 * be deactivated if any one stream is connected to it.
1744 */
1745 list_for_each(node, &adev->usecase_list) {
1746 usecase = node_to_item(node, struct audio_usecase, list);
1747 if (usecase->type == PCM_PLAYBACK &&
1748 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001749 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001750 }
1751 }
1752
1753 /*
1754 * Enable all the streams disabled above. Now the HDMI backend
1755 * will be activated with new channel configuration
1756 */
1757 list_for_each(node, &adev->usecase_list) {
1758 usecase = node_to_item(node, struct audio_usecase, list);
1759 if (usecase->type == PCM_PLAYBACK &&
1760 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001761 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001762 }
1763 }
1764
1765 return 0;
1766}
1767
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001768static int stop_output_stream(struct stream_out *out)
1769{
1770 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001771 struct audio_usecase *uc_info;
1772 struct audio_device *adev = out->dev;
1773
Eric Laurent994a6932013-07-17 11:51:42 -07001774 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001775 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001776 uc_info = get_usecase_from_list(adev, out->usecase);
1777 if (uc_info == NULL) {
1778 ALOGE("%s: Could not find the usecase (%d) in the list",
1779 __func__, out->usecase);
1780 return -EINVAL;
1781 }
1782
Haynes Mathew George41f86652014-06-17 14:22:15 -07001783 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1784 if (adev->visualizer_stop_output != NULL)
1785 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1786 if (adev->offload_effects_stop_output != NULL)
1787 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1788 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001789
Eric Laurent150dbfe2013-02-27 14:31:02 -08001790 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001791 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001792
1793 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001794 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001795
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001796 list_remove(&uc_info->list);
1797 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001798
Eric Laurent0499d4f2014-08-25 22:39:29 -05001799 audio_extn_extspk_update(adev->extspk);
1800
Eric Laurent07eeafd2013-10-06 12:52:49 -07001801 /* Must be called after removing the usecase from list */
1802 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1803 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1804
Eric Laurent994a6932013-07-17 11:51:42 -07001805 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001806 return ret;
1807}
1808
1809int start_output_stream(struct stream_out *out)
1810{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001811 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001812 struct audio_usecase *uc_info;
1813 struct audio_device *adev = out->dev;
1814
Eric Laurent994a6932013-07-17 11:51:42 -07001815 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001816 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001817
1818 if (out->card_status == CARD_STATUS_OFFLINE ||
1819 adev->card_status == CARD_STATUS_OFFLINE) {
1820 ALOGW("out->card_status or adev->card_status offline, try again");
1821 ret = -EAGAIN;
1822 goto error_config;
1823 }
1824
Eric Laurentb23d5282013-05-14 15:27:20 -07001825 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001826 if (out->pcm_device_id < 0) {
1827 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1828 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001829 ret = -EINVAL;
1830 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001831 }
1832
1833 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1834 uc_info->id = out->usecase;
1835 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001836 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001837 uc_info->devices = out->devices;
1838 uc_info->in_snd_device = SND_DEVICE_NONE;
1839 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001840
Eric Laurent07eeafd2013-10-06 12:52:49 -07001841 /* This must be called before adding this usecase to the list */
1842 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1843 check_and_set_hdmi_channels(adev, out->config.channels);
1844
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001845 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001846
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001847 audio_extn_perf_lock_acquire();
1848
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001849 select_devices(adev, out->usecase);
1850
Eric Laurent0499d4f2014-08-25 22:39:29 -05001851 audio_extn_extspk_update(adev->extspk);
1852
Andy Hung31aca912014-03-20 17:14:59 -07001853 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001854 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001855 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1856 out->pcm = NULL;
1857 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1858 COMPRESS_IN, &out->compr_config);
1859 if (out->compr && !is_compress_ready(out->compr)) {
1860 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1861 compress_close(out->compr);
1862 out->compr = NULL;
1863 ret = -EIO;
1864 goto error_open;
1865 }
1866 if (out->offload_callback)
1867 compress_nonblock(out->compr, out->non_blocking);
1868
1869 if (adev->visualizer_start_output != NULL)
1870 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1871 if (adev->offload_effects_start_output != NULL)
1872 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
1873 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001874 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001875 ALOGE("%s: pcm stream not ready", __func__);
1876 goto error_open;
1877 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001878 ret = pcm_start(out->pcm);
1879 if (ret < 0) {
1880 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1881 goto error_open;
1882 }
1883 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07001884 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001885 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001886
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001887 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1888 flags |= PCM_MMAP | PCM_NOIRQ;
1889 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001890 } else if (out->realtime) {
1891 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07001892 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001893
1894 while (1) {
1895 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1896 flags, &out->config);
1897 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1898 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1899 if (out->pcm != NULL) {
1900 pcm_close(out->pcm);
1901 out->pcm = NULL;
1902 }
1903 if (pcm_open_retry_count-- == 0) {
1904 ret = -EIO;
1905 goto error_open;
1906 }
1907 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1908 continue;
1909 }
1910 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001911 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001912 ALOGV("%s: pcm_prepare", __func__);
1913 if (pcm_is_ready(out->pcm)) {
1914 ret = pcm_prepare(out->pcm);
1915 if (ret < 0) {
1916 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1917 pcm_close(out->pcm);
1918 out->pcm = NULL;
1919 goto error_open;
1920 }
1921 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001922 if (out->realtime) {
1923 ret = pcm_start(out->pcm);
1924 if (ret < 0) {
1925 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1926 pcm_close(out->pcm);
1927 out->pcm = NULL;
1928 goto error_open;
1929 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001930 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001931 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001932 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001933 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001934 audio_extn_tfa_98xx_enable_speaker();
vivek mehta4a824772017-06-08 19:05:49 -07001935 audio_extn_utils_send_app_type_gain(out->dev,
1936 out->app_type_cfg.app_type,
1937 &out->app_type_cfg.gain[0]);
vivek mehtae59cfb22017-06-16 15:57:11 -07001938
1939 // consider a scenario where on pause lower layers are tear down.
1940 // so on resume, swap mixer control need to be sent only when
1941 // backend is active, hence rather than sending from enable device
1942 // sending it from start of streamtream
1943
1944 platform_set_swap_channels(adev, true);
1945
Eric Laurent994a6932013-07-17 11:51:42 -07001946 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001947 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001948error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001949 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001950 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001951error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001952 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001953}
1954
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001955static int check_input_parameters(uint32_t sample_rate,
1956 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07001957 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001958{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001959 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
1960 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07001961 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
1962 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07001963 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1964 return -EINVAL;
1965 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001966
Eric Laurent74b55762017-07-09 17:04:53 -07001967 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
1968 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001969 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07001970 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07001971 return -EINVAL;
1972 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001973
1974 switch (sample_rate) {
1975 case 8000:
1976 case 11025:
1977 case 12000:
1978 case 16000:
1979 case 22050:
1980 case 24000:
1981 case 32000:
1982 case 44100:
1983 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001984 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001985 break;
1986 default:
vivek mehtadae44712015-07-27 14:13:18 -07001987 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001988 return -EINVAL;
1989 }
1990
1991 return 0;
1992}
1993
vivek mehtaa68fea62017-06-08 19:04:02 -07001994static size_t get_stream_buffer_size(size_t duration_ms,
1995 uint32_t sample_rate,
1996 audio_format_t format,
1997 int channel_count,
1998 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001999{
2000 size_t size = 0;
2001
vivek mehtaa68fea62017-06-08 19:04:02 -07002002 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002003 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002004 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002005
2006 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002007
Glenn Kasten4f993392014-05-14 07:30:48 -07002008 /* make sure the size is multiple of 32 bytes
2009 * At 48 kHz mono 16-bit PCM:
2010 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2011 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2012 */
2013 size += 0x1f;
2014 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002015
2016 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002017}
2018
2019static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2020{
2021 struct stream_out *out = (struct stream_out *)stream;
2022
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002023 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002024}
2025
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002026static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002027{
2028 return -ENOSYS;
2029}
2030
2031static size_t out_get_buffer_size(const struct audio_stream *stream)
2032{
2033 struct stream_out *out = (struct stream_out *)stream;
2034
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002035 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2036 return out->compr_config.fragment_size;
2037 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002038 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002039 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002040}
2041
2042static uint32_t out_get_channels(const struct audio_stream *stream)
2043{
2044 struct stream_out *out = (struct stream_out *)stream;
2045
2046 return out->channel_mask;
2047}
2048
2049static audio_format_t out_get_format(const struct audio_stream *stream)
2050{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002051 struct stream_out *out = (struct stream_out *)stream;
2052
2053 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002054}
2055
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002056static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002057{
2058 return -ENOSYS;
2059}
2060
2061static int out_standby(struct audio_stream *stream)
2062{
2063 struct stream_out *out = (struct stream_out *)stream;
2064 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002065 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002066
Eric Laurent994a6932013-07-17 11:51:42 -07002067 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002068 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002069
Eric Laurenta1478072015-09-21 17:21:52 -07002070 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002071 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002072 if (adev->adm_deregister_stream)
2073 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002074 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002075 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002076 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2077 if (out->pcm) {
2078 pcm_close(out->pcm);
2079 out->pcm = NULL;
2080 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002081 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002082 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002083 out->playback_started = false;
2084 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002085 } else {
2086 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002087 out->gapless_mdata.encoder_delay = 0;
2088 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002089 if (out->compr != NULL) {
2090 compress_close(out->compr);
2091 out->compr = NULL;
2092 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002093 }
Phil Burkbc991042017-02-24 08:06:44 -08002094 if (do_stop) {
2095 stop_output_stream(out);
2096 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002097 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002098 }
2099 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002100 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002101 return 0;
2102}
2103
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002104static int out_on_error(struct audio_stream *stream)
2105{
2106 struct stream_out *out = (struct stream_out *)stream;
2107 struct audio_device *adev = out->dev;
2108 bool do_standby = false;
2109
2110 lock_output_stream(out);
2111 if (!out->standby) {
2112 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2113 stop_compressed_output_l(out);
2114 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2115 } else
2116 do_standby = true;
2117 }
2118 pthread_mutex_unlock(&out->lock);
2119
2120 if (do_standby)
2121 return out_standby(&out->stream.common);
2122
2123 return 0;
2124}
2125
Andy Hung7401c7c2016-09-21 12:41:21 -07002126static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002127{
Andy Hung7401c7c2016-09-21 12:41:21 -07002128 struct stream_out *out = (struct stream_out *)stream;
2129
2130 // We try to get the lock for consistency,
2131 // but it isn't necessary for these variables.
2132 // If we're not in standby, we may be blocked on a write.
2133 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2134 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2135 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2136
2137 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002138 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002139 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002140
2141 // dump error info
2142 (void)error_log_dump(
2143 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hungfc044e12017-03-20 09:24:22 -07002144 // dump power info (out->power_log may be null)
Andy Hung62c9b882017-03-22 16:43:42 -07002145 (void)power_log_dump(
2146 out->power_log, fd, " " /* prefix */, POWER_LOG_LINES, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002147 return 0;
2148}
2149
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002150static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2151{
2152 int ret = 0;
2153 char value[32];
2154 struct compr_gapless_mdata tmp_mdata;
2155
2156 if (!out || !parms) {
2157 return -EINVAL;
2158 }
2159
2160 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2161 if (ret >= 0) {
2162 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2163 } else {
2164 return -EINVAL;
2165 }
2166
2167 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2168 if (ret >= 0) {
2169 tmp_mdata.encoder_padding = atoi(value);
2170 } else {
2171 return -EINVAL;
2172 }
2173
2174 out->gapless_mdata = tmp_mdata;
2175 out->send_new_metadata = 1;
2176 ALOGV("%s new encoder delay %u and padding %u", __func__,
2177 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2178
2179 return 0;
2180}
2181
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002182static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2183{
2184 return out == adev->primary_output || out == adev->voice_tx_output;
2185}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002186
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002187static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2188{
2189 struct stream_out *out = (struct stream_out *)stream;
2190 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002191 struct audio_usecase *usecase;
2192 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002193 struct str_parms *parms;
2194 char value[32];
2195 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002196 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002197 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002198
Eric Laurent2e140aa2016-06-30 17:14:46 -07002199 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002200 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002201 parms = str_parms_create_str(kvpairs);
2202 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2203 if (ret >= 0) {
2204 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07002205 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002206 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002207
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002208 /*
2209 * When HDMI cable is unplugged the music playback is paused and
2210 * the policy manager sends routing=0. But the audioflinger
2211 * continues to write data until standby time (3sec).
2212 * As the HDMI core is turned off, the write gets blocked.
2213 * Avoid this by routing audio to speaker until standby.
2214 */
2215 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2216 val == AUDIO_DEVICE_NONE) {
2217 val = AUDIO_DEVICE_OUT_SPEAKER;
2218 }
2219
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002220 audio_devices_t new_dev = val;
2221
2222 // Workaround: If routing to an non existing usb device, fail gracefully
2223 // The routing request will otherwise block during 10 second
2224 if (audio_is_usb_out_device(new_dev) && !audio_extn_usb_alive(adev->snd_card)) {
2225 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d",
2226 adev->snd_card);
2227 pthread_mutex_unlock(&adev->lock);
2228 pthread_mutex_unlock(&out->lock);
2229 status = -ENOSYS;
2230 goto routing_fail;
2231 }
2232
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002233 /*
2234 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002235 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002236 * the select_devices(). But how do we undo this?
2237 *
2238 * For example, music playback is active on headset (deep-buffer usecase)
2239 * and if we go to ringtones and select a ringtone, low-latency usecase
2240 * will be started on headset+speaker. As we can't enable headset+speaker
2241 * and headset devices at the same time, select_devices() switches the music
2242 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2243 * So when the ringtone playback is completed, how do we undo the same?
2244 *
2245 * We are relying on the out_set_parameters() call on deep-buffer output,
2246 * once the ringtone playback is ended.
2247 * NOTE: We should not check if the current devices are same as new devices.
2248 * Because select_devices() must be called to switch back the music
2249 * playback to headset.
2250 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002251 if (new_dev != AUDIO_DEVICE_NONE) {
2252 bool same_dev = out->devices == new_dev;
2253 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002254
Eric Laurenta7657192014-10-09 21:09:33 -07002255 if (output_drives_call(adev, out)) {
2256 if (!voice_is_in_call(adev)) {
2257 if (adev->mode == AUDIO_MODE_IN_CALL) {
2258 adev->current_call_output = out;
2259 ret = voice_start_call(adev);
2260 }
2261 } else {
2262 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002263 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002264 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002265 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002266
2267 if (!out->standby) {
2268 if (!same_dev) {
2269 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002270 // inform adm before actual routing to prevent glitches.
2271 if (adev->adm_on_routing_change) {
2272 adev->adm_on_routing_change(adev->adm_data,
2273 out->handle);
2274 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002275 }
2276 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002277 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002278
2279 // on device switch force swap, lower functions will make sure
2280 // to check if swap is allowed or not.
2281
2282 if (!same_dev)
2283 platform_set_swap_channels(adev, true);
vivek mehta0d3637a2016-07-24 09:32:02 -07002284 }
2285
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002286 }
2287
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002288 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002289 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002290
2291 /*handles device and call state changes*/
2292 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002293 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002294 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002295
2296 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2297 parse_compress_metadata(out, parms);
2298 }
2299
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002300 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002301 ALOGV("%s: exit: code(%d)", __func__, status);
2302 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002303}
2304
Haynes Mathew George569b7482017-05-08 14:44:27 -07002305static bool stream_get_parameter_channels(struct str_parms *query,
2306 struct str_parms *reply,
2307 audio_channel_mask_t *supported_channel_masks) {
2308 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002309 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002310 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002311 size_t i, j;
2312
2313 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2314 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002315 value[0] = '\0';
2316 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002317 while (supported_channel_masks[i] != 0) {
2318 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2319 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002320 if (!first) {
2321 strcat(value, "|");
2322 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002323 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002324 first = false;
2325 break;
2326 }
2327 }
2328 i++;
2329 }
2330 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002331 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002332 return ret >= 0;
2333}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002334
Haynes Mathew George569b7482017-05-08 14:44:27 -07002335static bool stream_get_parameter_formats(struct str_parms *query,
2336 struct str_parms *reply,
2337 audio_format_t *supported_formats) {
2338 int ret = -1;
2339 char value[256];
2340 int i;
2341
2342 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2343 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002344 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002345 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002346 case AUDIO_FORMAT_PCM_16_BIT:
2347 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2348 break;
2349 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2350 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2351 break;
2352 case AUDIO_FORMAT_PCM_32_BIT:
2353 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2354 break;
2355 default:
2356 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002357 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002358 break;
2359 }
2360 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002361 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002362 return ret >= 0;
2363}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002364
Haynes Mathew George569b7482017-05-08 14:44:27 -07002365static bool stream_get_parameter_rates(struct str_parms *query,
2366 struct str_parms *reply,
2367 uint32_t *supported_sample_rates) {
2368
2369 int i;
2370 char value[256];
2371 int ret = -1;
2372 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2373 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002374 value[0] = '\0';
2375 i=0;
2376 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002377 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002378 int avail = sizeof(value) - cursor;
2379 ret = snprintf(value + cursor, avail, "%s%d",
2380 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002381 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002382 if (ret < 0 || ret >= avail) {
2383 // if cursor is at the last element of the array
2384 // overwrite with \0 is duplicate work as
2385 // snprintf already put a \0 in place.
2386 // else
2387 // we had space to write the '|' at value[cursor]
2388 // (which will be overwritten) or no space to fill
2389 // the first element (=> cursor == 0)
2390 value[cursor] = '\0';
2391 break;
2392 }
2393 cursor += ret;
2394 ++i;
2395 }
2396 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2397 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002398 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002399 return ret >= 0;
2400}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002401
Haynes Mathew George569b7482017-05-08 14:44:27 -07002402static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2403{
2404 struct stream_out *out = (struct stream_out *)stream;
2405 struct str_parms *query = str_parms_create_str(keys);
2406 char *str;
2407 struct str_parms *reply = str_parms_create();
2408 bool replied = false;
2409 ALOGV("%s: enter: keys - %s", __func__, keys);
2410
2411 replied |= stream_get_parameter_channels(query, reply,
2412 &out->supported_channel_masks[0]);
2413 replied |= stream_get_parameter_formats(query, reply,
2414 &out->supported_formats[0]);
2415 replied |= stream_get_parameter_rates(query, reply,
2416 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002417 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002418 str = str_parms_to_str(reply);
2419 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002420 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002421 }
2422 str_parms_destroy(query);
2423 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002424 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002425 return str;
2426}
2427
2428static uint32_t out_get_latency(const struct audio_stream_out *stream)
2429{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002430 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002431 struct stream_out *out = (struct stream_out *)stream;
2432
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002433 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2434 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002435 else if ((out->realtime) ||
2436 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002437 // since the buffer won't be filled up faster than realtime,
2438 // return a smaller number
2439 period_ms = (out->af_period_multiplier * out->config.period_size *
2440 1000) / (out->config.rate);
2441 hw_delay = platform_render_latency(out->usecase)/1000;
2442 return period_ms + hw_delay;
2443 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002444
2445 return (out->config.period_count * out->config.period_size * 1000) /
2446 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002447}
2448
2449static int out_set_volume(struct audio_stream_out *stream, float left,
2450 float right)
2451{
Eric Laurenta9024de2013-04-04 09:19:12 -07002452 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002453 int volume[2];
2454
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002455 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002456 /* only take left channel into account: the API is for stereo anyway */
2457 out->muted = (left == 0.0f);
2458 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002459 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2460 const char *mixer_ctl_name = "Compress Playback Volume";
2461 struct audio_device *adev = out->dev;
2462 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002463 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2464 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002465 /* try with the control based on device id */
2466 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2467 PCM_PLAYBACK);
2468 char ctl_name[128] = {0};
2469 snprintf(ctl_name, sizeof(ctl_name),
2470 "Compress Playback %d Volume", pcm_device_id);
2471 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2472 if (!ctl) {
2473 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2474 return -EINVAL;
2475 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002476 }
2477 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2478 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2479 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2480 return 0;
vivek mehtaa68fea62017-06-08 19:04:02 -07002481 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002482 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2483 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2484 if (!out->standby) {
2485 // if in standby, cached volume will be sent after stream is opened
2486 audio_extn_utils_send_app_type_gain(out->dev,
2487 out->app_type_cfg.app_type,
2488 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002489 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002490 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002491 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002492
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002493 return -ENOSYS;
2494}
2495
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002496// note: this call is safe only if the stream_cb is
2497// removed first in close_output_stream (as is done now).
2498static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2499{
2500 if (!stream || !parms)
2501 return;
2502
2503 struct stream_out *out = (struct stream_out *)stream;
2504 struct audio_device *adev = out->dev;
2505
2506 card_status_t status;
2507 int card;
2508 if (parse_snd_card_status(parms, &card, &status) < 0)
2509 return;
2510
2511 pthread_mutex_lock(&adev->lock);
2512 bool valid_cb = (card == adev->snd_card);
2513 pthread_mutex_unlock(&adev->lock);
2514
2515 if (!valid_cb)
2516 return;
2517
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002518 lock_output_stream(out);
2519 if (out->card_status != status)
2520 out->card_status = status;
2521 pthread_mutex_unlock(&out->lock);
2522
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002523 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2524 use_case_table[out->usecase],
2525 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2526
2527 if (status == CARD_STATUS_OFFLINE)
2528 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002529
2530 return;
2531}
2532
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002533#ifdef NO_AUDIO_OUT
2534static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002535 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002536{
2537 struct stream_out *out = (struct stream_out *)stream;
2538
2539 /* No Output device supported other than BT for playback.
2540 * Sleep for the amount of buffer duration
2541 */
Eric Laurenta1478072015-09-21 17:21:52 -07002542 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002543 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2544 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002545 out_get_sample_rate(&out->stream.common));
2546 pthread_mutex_unlock(&out->lock);
2547 return bytes;
2548}
2549#endif
2550
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002551static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2552 size_t bytes)
2553{
2554 struct stream_out *out = (struct stream_out *)stream;
2555 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002556 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002557 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002558
Eric Laurenta1478072015-09-21 17:21:52 -07002559 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002560 // this is always nonzero
Andy Hung928efbe2017-06-12 14:05:22 -07002561 const size_t frame_size = audio_stream_out_frame_size(stream);
2562 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002563
Eric Laurent0e46adf2016-12-16 12:49:24 -08002564 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2565 error_code = ERROR_CODE_WRITE;
2566 goto exit;
2567 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002568 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002569 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002570 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002571 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002572 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002573 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002574 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002575 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002576 goto exit;
2577 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002578
2579 if (last_known_cal_step != -1) {
2580 ALOGD("%s: retry previous failed cal level set", __func__);
2581 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2582 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002583 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002584
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002585 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002586 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002587 if (out->send_new_metadata) {
2588 ALOGVV("send new gapless metadata");
2589 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2590 out->send_new_metadata = 0;
2591 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002592 unsigned int avail;
2593 struct timespec tstamp;
2594 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2595 /* Do not limit write size if the available frames count is unknown */
2596 if (ret != 0) {
2597 avail = bytes;
2598 }
2599 if (avail == 0) {
2600 ret = 0;
2601 } else {
2602 if (avail > bytes) {
2603 avail = bytes;
2604 }
2605 ret = compress_write(out->compr, buffer, avail);
2606 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2607 __func__, avail, ret);
2608 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002609
Eric Laurent6e895242013-09-05 16:10:57 -07002610 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002611 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2612 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002613 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002614 compress_start(out->compr);
2615 out->playback_started = 1;
2616 out->offload_state = OFFLOAD_STATE_PLAYING;
2617 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002618 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002619 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002620 } else {
2621 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002622 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002623 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002624 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002625 return ret;
2626 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002627 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002628 if (out->pcm) {
2629 if (out->muted)
2630 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002631
Eric Laurent0e46adf2016-12-16 12:49:24 -08002632 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002633
Haynes Mathew George03c40102016-01-29 17:57:48 -08002634 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2635 out->config.rate;
2636 request_out_focus(out, ns);
2637
2638 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2639 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002640 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002641 else
2642 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002643
Haynes Mathew George03c40102016-01-29 17:57:48 -08002644 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002645 } else {
2646 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002647 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002648 }
2649
2650exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002651 // For PCM we always consume the buffer and return #bytes regardless of ret.
2652 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung928efbe2017-06-12 14:05:22 -07002653 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07002654 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002655 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07002656
2657 // only get time if needed for logging, as it is a system call on 32 bit devices.
2658 // TODO: Consider always enabling for 64 bit vDSO using compile time check on __LP64__.
2659 const int64_t now_ns = out->power_log != 0 || (ret != 0 && out->error_log != 0)
2660 ? audio_utils_get_real_time_ns() : 0;
Andy Hungfc044e12017-03-20 09:24:22 -07002661
Andy Hung7401c7c2016-09-21 12:41:21 -07002662 if (ret != 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002663 error_log_log(out->error_log, error_code, now_ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002664 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2665 ALOGE_IF(out->pcm != NULL,
2666 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung928efbe2017-06-12 14:05:22 -07002667 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002668 // usleep not guaranteed for values over 1 second but we don't limit here.
2669 }
2670 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002671
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002672 pthread_mutex_unlock(&out->lock);
2673
2674 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002675 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002676 if (sleeptime_us != 0)
2677 usleep(sleeptime_us);
Andy Hungfc044e12017-03-20 09:24:22 -07002678 } else {
2679 // only log if the data is properly written (out->power_log may be null)
Andy Hung928efbe2017-06-12 14:05:22 -07002680 power_log_log(out->power_log, buffer, frames, now_ns);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002681 }
2682 return bytes;
2683}
2684
2685static int out_get_render_position(const struct audio_stream_out *stream,
2686 uint32_t *dsp_frames)
2687{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002688 struct stream_out *out = (struct stream_out *)stream;
2689 *dsp_frames = 0;
2690 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002691 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002692 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002693 unsigned long frames = 0;
2694 // TODO: check return value
2695 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2696 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002697 ALOGVV("%s rendered frames %d sample_rate %d",
2698 __func__, *dsp_frames, out->sample_rate);
2699 }
2700 pthread_mutex_unlock(&out->lock);
2701 return 0;
2702 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002703 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002704}
2705
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002706static int out_add_audio_effect(const struct audio_stream *stream __unused,
2707 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002708{
2709 return 0;
2710}
2711
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002712static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2713 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002714{
2715 return 0;
2716}
2717
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002718static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2719 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002720{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002721 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002722}
2723
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002724static int out_get_presentation_position(const struct audio_stream_out *stream,
2725 uint64_t *frames, struct timespec *timestamp)
2726{
2727 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002728 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07002729 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002730
Eric Laurenta1478072015-09-21 17:21:52 -07002731 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002732
Eric Laurent949a0892013-09-20 09:20:13 -07002733 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2734 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002735 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002736 compress_get_tstamp(out->compr, &dsp_frames,
2737 &out->sample_rate);
2738 ALOGVV("%s rendered frames %ld sample_rate %d",
2739 __func__, dsp_frames, out->sample_rate);
2740 *frames = dsp_frames;
2741 ret = 0;
2742 /* this is the best we can do */
2743 clock_gettime(CLOCK_MONOTONIC, timestamp);
2744 }
2745 } else {
2746 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002747 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002748 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2749 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002750 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002751 // This adjustment accounts for buffering after app processor.
2752 // It is based on estimated DSP latency per use case, rather than exact.
2753 signed_frames -=
2754 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2755
Eric Laurent949a0892013-09-20 09:20:13 -07002756 // It would be unusual for this value to be negative, but check just in case ...
2757 if (signed_frames >= 0) {
2758 *frames = signed_frames;
2759 ret = 0;
2760 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002761 }
2762 }
2763 }
2764
2765 pthread_mutex_unlock(&out->lock);
2766
2767 return ret;
2768}
2769
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002770static int out_set_callback(struct audio_stream_out *stream,
2771 stream_callback_t callback, void *cookie)
2772{
2773 struct stream_out *out = (struct stream_out *)stream;
2774
2775 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002776 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002777 out->offload_callback = callback;
2778 out->offload_cookie = cookie;
2779 pthread_mutex_unlock(&out->lock);
2780 return 0;
2781}
2782
2783static int out_pause(struct audio_stream_out* stream)
2784{
2785 struct stream_out *out = (struct stream_out *)stream;
2786 int status = -ENOSYS;
2787 ALOGV("%s", __func__);
2788 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002789 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002790 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2791 status = compress_pause(out->compr);
2792 out->offload_state = OFFLOAD_STATE_PAUSED;
2793 }
2794 pthread_mutex_unlock(&out->lock);
2795 }
2796 return status;
2797}
2798
2799static int out_resume(struct audio_stream_out* stream)
2800{
2801 struct stream_out *out = (struct stream_out *)stream;
2802 int status = -ENOSYS;
2803 ALOGV("%s", __func__);
2804 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2805 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002806 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002807 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2808 status = compress_resume(out->compr);
2809 out->offload_state = OFFLOAD_STATE_PLAYING;
2810 }
2811 pthread_mutex_unlock(&out->lock);
2812 }
2813 return status;
2814}
2815
2816static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2817{
2818 struct stream_out *out = (struct stream_out *)stream;
2819 int status = -ENOSYS;
2820 ALOGV("%s", __func__);
2821 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002822 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002823 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2824 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2825 else
2826 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2827 pthread_mutex_unlock(&out->lock);
2828 }
2829 return status;
2830}
2831
2832static int out_flush(struct audio_stream_out* stream)
2833{
2834 struct stream_out *out = (struct stream_out *)stream;
2835 ALOGV("%s", __func__);
2836 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002837 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002838 stop_compressed_output_l(out);
2839 pthread_mutex_unlock(&out->lock);
2840 return 0;
2841 }
2842 return -ENOSYS;
2843}
2844
Eric Laurent0e46adf2016-12-16 12:49:24 -08002845static int out_stop(const struct audio_stream_out* stream)
2846{
2847 struct stream_out *out = (struct stream_out *)stream;
2848 struct audio_device *adev = out->dev;
2849 int ret = -ENOSYS;
2850
2851 ALOGV("%s", __func__);
2852 pthread_mutex_lock(&adev->lock);
2853 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2854 out->playback_started && out->pcm != NULL) {
2855 pcm_stop(out->pcm);
2856 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08002857 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002858 }
2859 pthread_mutex_unlock(&adev->lock);
2860 return ret;
2861}
2862
2863static int out_start(const struct audio_stream_out* stream)
2864{
2865 struct stream_out *out = (struct stream_out *)stream;
2866 struct audio_device *adev = out->dev;
2867 int ret = -ENOSYS;
2868
2869 ALOGV("%s", __func__);
2870 pthread_mutex_lock(&adev->lock);
2871 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2872 !out->playback_started && out->pcm != NULL) {
2873 ret = start_output_stream(out);
2874 if (ret == 0) {
2875 out->playback_started = true;
2876 }
2877 }
2878 pthread_mutex_unlock(&adev->lock);
2879 return ret;
2880}
2881
Phil Burkbc991042017-02-24 08:06:44 -08002882/*
2883 * Modify config->period_count based on min_size_frames
2884 */
2885static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
2886{
2887 int periodCountRequested = (min_size_frames + config->period_size - 1)
2888 / config->period_size;
2889 int periodCount = MMAP_PERIOD_COUNT_MIN;
2890
2891 ALOGV("%s original config.period_size = %d config.period_count = %d",
2892 __func__, config->period_size, config->period_count);
2893
2894 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
2895 periodCount *= 2;
2896 }
2897 config->period_count = periodCount;
2898
2899 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
2900}
2901
Eric Laurent0e46adf2016-12-16 12:49:24 -08002902static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2903 int32_t min_size_frames,
2904 struct audio_mmap_buffer_info *info)
2905{
2906 struct stream_out *out = (struct stream_out *)stream;
2907 struct audio_device *adev = out->dev;
2908 int ret = 0;
2909 unsigned int offset1;
2910 unsigned int frames1;
2911 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07002912 uint32_t mmap_size;
2913 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002914
2915 ALOGV("%s", __func__);
2916 pthread_mutex_lock(&adev->lock);
2917
2918 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002919 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002920 ret = -EINVAL;
2921 goto exit;
2922 }
2923 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08002924 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002925 ret = -ENOSYS;
2926 goto exit;
2927 }
2928 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
2929 if (out->pcm_device_id < 0) {
2930 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2931 __func__, out->pcm_device_id, out->usecase);
2932 ret = -EINVAL;
2933 goto exit;
2934 }
Phil Burkbc991042017-02-24 08:06:44 -08002935
2936 adjust_mmap_period_count(&out->config, min_size_frames);
2937
Eric Laurent0e46adf2016-12-16 12:49:24 -08002938 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2939 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
2940 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2941 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
2942 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2943 step = "open";
2944 ret = -ENODEV;
2945 goto exit;
2946 }
2947 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
2948 if (ret < 0) {
2949 step = "begin";
2950 goto exit;
2951 }
2952 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07002953 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002954 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07002955 ret = platform_get_mmap_data_fd(adev->platform,
2956 out->pcm_device_id, 0 /*playback*/,
2957 &info->shared_memory_fd,
2958 &mmap_size);
2959 if (ret < 0) {
2960 // Fall back to non exclusive mode
2961 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
2962 } else {
2963 if (mmap_size < buffer_size) {
2964 step = "mmap";
2965 goto exit;
2966 }
2967 // FIXME: indicate exclusive mode support by returning a negative buffer size
2968 info->buffer_size_frames *= -1;
2969 }
2970 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002971
2972 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
2973 if (ret < 0) {
2974 step = "commit";
2975 goto exit;
2976 }
Phil Burkbc991042017-02-24 08:06:44 -08002977
2978 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002979 ret = 0;
2980
2981 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
2982 __func__, info->shared_memory_address, info->buffer_size_frames);
2983
2984exit:
2985 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002986 if (out->pcm == NULL) {
2987 ALOGE("%s: %s - %d", __func__, step, ret);
2988 } else {
2989 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08002990 pcm_close(out->pcm);
2991 out->pcm = NULL;
2992 }
2993 }
2994 pthread_mutex_unlock(&adev->lock);
2995 return ret;
2996}
2997
2998static int out_get_mmap_position(const struct audio_stream_out *stream,
2999 struct audio_mmap_position *position)
3000{
3001 struct stream_out *out = (struct stream_out *)stream;
3002 ALOGVV("%s", __func__);
3003 if (position == NULL) {
3004 return -EINVAL;
3005 }
3006 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
3007 return -ENOSYS;
3008 }
3009 if (out->pcm == NULL) {
3010 return -ENOSYS;
3011 }
3012
3013 struct timespec ts = { 0, 0 };
3014 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
3015 if (ret < 0) {
3016 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
3017 return ret;
3018 }
Andy Hungfc044e12017-03-20 09:24:22 -07003019 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003020 return 0;
3021}
3022
3023
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003024/** audio_stream_in implementation **/
3025static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3026{
3027 struct stream_in *in = (struct stream_in *)stream;
3028
3029 return in->config.rate;
3030}
3031
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003032static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003033{
3034 return -ENOSYS;
3035}
3036
3037static size_t in_get_buffer_size(const struct audio_stream *stream)
3038{
3039 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003040 return in->config.period_size * in->af_period_multiplier *
3041 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003042}
3043
3044static uint32_t in_get_channels(const struct audio_stream *stream)
3045{
3046 struct stream_in *in = (struct stream_in *)stream;
3047
3048 return in->channel_mask;
3049}
3050
vivek mehta4ed66e62016-04-15 23:33:34 -07003051static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003052{
vivek mehta4ed66e62016-04-15 23:33:34 -07003053 struct stream_in *in = (struct stream_in *)stream;
3054 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003055}
3056
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003057static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003058{
3059 return -ENOSYS;
3060}
3061
3062static int in_standby(struct audio_stream *stream)
3063{
3064 struct stream_in *in = (struct stream_in *)stream;
3065 struct audio_device *adev = in->dev;
3066 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003067 bool do_stop = true;
3068
Eric Laurent994a6932013-07-17 11:51:42 -07003069 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003070
3071 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003072
3073 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003074 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003075 audio_extn_sound_trigger_stop_lab(in);
3076 in->standby = true;
3077 }
3078
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003079 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003080 if (adev->adm_deregister_stream)
3081 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3082
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003083 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003084 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003085 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003086 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003087 in->capture_started = false;
3088 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003089 if (in->pcm) {
3090 pcm_close(in->pcm);
3091 in->pcm = NULL;
3092 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003093 adev->enable_voicerx = false;
3094 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003095 if (do_stop) {
3096 status = stop_input_stream(in);
3097 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003098 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003099 }
3100 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003101 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003102 return status;
3103}
3104
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003105static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003106{
3107 return 0;
3108}
3109
3110static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3111{
3112 struct stream_in *in = (struct stream_in *)stream;
3113 struct audio_device *adev = in->dev;
3114 struct str_parms *parms;
3115 char *str;
3116 char value[32];
3117 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003118 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003119
Eric Laurent994a6932013-07-17 11:51:42 -07003120 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003121 parms = str_parms_create_str(kvpairs);
3122
3123 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3124
Eric Laurenta1478072015-09-21 17:21:52 -07003125 lock_input_stream(in);
3126
Eric Laurent150dbfe2013-02-27 14:31:02 -08003127 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003128 if (ret >= 0) {
3129 val = atoi(value);
3130 /* no audio source uses val == 0 */
3131 if ((in->source != val) && (val != 0)) {
3132 in->source = val;
3133 }
3134 }
3135
3136 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003137
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003138 if (ret >= 0) {
3139 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003140 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003141
3142 // Workaround: If routing to an non existing usb device, fail gracefully
3143 // The routing request will otherwise block during 10 second
3144 if (audio_is_usb_in_device(val) && !audio_extn_usb_alive(adev->snd_card)) {
3145 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d",
3146 adev->snd_card);
3147 status = -ENOSYS;
3148 } else {
3149
3150 in->device = val;
3151 /* If recording is in progress, change the tx device to new device */
3152 if (!in->standby) {
3153 ALOGV("update input routing change");
3154 // inform adm before actual routing to prevent glitches.
3155 if (adev->adm_on_routing_change) {
3156 adev->adm_on_routing_change(adev->adm_data,
3157 in->capture_handle);
3158 }
3159 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003160 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003161 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003162 }
3163 }
3164
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003165 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003166 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003167
3168 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003169 ALOGV("%s: exit: status(%d)", __func__, status);
3170 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003171}
3172
Haynes Mathew George569b7482017-05-08 14:44:27 -07003173static char* in_get_parameters(const struct audio_stream *stream,
3174 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003175{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003176 struct stream_in *in = (struct stream_in *)stream;
3177 struct str_parms *query = str_parms_create_str(keys);
3178 char *str;
3179 struct str_parms *reply = str_parms_create();
3180 bool replied = false;
3181
3182 ALOGV("%s: enter: keys - %s", __func__, keys);
3183 replied |= stream_get_parameter_channels(query, reply,
3184 &in->supported_channel_masks[0]);
3185 replied |= stream_get_parameter_formats(query, reply,
3186 &in->supported_formats[0]);
3187 replied |= stream_get_parameter_rates(query, reply,
3188 &in->supported_sample_rates[0]);
3189 if (replied) {
3190 str = str_parms_to_str(reply);
3191 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003192 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003193 }
3194 str_parms_destroy(query);
3195 str_parms_destroy(reply);
3196 ALOGV("%s: exit: returns - %s", __func__, str);
3197 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003198}
3199
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003200static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003201{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003202 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003203}
3204
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003205static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3206{
3207 if (!stream || !parms)
3208 return;
3209
3210 struct stream_in *in = (struct stream_in *)stream;
3211 struct audio_device *adev = in->dev;
3212
3213 card_status_t status;
3214 int card;
3215 if (parse_snd_card_status(parms, &card, &status) < 0)
3216 return;
3217
3218 pthread_mutex_lock(&adev->lock);
3219 bool valid_cb = (card == adev->snd_card);
3220 pthread_mutex_unlock(&adev->lock);
3221
3222 if (!valid_cb)
3223 return;
3224
3225 lock_input_stream(in);
3226 if (in->card_status != status)
3227 in->card_status = status;
3228 pthread_mutex_unlock(&in->lock);
3229
3230 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3231 use_case_table[in->usecase],
3232 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3233
3234 // a better solution would be to report error back to AF and let
3235 // it put the stream to standby
3236 if (status == CARD_STATUS_OFFLINE)
3237 in_standby(&in->stream.common);
3238
3239 return;
3240}
3241
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003242static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3243 size_t bytes)
3244{
3245 struct stream_in *in = (struct stream_in *)stream;
3246 struct audio_device *adev = in->dev;
3247 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003248 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003249
Eric Laurenta1478072015-09-21 17:21:52 -07003250 lock_input_stream(in);
Andy Hung928efbe2017-06-12 14:05:22 -07003251 const size_t frame_size = audio_stream_in_frame_size(stream);
3252 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003253
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003254 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003255 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003256 /* Read from sound trigger HAL */
3257 audio_extn_sound_trigger_read(in, buffer, bytes);
3258 pthread_mutex_unlock(&in->lock);
3259 return bytes;
3260 }
3261
Eric Laurent0e46adf2016-12-16 12:49:24 -08003262 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3263 ret = -ENOSYS;
3264 goto exit;
3265 }
3266
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003267 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003268 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003269 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003270 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003271 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003272 goto exit;
3273 }
3274 in->standby = 0;
3275 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003276
Haynes Mathew George03c40102016-01-29 17:57:48 -08003277 //what's the duration requested by the client?
3278 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3279 in->config.rate;
3280 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003281
Haynes Mathew George03c40102016-01-29 17:57:48 -08003282 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003283 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003284 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003285 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003286 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003287 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003288 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003289 if (ret < 0) {
3290 ALOGE("Failed to read w/err %s", strerror(errno));
3291 ret = -errno;
3292 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003293 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3294 if (bytes % 4 == 0) {
3295 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3296 int_buf_stream = buffer;
3297 for (size_t itt=0; itt < bytes/4 ; itt++) {
3298 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003299 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003300 } else {
3301 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3302 ret = -EINVAL;
3303 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003304 }
3305 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003306 }
3307
Haynes Mathew George03c40102016-01-29 17:57:48 -08003308 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003309
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003310 /*
3311 * Instead of writing zeroes here, we could trust the hardware
3312 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003313 * 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 -08003314 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003315 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003316 memset(buffer, 0, bytes);
3317
3318exit:
3319 pthread_mutex_unlock(&in->lock);
3320
3321 if (ret != 0) {
3322 in_standby(&in->stream.common);
3323 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung928efbe2017-06-12 14:05:22 -07003324 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003325 memset(buffer, 0, bytes); // clear return data
3326 }
3327 if (bytes > 0) {
Andy Hung928efbe2017-06-12 14:05:22 -07003328 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003329 }
3330 return bytes;
3331}
3332
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003333static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003334{
3335 return 0;
3336}
3337
Andy Hung6ebe5962016-01-15 17:46:57 -08003338static int in_get_capture_position(const struct audio_stream_in *stream,
3339 int64_t *frames, int64_t *time)
3340{
3341 if (stream == NULL || frames == NULL || time == NULL) {
3342 return -EINVAL;
3343 }
3344 struct stream_in *in = (struct stream_in *)stream;
3345 int ret = -ENOSYS;
3346
3347 lock_input_stream(in);
3348 if (in->pcm) {
3349 struct timespec timestamp;
3350 unsigned int avail;
3351 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3352 *frames = in->frames_read + avail;
3353 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3354 ret = 0;
3355 }
3356 }
3357 pthread_mutex_unlock(&in->lock);
3358 return ret;
3359}
3360
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003361static int add_remove_audio_effect(const struct audio_stream *stream,
3362 effect_handle_t effect,
3363 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003364{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003365 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003366 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003367 int status = 0;
3368 effect_descriptor_t desc;
3369
3370 status = (*effect)->get_descriptor(effect, &desc);
3371 if (status != 0)
3372 return status;
3373
Eric Laurenta1478072015-09-21 17:21:52 -07003374 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003375 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003376 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003377 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003378 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003379 in->enable_aec != enable &&
3380 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3381 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003382 if (!enable)
3383 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003384 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3385 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3386 adev->enable_voicerx = enable;
3387 struct audio_usecase *usecase;
3388 struct listnode *node;
3389 list_for_each(node, &adev->usecase_list) {
3390 usecase = node_to_item(node, struct audio_usecase, list);
3391 if (usecase->type == PCM_PLAYBACK) {
3392 select_devices(adev, usecase->id);
3393 break;
3394 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003395 }
3396 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003397 if (!in->standby)
3398 select_devices(in->dev, in->usecase);
3399 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003400 if (in->enable_ns != enable &&
3401 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3402 in->enable_ns = enable;
3403 if (!in->standby)
3404 select_devices(in->dev, in->usecase);
3405 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003406 pthread_mutex_unlock(&in->dev->lock);
3407 pthread_mutex_unlock(&in->lock);
3408
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003409 return 0;
3410}
3411
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003412static int in_add_audio_effect(const struct audio_stream *stream,
3413 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003414{
Eric Laurent994a6932013-07-17 11:51:42 -07003415 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003416 return add_remove_audio_effect(stream, effect, true);
3417}
3418
3419static int in_remove_audio_effect(const struct audio_stream *stream,
3420 effect_handle_t effect)
3421{
Eric Laurent994a6932013-07-17 11:51:42 -07003422 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003423 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003424}
3425
Eric Laurent0e46adf2016-12-16 12:49:24 -08003426static int in_stop(const struct audio_stream_in* stream)
3427{
3428 struct stream_in *in = (struct stream_in *)stream;
3429 struct audio_device *adev = in->dev;
3430
3431 int ret = -ENOSYS;
3432 ALOGV("%s", __func__);
3433 pthread_mutex_lock(&adev->lock);
3434 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3435 in->capture_started && in->pcm != NULL) {
3436 pcm_stop(in->pcm);
3437 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003438 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003439 }
3440 pthread_mutex_unlock(&adev->lock);
3441 return ret;
3442}
3443
3444static int in_start(const struct audio_stream_in* stream)
3445{
3446 struct stream_in *in = (struct stream_in *)stream;
3447 struct audio_device *adev = in->dev;
3448 int ret = -ENOSYS;
3449
3450 ALOGV("%s in %p", __func__, in);
3451 pthread_mutex_lock(&adev->lock);
3452 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3453 !in->capture_started && in->pcm != NULL) {
3454 if (!in->capture_started) {
3455 ret = start_input_stream(in);
3456 if (ret == 0) {
3457 in->capture_started = true;
3458 }
3459 }
3460 }
3461 pthread_mutex_unlock(&adev->lock);
3462 return ret;
3463}
3464
3465static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3466 int32_t min_size_frames,
3467 struct audio_mmap_buffer_info *info)
3468{
3469 struct stream_in *in = (struct stream_in *)stream;
3470 struct audio_device *adev = in->dev;
3471 int ret = 0;
3472 unsigned int offset1;
3473 unsigned int frames1;
3474 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003475 uint32_t mmap_size;
3476 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003477
3478 pthread_mutex_lock(&adev->lock);
3479 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003480
Eric Laurent0e46adf2016-12-16 12:49:24 -08003481 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003482 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003483 ret = -EINVAL;
3484 goto exit;
3485 }
3486 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003487 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003488 ALOGV("%s in %p", __func__, in);
3489 ret = -ENOSYS;
3490 goto exit;
3491 }
3492 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3493 if (in->pcm_device_id < 0) {
3494 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3495 __func__, in->pcm_device_id, in->usecase);
3496 ret = -EINVAL;
3497 goto exit;
3498 }
Phil Burkbc991042017-02-24 08:06:44 -08003499
3500 adjust_mmap_period_count(&in->config, min_size_frames);
3501
Eric Laurent0e46adf2016-12-16 12:49:24 -08003502 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3503 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3504 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3505 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3506 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3507 step = "open";
3508 ret = -ENODEV;
3509 goto exit;
3510 }
3511
3512 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3513 if (ret < 0) {
3514 step = "begin";
3515 goto exit;
3516 }
3517 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003518 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003519 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003520 ret = platform_get_mmap_data_fd(adev->platform,
3521 in->pcm_device_id, 1 /*capture*/,
3522 &info->shared_memory_fd,
3523 &mmap_size);
3524 if (ret < 0) {
3525 // Fall back to non exclusive mode
3526 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3527 } else {
3528 if (mmap_size < buffer_size) {
3529 step = "mmap";
3530 goto exit;
3531 }
3532 // FIXME: indicate exclusive mode support by returning a negative buffer size
3533 info->buffer_size_frames *= -1;
3534 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08003535
Haynes Mathew George96483a22017-03-28 14:52:47 -07003536 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003537
3538 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3539 if (ret < 0) {
3540 step = "commit";
3541 goto exit;
3542 }
3543
Phil Burkbc991042017-02-24 08:06:44 -08003544 in->standby = false;
3545 ret = 0;
3546
Eric Laurent0e46adf2016-12-16 12:49:24 -08003547 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3548 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003549
3550exit:
3551 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003552 if (in->pcm == NULL) {
3553 ALOGE("%s: %s - %d", __func__, step, ret);
3554 } else {
3555 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003556 pcm_close(in->pcm);
3557 in->pcm = NULL;
3558 }
3559 }
3560 pthread_mutex_unlock(&adev->lock);
3561 return ret;
3562}
3563
3564static int in_get_mmap_position(const struct audio_stream_in *stream,
3565 struct audio_mmap_position *position)
3566{
3567 struct stream_in *in = (struct stream_in *)stream;
3568 ALOGVV("%s", __func__);
3569 if (position == NULL) {
3570 return -EINVAL;
3571 }
3572 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
3573 return -ENOSYS;
3574 }
3575 if (in->pcm == NULL) {
3576 return -ENOSYS;
3577 }
3578 struct timespec ts = { 0, 0 };
3579 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
3580 if (ret < 0) {
3581 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3582 return ret;
3583 }
Andy Hungfc044e12017-03-20 09:24:22 -07003584 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003585 return 0;
3586}
3587
3588
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003589static int adev_open_output_stream(struct audio_hw_device *dev,
3590 audio_io_handle_t handle,
3591 audio_devices_t devices,
3592 audio_output_flags_t flags,
3593 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003594 struct audio_stream_out **stream_out,
3595 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003596{
3597 struct audio_device *adev = (struct audio_device *)dev;
3598 struct stream_out *out;
3599 int i, ret;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003600 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
3601 bool is_usb_dev = audio_is_usb_out_device(devices) &&
3602 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
3603 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003604
Andy Hungd9653bd2017-08-01 19:31:39 -07003605 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
3606 return -ENOSYS;
3607 }
3608
Eric Laurent994a6932013-07-17 11:51:42 -07003609 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003610 __func__, config->sample_rate, config->channel_mask, devices, flags);
3611 *stream_out = NULL;
3612 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3613
3614 if (devices == AUDIO_DEVICE_NONE)
3615 devices = AUDIO_DEVICE_OUT_SPEAKER;
3616
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003617 out->flags = flags;
3618 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003619 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003620 out->format = config->format;
3621 out->sample_rate = config->sample_rate;
3622 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3623 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003624 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003625
3626 /* Init use case and pcm_config */
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003627 if (audio_is_linear_pcm(out->format) &&
3628 (out->flags == AUDIO_OUTPUT_FLAG_NONE ||
Haynes Mathew George569b7482017-05-08 14:44:27 -07003629 out->flags == AUDIO_OUTPUT_FLAG_DIRECT) && direct_dev) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003630 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003631 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003632 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003633 if (config->sample_rate == 0)
3634 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3635 if (config->channel_mask == 0)
3636 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3637 if (config->format == AUDIO_FORMAT_DEFAULT)
3638 config->format = AUDIO_FORMAT_PCM_16_BIT;
3639 } else if (is_usb_dev) {
3640 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
3641 &config->format,
3642 &out->supported_formats[0],
3643 MAX_SUPPORTED_FORMATS,
3644 &config->channel_mask,
3645 &out->supported_channel_masks[0],
3646 MAX_SUPPORTED_CHANNEL_MASKS,
3647 &config->sample_rate,
3648 &out->supported_sample_rates[0],
3649 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003650 ALOGV("plugged dev USB ret %d", ret);
3651 } else {
3652 ret = -1;
3653 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003654 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003655 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003656 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003657
Haynes Mathew George569b7482017-05-08 14:44:27 -07003658 out->channel_mask = config->channel_mask;
3659 out->sample_rate = config->sample_rate;
3660 out->format = config->format;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003661 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3662 // does this change?
Haynes Mathew George569b7482017-05-08 14:44:27 -07003663 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003664 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003665 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Andy Hung928efbe2017-06-12 14:05:22 -07003666 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
3667 audio_bytes_per_sample(config->format));
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003668 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003669 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003670 pthread_mutex_lock(&adev->lock);
3671 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3672 pthread_mutex_unlock(&adev->lock);
3673
3674 // reject offload during card offline to allow
3675 // fallback to s/w paths
3676 if (offline) {
3677 ret = -ENODEV;
3678 goto error_open;
3679 }
3680
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003681 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3682 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3683 ALOGE("%s: Unsupported Offload information", __func__);
3684 ret = -EINVAL;
3685 goto error_open;
3686 }
3687 if (!is_supported_format(config->offload_info.format)) {
3688 ALOGE("%s: Unsupported audio format", __func__);
3689 ret = -EINVAL;
3690 goto error_open;
3691 }
3692
3693 out->compr_config.codec = (struct snd_codec *)
3694 calloc(1, sizeof(struct snd_codec));
3695
3696 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3697 if (config->offload_info.channel_mask)
3698 out->channel_mask = config->offload_info.channel_mask;
3699 else if (config->channel_mask)
3700 out->channel_mask = config->channel_mask;
3701 out->format = config->offload_info.format;
3702 out->sample_rate = config->offload_info.sample_rate;
3703
3704 out->stream.set_callback = out_set_callback;
3705 out->stream.pause = out_pause;
3706 out->stream.resume = out_resume;
3707 out->stream.drain = out_drain;
3708 out->stream.flush = out_flush;
3709
3710 out->compr_config.codec->id =
3711 get_snd_codec_id(config->offload_info.format);
3712 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3713 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07003714 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003715 out->compr_config.codec->bit_rate =
3716 config->offload_info.bit_rate;
3717 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003718 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003719 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3720
3721 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3722 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003723
3724 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003725 create_offload_callback_thread(out);
3726 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3727 __func__, config->offload_info.version,
3728 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003729 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07003730 switch (config->sample_rate) {
3731 case 8000:
3732 case 16000:
3733 case 48000:
3734 out->sample_rate = config->sample_rate;
3735 break;
3736 default:
3737 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003738 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003739 out->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003740 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3741 out->config = pcm_config_afe_proxy_playback;
3742 adev->voice_tx_output = out;
David Lin6b00c232017-07-26 00:20:16 -07003743 } else if (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT |
3744 AUDIO_OUTPUT_FLAG_VOIP_RX)) {
vivek mehtaa68fea62017-06-08 19:04:02 -07003745 uint32_t buffer_size, frame_size;
3746 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
3747 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
3748 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
3749 out->config = pcm_config_voip;
3750 out->config.format = pcm_format_from_audio_format(config->format);
3751 out->config.rate = config->sample_rate;
3752 out->config.channels =
3753 audio_channel_count_from_out_mask(config->channel_mask);
3754 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
3755 config->sample_rate,
3756 config->format,
3757 out->config.channels,
3758 false /*is_low_latency*/);
3759 frame_size = audio_bytes_per_sample(config->format) * out->config.channels;
3760 out->config.period_size = buffer_size / frame_size;
3761 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
3762 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003763 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003764 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3765 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3766 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003767 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
3768 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3769 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003770 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3771 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003772 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003773 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003774 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3775 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3776 out->config = pcm_config_mmap_playback;
3777 out->stream.start = out_start;
3778 out->stream.stop = out_stop;
3779 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3780 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003781 } else {
3782 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3783 out->config = pcm_config_low_latency;
3784 }
3785 if (config->format != audio_format_from_pcm_format(out->config.format)) {
Haynes Mathew Georgedf0f8862017-06-28 13:36:40 -07003786 out->config.format = pcm_format_from_audio_format(config->format);
Andy Hung6fcba9c2014-03-18 11:53:32 -07003787 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003788 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003789 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003790
3791 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
3792 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
3793 (config->channel_mask != 0 && config->channel_mask != out->channel_mask)) {
3794 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
3795 __func__, config->sample_rate, config->format, config->channel_mask);
3796 config->sample_rate = out->sample_rate;
3797 config->format = out->format;
3798 config->channel_mask = out->channel_mask;
3799 ret = -EINVAL;
3800 goto error_open;
3801 }
3802
Andy Hung6fcba9c2014-03-18 11:53:32 -07003803 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3804 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003805
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003806 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003807 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003808 adev->primary_output = out;
3809 else {
3810 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003811 ret = -EEXIST;
3812 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003813 }
3814 }
3815
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003816 /* Check if this usecase is already existing */
3817 pthread_mutex_lock(&adev->lock);
3818 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3819 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003820 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003821 ret = -EEXIST;
3822 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003823 }
3824 pthread_mutex_unlock(&adev->lock);
3825
3826 out->stream.common.get_sample_rate = out_get_sample_rate;
3827 out->stream.common.set_sample_rate = out_set_sample_rate;
3828 out->stream.common.get_buffer_size = out_get_buffer_size;
3829 out->stream.common.get_channels = out_get_channels;
3830 out->stream.common.get_format = out_get_format;
3831 out->stream.common.set_format = out_set_format;
3832 out->stream.common.standby = out_standby;
3833 out->stream.common.dump = out_dump;
3834 out->stream.common.set_parameters = out_set_parameters;
3835 out->stream.common.get_parameters = out_get_parameters;
3836 out->stream.common.add_audio_effect = out_add_audio_effect;
3837 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3838 out->stream.get_latency = out_get_latency;
3839 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003840#ifdef NO_AUDIO_OUT
3841 out->stream.write = out_write_for_no_output;
3842#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003843 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003844#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003845 out->stream.get_render_position = out_get_render_position;
3846 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003847 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003848
Eric Laurent0e46adf2016-12-16 12:49:24 -08003849 if (out->realtime)
3850 out->af_period_multiplier = af_period_multiplier;
3851 else
3852 out->af_period_multiplier = 1;
3853
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003854 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003855 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003856 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003857
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003858 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003859 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003860 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3861
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003862 config->format = out->stream.common.get_format(&out->stream.common);
3863 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3864 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3865
Andy Hunga452b0a2017-03-15 14:51:15 -07003866 out->error_log = error_log_create(
3867 ERROR_LOG_ENTRIES,
3868 1000000000 /* aggregate consecutive identical errors within one second in ns */);
3869
Andy Hungfc044e12017-03-20 09:24:22 -07003870 // power_log may be null if the format is not supported
Andy Hung9e737de2017-05-22 10:51:22 -07003871 // or not a userdebug or eng build.
Andy Hung02caae52017-06-06 12:33:33 -07003872 if (false /* is_userdebug_or_eng_build() */) {
Andy Hung9e737de2017-05-22 10:51:22 -07003873 const size_t POWER_LOG_FRAMES_PER_ENTRY =
3874 (long long)config->sample_rate * POWER_LOG_SAMPLING_INTERVAL_MS / 1000;
3875
3876 out->power_log = power_log_create(
3877 config->sample_rate,
3878 audio_channel_count_from_out_mask(config->channel_mask),
3879 config->format,
3880 POWER_LOG_ENTRIES,
3881 POWER_LOG_FRAMES_PER_ENTRY);
3882 }
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003883
3884 /*
3885 By locking output stream before registering, we allow the callback
3886 to update stream's state only after stream's initial state is set to
3887 adev state.
3888 */
3889 lock_output_stream(out);
3890 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3891 pthread_mutex_lock(&adev->lock);
3892 out->card_status = adev->card_status;
3893 pthread_mutex_unlock(&adev->lock);
3894 pthread_mutex_unlock(&out->lock);
3895
vivek mehta4a824772017-06-08 19:05:49 -07003896 stream_app_type_cfg_init(&out->app_type_cfg);
3897
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003898 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003899
Eric Laurent994a6932013-07-17 11:51:42 -07003900 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003901 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003902
3903error_open:
3904 free(out);
3905 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003906 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003907 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003908}
3909
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003910static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003911 struct audio_stream_out *stream)
3912{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003913 struct stream_out *out = (struct stream_out *)stream;
3914 struct audio_device *adev = out->dev;
3915
Eric Laurent994a6932013-07-17 11:51:42 -07003916 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003917
3918 // must deregister from sndmonitor first to prevent races
3919 // between the callback and close_stream
3920 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003921 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003922 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3923 destroy_offload_callback_thread(out);
3924
3925 if (out->compr_config.codec != NULL)
3926 free(out->compr_config.codec);
3927 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003928
3929 if (adev->voice_tx_output == out)
3930 adev->voice_tx_output = NULL;
3931
Andy Hungfc044e12017-03-20 09:24:22 -07003932 power_log_destroy(out->power_log);
3933 out->power_log = NULL;
3934
Andy Hunga452b0a2017-03-15 14:51:15 -07003935 error_log_destroy(out->error_log);
3936 out->error_log = NULL;
3937
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003938 pthread_cond_destroy(&out->cond);
3939 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003940 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003941 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003942}
3943
3944static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3945{
3946 struct audio_device *adev = (struct audio_device *)dev;
3947 struct str_parms *parms;
3948 char *str;
3949 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003950 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003951 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003952 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003953
Joe Onorato188b6222016-03-01 11:02:27 -08003954 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003955
3956 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003957
3958 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003959 status = voice_set_parameters(adev, parms);
3960 if (status != 0) {
3961 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003962 }
3963
3964 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3965 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003966 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003967 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3968 adev->bluetooth_nrec = true;
3969 else
3970 adev->bluetooth_nrec = false;
3971 }
3972
3973 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3974 if (ret >= 0) {
3975 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3976 adev->screen_off = false;
3977 else
3978 adev->screen_off = true;
3979 }
3980
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003981 ret = str_parms_get_int(parms, "rotation", &val);
3982 if (ret >= 0) {
3983 bool reverse_speakers = false;
3984 switch(val) {
3985 // FIXME: note that the code below assumes that the speakers are in the correct placement
3986 // relative to the user when the device is rotated 90deg from its default rotation. This
3987 // assumption is device-specific, not platform-specific like this code.
3988 case 270:
3989 reverse_speakers = true;
3990 break;
3991 case 0:
3992 case 90:
3993 case 180:
3994 break;
3995 default:
3996 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003997 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003998 }
Eric Laurent03f09432014-03-25 18:09:11 -07003999 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004000 // check and set swap
4001 // - check if orientation changed and speaker active
4002 // - set rotation and cache the rotation value
4003 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004004 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004005 }
4006
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004007 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4008 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004009 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004010 }
4011
David Linee3fe402017-03-13 10:00:42 -07004012 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4013 if (ret >= 0) {
4014 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004015 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004016 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4017 if (ret >= 0) {
4018 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004019 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004020 }
Eric Laurent99dab492017-06-17 15:19:08 -07004021 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004022 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4023 if (ret >= 0) {
4024 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004025 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004026 }
4027 }
4028 }
4029
4030 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4031 if (ret >= 0) {
4032 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004033 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004034 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4035 if (ret >= 0) {
4036 const int card = atoi(value);
4037
Eric Laurent99dab492017-06-17 15:19:08 -07004038 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004039 }
Eric Laurent99dab492017-06-17 15:19:08 -07004040 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004041 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4042 if (ret >= 0) {
4043 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004044 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004045 }
4046 }
4047 }
4048
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004049 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004050done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004051 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004052 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004053 ALOGV("%s: exit with code(%d)", __func__, status);
4054 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004055}
4056
4057static char* adev_get_parameters(const struct audio_hw_device *dev,
4058 const char *keys)
4059{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004060 struct audio_device *adev = (struct audio_device *)dev;
4061 struct str_parms *reply = str_parms_create();
4062 struct str_parms *query = str_parms_create_str(keys);
4063 char *str;
4064
4065 pthread_mutex_lock(&adev->lock);
4066
4067 voice_get_parameters(adev, query, reply);
4068 str = str_parms_to_str(reply);
4069 str_parms_destroy(query);
4070 str_parms_destroy(reply);
4071
4072 pthread_mutex_unlock(&adev->lock);
4073 ALOGV("%s: exit: returns - %s", __func__, str);
4074 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004075}
4076
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004077static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004078{
4079 return 0;
4080}
4081
Haynes Mathew George5191a852013-09-11 14:19:36 -07004082static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4083{
4084 int ret;
4085 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004086
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004087 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4088
Haynes Mathew George5191a852013-09-11 14:19:36 -07004089 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004090 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004091 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004092
Haynes Mathew George5191a852013-09-11 14:19:36 -07004093 return ret;
4094}
4095
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004096static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004097{
4098 return -ENOSYS;
4099}
4100
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004101static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4102 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004103{
4104 return -ENOSYS;
4105}
4106
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004107static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004108{
4109 return -ENOSYS;
4110}
4111
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004112static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004113{
4114 return -ENOSYS;
4115}
4116
4117static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4118{
4119 struct audio_device *adev = (struct audio_device *)dev;
4120
4121 pthread_mutex_lock(&adev->lock);
4122 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004123 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004124 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004125 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4126 voice_is_in_call(adev)) {
4127 voice_stop_call(adev);
4128 adev->current_call_output = NULL;
4129 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004130 }
4131 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004132
4133 audio_extn_extspk_set_mode(adev->extspk, mode);
4134
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004135 return 0;
4136}
4137
4138static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4139{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004140 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004141 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004142
Eric Laurent2bafff12016-03-17 12:17:23 -07004143 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004144 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004145 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4146 ret = audio_extn_hfp_set_mic_mute(adev, state);
4147 } else {
4148 ret = voice_set_mic_mute(adev, state);
4149 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004150 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004151 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004152
4153 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004154}
4155
4156static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4157{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004158 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004159 return 0;
4160}
4161
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004162static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004163 const struct audio_config *config)
4164{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004165 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004166
Eric Laurent74b55762017-07-09 17:04:53 -07004167 /* Don't know if USB HIFI in this context so use true to be conservative */
4168 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4169 true /*is_usb_hifi */) != 0)
4170 return 0;
4171
vivek mehtaa68fea62017-06-08 19:04:02 -07004172 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4173 config->sample_rate, config->format,
4174 channel_count,
4175 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004176}
4177
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004178static bool adev_input_allow_hifi_record(struct audio_device *adev,
4179 audio_devices_t devices,
4180 audio_input_flags_t flags,
4181 audio_source_t source) {
4182 const bool allowed = true;
4183
4184 if (!audio_is_usb_in_device(devices))
4185 return !allowed;
4186
4187 switch (flags) {
4188 case AUDIO_INPUT_FLAG_NONE:
4189 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4190 break;
4191 default:
4192 return !allowed;
4193 }
4194
4195 switch (source) {
4196 case AUDIO_SOURCE_DEFAULT:
4197 case AUDIO_SOURCE_MIC:
4198 case AUDIO_SOURCE_UNPROCESSED:
4199 break;
4200 default:
4201 return !allowed;
4202 }
4203
4204 switch (adev->mode) {
4205 case 0:
4206 break;
4207 default:
4208 return !allowed;
4209 }
4210
4211 return allowed;
4212}
4213
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004214static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004215 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004216 audio_devices_t devices,
4217 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004218 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004219 audio_input_flags_t flags,
4220 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004221 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004222{
4223 struct audio_device *adev = (struct audio_device *)dev;
4224 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004225 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004226 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004227 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004228 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004229 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4230 devices,
4231 flags,
4232 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004233 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004234 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004235
Andy Hungd9653bd2017-08-01 19:31:39 -07004236 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
4237 return -ENOSYS;
4238 }
4239
Eric Laurent74b55762017-07-09 17:04:53 -07004240 if (!(is_usb_dev && may_use_hifi_record)) {
4241 if (config->sample_rate == 0)
4242 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4243 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4244 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4245 if (config->format == AUDIO_FORMAT_DEFAULT)
4246 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004247
Eric Laurent74b55762017-07-09 17:04:53 -07004248 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
4249
4250 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
4251 return -EINVAL;
4252 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004253
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004254 if (audio_extn_tfa_98xx_is_supported() &&
4255 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004256 return -EINVAL;
4257
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004258 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4259
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004260 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004261 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004262
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004263 in->stream.common.get_sample_rate = in_get_sample_rate;
4264 in->stream.common.set_sample_rate = in_set_sample_rate;
4265 in->stream.common.get_buffer_size = in_get_buffer_size;
4266 in->stream.common.get_channels = in_get_channels;
4267 in->stream.common.get_format = in_get_format;
4268 in->stream.common.set_format = in_set_format;
4269 in->stream.common.standby = in_standby;
4270 in->stream.common.dump = in_dump;
4271 in->stream.common.set_parameters = in_set_parameters;
4272 in->stream.common.get_parameters = in_get_parameters;
4273 in->stream.common.add_audio_effect = in_add_audio_effect;
4274 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4275 in->stream.set_gain = in_set_gain;
4276 in->stream.read = in_read;
4277 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08004278 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004279
4280 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004281 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004282 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004283 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004284 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004285 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004286
Haynes Mathew George569b7482017-05-08 14:44:27 -07004287 if (is_usb_dev && may_use_hifi_record) {
4288 /* HiFi record selects an appropriate format, channel, rate combo
4289 depending on sink capabilities*/
4290 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
4291 &config->format,
4292 &in->supported_formats[0],
4293 MAX_SUPPORTED_FORMATS,
4294 &config->channel_mask,
4295 &in->supported_channel_masks[0],
4296 MAX_SUPPORTED_CHANNEL_MASKS,
4297 &config->sample_rate,
4298 &in->supported_sample_rates[0],
4299 MAX_SUPPORTED_SAMPLE_RATES);
4300 if (ret != 0) {
4301 ret = -EINVAL;
4302 goto err_open;
4303 }
Eric Laurent74b55762017-07-09 17:04:53 -07004304 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004305 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07004306 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07004307 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
4308 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
4309 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4310 bool ret_error = false;
4311 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4312 from HAL is 8_24
4313 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4314 8_24 return error indicating supported format is 8_24
4315 *> In case of any other source requesting 24 bit or float return error
4316 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07004317
vivek mehta57ff9b52016-04-28 14:13:08 -07004318 on error flinger will retry with supported format passed
4319 */
4320 if (source != AUDIO_SOURCE_UNPROCESSED) {
4321 config->format = AUDIO_FORMAT_PCM_16_BIT;
4322 ret_error = true;
4323 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
4324 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
4325 ret_error = true;
4326 }
4327
4328 if (ret_error) {
4329 ret = -EINVAL;
4330 goto err_open;
4331 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004332 }
4333
vivek mehta57ff9b52016-04-28 14:13:08 -07004334 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07004335 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07004336
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004337 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004338 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
4339 if (config->sample_rate == 0)
4340 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4341 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4342 config->sample_rate != 8000) {
4343 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4344 ret = -EINVAL;
4345 goto err_open;
4346 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004347
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004348 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4349 config->format = AUDIO_FORMAT_PCM_16_BIT;
4350 ret = -EINVAL;
4351 goto err_open;
4352 }
4353
4354 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4355 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07004356 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004357 } else if (is_usb_dev && may_use_hifi_record) {
4358 in->usecase = USECASE_AUDIO_RECORD_HIFI;
4359 in->config = pcm_config_audio_capture;
4360 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004361 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4362 config->sample_rate,
4363 config->format,
4364 channel_count,
4365 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004366 in->config.period_size = buffer_size / frame_size;
4367 in->config.rate = config->sample_rate;
4368 in->af_period_multiplier = 1;
4369 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004370 } else {
4371 in->usecase = USECASE_AUDIO_RECORD;
4372 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08004373 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004374 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07004375#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004376 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07004377#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08004378 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004379 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08004380 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004381 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004382 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4383 config->sample_rate,
4384 config->format,
4385 channel_count,
4386 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004387 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004388 in->config.rate = config->sample_rate;
4389 in->af_period_multiplier = 1;
4390 } else {
4391 // period size is left untouched for rt mode playback
4392 in->config = pcm_config_audio_capture_rt;
4393 in->af_period_multiplier = af_period_multiplier;
4394 }
4395 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
4396 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004397 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08004398 in->usecase = USECASE_AUDIO_RECORD_MMAP;
4399 in->config = pcm_config_mmap_capture;
4400 in->stream.start = in_start;
4401 in->stream.stop = in_stop;
4402 in->stream.create_mmap_buffer = in_create_mmap_buffer;
4403 in->stream.get_mmap_position = in_get_mmap_position;
4404 in->af_period_multiplier = 1;
4405 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07004406 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07004407 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07004408 (config->sample_rate == 8000 ||
4409 config->sample_rate == 16000 ||
4410 config->sample_rate == 32000 ||
4411 config->sample_rate == 48000) &&
4412 channel_count == 1) {
4413 in->usecase = USECASE_AUDIO_RECORD_VOIP;
4414 in->config = pcm_config_audio_capture;
4415 frame_size = audio_stream_in_frame_size(&in->stream);
4416 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
4417 config->sample_rate,
4418 config->format,
4419 channel_count, false /*is_low_latency*/);
4420 in->config.period_size = buffer_size / frame_size;
4421 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
4422 in->config.rate = config->sample_rate;
4423 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004424 } else {
4425 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004426 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004427 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4428 config->sample_rate,
4429 config->format,
4430 channel_count,
4431 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004432 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004433 in->config.rate = config->sample_rate;
4434 in->af_period_multiplier = 1;
4435 }
4436 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
4437 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004438 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004439
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004440 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07004441 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004442
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004443 /* This stream could be for sound trigger lab,
4444 get sound trigger pcm if present */
4445 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004446
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004447 lock_input_stream(in);
4448 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
4449 pthread_mutex_lock(&adev->lock);
4450 in->card_status = adev->card_status;
4451 pthread_mutex_unlock(&adev->lock);
4452 pthread_mutex_unlock(&in->lock);
4453
vivek mehta4a824772017-06-08 19:05:49 -07004454 stream_app_type_cfg_init(&in->app_type_cfg);
4455
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004456 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004457 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004458 return 0;
4459
4460err_open:
4461 free(in);
4462 *stream_in = NULL;
4463 return ret;
4464}
4465
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004466static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004467 struct audio_stream_in *stream)
4468{
Eric Laurent994a6932013-07-17 11:51:42 -07004469 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004470
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004471 // must deregister from sndmonitor first to prevent races
4472 // between the callback and close_stream
4473 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004474 in_standby(&stream->common);
4475 free(stream);
4476
4477 return;
4478}
4479
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004480static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004481{
4482 return 0;
4483}
4484
Andy Hung31aca912014-03-20 17:14:59 -07004485/* verifies input and output devices and their capabilities.
4486 *
4487 * This verification is required when enabling extended bit-depth or
4488 * sampling rates, as not all qcom products support it.
4489 *
4490 * Suitable for calling only on initialization such as adev_open().
4491 * It fills the audio_device use_case_table[] array.
4492 *
4493 * Has a side-effect that it needs to configure audio routing / devices
4494 * in order to power up the devices and read the device parameters.
4495 * It does not acquire any hw device lock. Should restore the devices
4496 * back to "normal state" upon completion.
4497 */
4498static int adev_verify_devices(struct audio_device *adev)
4499{
4500 /* enumeration is a bit difficult because one really wants to pull
4501 * the use_case, device id, etc from the hidden pcm_device_table[].
4502 * In this case there are the following use cases and device ids.
4503 *
4504 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
4505 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004506 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07004507 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
4508 * [USECASE_AUDIO_RECORD] = {0, 0},
4509 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
4510 * [USECASE_VOICE_CALL] = {2, 2},
4511 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004512 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07004513 * USECASE_VOICE_CALL omitted, but possible for either input or output.
4514 */
4515
4516 /* should be the usecases enabled in adev_open_input_stream() */
4517 static const int test_in_usecases[] = {
4518 USECASE_AUDIO_RECORD,
4519 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
4520 };
4521 /* should be the usecases enabled in adev_open_output_stream()*/
4522 static const int test_out_usecases[] = {
4523 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
4524 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
4525 };
4526 static const usecase_type_t usecase_type_by_dir[] = {
4527 PCM_PLAYBACK,
4528 PCM_CAPTURE,
4529 };
4530 static const unsigned flags_by_dir[] = {
4531 PCM_OUT,
4532 PCM_IN,
4533 };
4534
4535 size_t i;
4536 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004537 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07004538 char info[512]; /* for possible debug info */
4539
4540 for (dir = 0; dir < 2; ++dir) {
4541 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
4542 const unsigned flags_dir = flags_by_dir[dir];
4543 const size_t testsize =
4544 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
4545 const int *testcases =
4546 dir ? test_in_usecases : test_out_usecases;
4547 const audio_devices_t audio_device =
4548 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
4549
4550 for (i = 0; i < testsize; ++i) {
4551 const audio_usecase_t audio_usecase = testcases[i];
4552 int device_id;
4553 snd_device_t snd_device;
4554 struct pcm_params **pparams;
4555 struct stream_out out;
4556 struct stream_in in;
4557 struct audio_usecase uc_info;
4558 int retval;
4559
4560 pparams = &adev->use_case_table[audio_usecase];
4561 pcm_params_free(*pparams); /* can accept null input */
4562 *pparams = NULL;
4563
4564 /* find the device ID for the use case (signed, for error) */
4565 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
4566 if (device_id < 0)
4567 continue;
4568
4569 /* prepare structures for device probing */
4570 memset(&uc_info, 0, sizeof(uc_info));
4571 uc_info.id = audio_usecase;
4572 uc_info.type = usecase_type;
4573 if (dir) {
4574 adev->active_input = &in;
4575 memset(&in, 0, sizeof(in));
4576 in.device = audio_device;
4577 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4578 uc_info.stream.in = &in;
4579 } else {
4580 adev->active_input = NULL;
4581 }
4582 memset(&out, 0, sizeof(out));
4583 out.devices = audio_device; /* only field needed in select_devices */
4584 uc_info.stream.out = &out;
4585 uc_info.devices = audio_device;
4586 uc_info.in_snd_device = SND_DEVICE_NONE;
4587 uc_info.out_snd_device = SND_DEVICE_NONE;
4588 list_add_tail(&adev->usecase_list, &uc_info.list);
4589
4590 /* select device - similar to start_(in/out)put_stream() */
4591 retval = select_devices(adev, audio_usecase);
4592 if (retval >= 0) {
4593 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4594#if LOG_NDEBUG == 0
4595 if (*pparams) {
4596 ALOGV("%s: (%s) card %d device %d", __func__,
4597 dir ? "input" : "output", card_id, device_id);
4598 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004599 } else {
4600 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4601 }
4602#endif
4603 }
4604
4605 /* deselect device - similar to stop_(in/out)put_stream() */
4606 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004607 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004608 /* 2. Disable the rx device */
4609 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004610 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004611 list_remove(&uc_info.list);
4612 }
4613 }
4614 adev->active_input = NULL; /* restore adev state */
4615 return 0;
4616}
4617
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004618static int adev_close(hw_device_t *device)
4619{
Andy Hung31aca912014-03-20 17:14:59 -07004620 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004621 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004622
4623 if (!adev)
4624 return 0;
4625
4626 pthread_mutex_lock(&adev_init_lock);
4627
4628 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004629 audio_extn_snd_mon_unregister_listener(adev);
4630 audio_extn_tfa_98xx_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004631 audio_route_free(adev->audio_route);
4632 free(adev->snd_dev_ref_cnt);
4633 platform_deinit(adev->platform);
4634 audio_extn_extspk_deinit(adev->extspk);
4635 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004636 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004637 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4638 pcm_params_free(adev->use_case_table[i]);
4639 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004640 if (adev->adm_deinit)
4641 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004642 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004643 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004644
4645 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004646
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004647 return 0;
4648}
4649
Glenn Kasten4f993392014-05-14 07:30:48 -07004650/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4651 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4652 * just that it _might_ work.
4653 */
4654static int period_size_is_plausible_for_low_latency(int period_size)
4655{
4656 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004657 case 48:
4658 case 96:
4659 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004660 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004661 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004662 case 240:
4663 case 320:
4664 case 480:
4665 return 1;
4666 default:
4667 return 0;
4668 }
4669}
4670
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004671static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4672{
4673 int card;
4674 card_status_t status;
4675
4676 if (!parms)
4677 return;
4678
4679 if (parse_snd_card_status(parms, &card, &status) < 0)
4680 return;
4681
4682 pthread_mutex_lock(&adev->lock);
4683 bool valid_cb = (card == adev->snd_card);
4684 if (valid_cb) {
4685 if (adev->card_status != status) {
4686 adev->card_status = status;
4687 platform_snd_card_update(adev->platform, status);
4688 }
4689 }
4690 pthread_mutex_unlock(&adev->lock);
4691 return;
4692}
4693
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004694static int adev_open(const hw_module_t *module, const char *name,
4695 hw_device_t **device)
4696{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004697 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004698
Eric Laurent2bafff12016-03-17 12:17:23 -07004699 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004700 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004701 pthread_mutex_lock(&adev_init_lock);
4702 if (audio_device_ref_count != 0) {
4703 *device = &adev->device.common;
4704 audio_device_ref_count++;
4705 ALOGV("%s: returning existing instance of adev", __func__);
4706 ALOGV("%s: exit", __func__);
4707 pthread_mutex_unlock(&adev_init_lock);
4708 return 0;
4709 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004710 adev = calloc(1, sizeof(struct audio_device));
4711
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004712 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4713
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004714 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4715 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4716 adev->device.common.module = (struct hw_module_t *)module;
4717 adev->device.common.close = adev_close;
4718
4719 adev->device.init_check = adev_init_check;
4720 adev->device.set_voice_volume = adev_set_voice_volume;
4721 adev->device.set_master_volume = adev_set_master_volume;
4722 adev->device.get_master_volume = adev_get_master_volume;
4723 adev->device.set_master_mute = adev_set_master_mute;
4724 adev->device.get_master_mute = adev_get_master_mute;
4725 adev->device.set_mode = adev_set_mode;
4726 adev->device.set_mic_mute = adev_set_mic_mute;
4727 adev->device.get_mic_mute = adev_get_mic_mute;
4728 adev->device.set_parameters = adev_set_parameters;
4729 adev->device.get_parameters = adev_get_parameters;
4730 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4731 adev->device.open_output_stream = adev_open_output_stream;
4732 adev->device.close_output_stream = adev_close_output_stream;
4733 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004734
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004735 adev->device.close_input_stream = adev_close_input_stream;
4736 adev->device.dump = adev_dump;
4737
4738 /* Set the default route before the PCM stream is opened */
4739 pthread_mutex_lock(&adev->lock);
4740 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004741 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004742 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004743 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004744 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004745 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004746 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004747 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004748 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004749 pthread_mutex_unlock(&adev->lock);
4750
4751 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004752 adev->platform = platform_init(adev);
4753 if (!adev->platform) {
4754 free(adev->snd_dev_ref_cnt);
4755 free(adev);
4756 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4757 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004758 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004759 return -EINVAL;
4760 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05004761 adev->extspk = audio_extn_extspk_init(adev);
4762
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004763 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4764 if (adev->visualizer_lib == NULL) {
4765 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4766 } else {
4767 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4768 adev->visualizer_start_output =
4769 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4770 "visualizer_hal_start_output");
4771 adev->visualizer_stop_output =
4772 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4773 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07004774 }
4775
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004776 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4777 if (adev->offload_effects_lib == NULL) {
4778 ALOGW("%s: DLOPEN failed for %s", __func__,
4779 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4780 } else {
4781 ALOGV("%s: DLOPEN successful for %s", __func__,
4782 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4783 adev->offload_effects_start_output =
4784 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4785 "offload_effects_bundle_hal_start_output");
4786 adev->offload_effects_stop_output =
4787 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4788 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07004789 }
4790
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004791 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4792 if (adev->adm_lib == NULL) {
4793 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4794 } else {
4795 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4796 adev->adm_init = (adm_init_t)
4797 dlsym(adev->adm_lib, "adm_init");
4798 adev->adm_deinit = (adm_deinit_t)
4799 dlsym(adev->adm_lib, "adm_deinit");
4800 adev->adm_register_input_stream = (adm_register_input_stream_t)
4801 dlsym(adev->adm_lib, "adm_register_input_stream");
4802 adev->adm_register_output_stream = (adm_register_output_stream_t)
4803 dlsym(adev->adm_lib, "adm_register_output_stream");
4804 adev->adm_deregister_stream = (adm_deregister_stream_t)
4805 dlsym(adev->adm_lib, "adm_deregister_stream");
4806 adev->adm_request_focus = (adm_request_focus_t)
4807 dlsym(adev->adm_lib, "adm_request_focus");
4808 adev->adm_abandon_focus = (adm_abandon_focus_t)
4809 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08004810 adev->adm_set_config = (adm_set_config_t)
4811 dlsym(adev->adm_lib, "adm_set_config");
4812 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4813 dlsym(adev->adm_lib, "adm_request_focus_v2");
4814 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4815 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4816 adev->adm_on_routing_change = (adm_on_routing_change_t)
4817 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004818 }
4819
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004820 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004821 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004822
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004823 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004824
Andy Hung31aca912014-03-20 17:14:59 -07004825 if (k_enable_extended_precision)
4826 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004827
Glenn Kasten4f993392014-05-14 07:30:48 -07004828 char value[PROPERTY_VALUE_MAX];
4829 int trial;
4830 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4831 trial = atoi(value);
4832 if (period_size_is_plausible_for_low_latency(trial)) {
4833 pcm_config_low_latency.period_size = trial;
4834 pcm_config_low_latency.start_threshold = trial / 4;
4835 pcm_config_low_latency.avail_min = trial / 4;
4836 configured_low_latency_capture_period_size = trial;
4837 }
4838 }
4839 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4840 trial = atoi(value);
4841 if (period_size_is_plausible_for_low_latency(trial)) {
4842 configured_low_latency_capture_period_size = trial;
4843 }
4844 }
4845
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004846 // commented as full set of app type cfg is sent from platform
4847 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004848 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004849
4850 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4851 af_period_multiplier = atoi(value);
4852 if (af_period_multiplier < 0) {
4853 af_period_multiplier = 2;
4854 } else if (af_period_multiplier > 4) {
4855 af_period_multiplier = 4;
4856 }
4857 ALOGV("new period_multiplier = %d", af_period_multiplier);
4858 }
4859
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004860 audio_extn_tfa_98xx_init(adev);
4861
vivek mehta1a9b7c02015-06-25 11:49:38 -07004862 pthread_mutex_unlock(&adev_init_lock);
4863
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004864 if (adev->adm_init)
4865 adev->adm_data = adev->adm_init();
4866
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004867 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004868 audio_extn_snd_mon_init();
4869 pthread_mutex_lock(&adev->lock);
4870 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
4871 adev->card_status = CARD_STATUS_ONLINE;
4872 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004873 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004874
Eric Laurent2bafff12016-03-17 12:17:23 -07004875 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004876 return 0;
4877}
4878
4879static struct hw_module_methods_t hal_module_methods = {
4880 .open = adev_open,
4881};
4882
4883struct audio_module HAL_MODULE_INFO_SYM = {
4884 .common = {
4885 .tag = HARDWARE_MODULE_TAG,
4886 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4887 .hal_api_version = HARDWARE_HAL_API_VERSION,
4888 .id = AUDIO_HARDWARE_MODULE_ID,
4889 .name = "QCOM Audio HAL",
4890 .author = "Code Aurora Forum",
4891 .methods = &hal_module_methods,
4892 },
4893};