blob: 7f91a240eed705d139756a9966e06a739fa184c0 [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);
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07001804 else if (out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
1805 struct listnode *node;
1806 struct audio_usecase *usecase;
1807 list_for_each(node, &adev->usecase_list) {
1808 usecase = node_to_item(node, struct audio_usecase, list);
1809 if (usecase->devices & AUDIO_DEVICE_OUT_SPEAKER)
1810 select_devices(adev, usecase->id);
1811 }
1812 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001813
Eric Laurent994a6932013-07-17 11:51:42 -07001814 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001815 return ret;
1816}
1817
1818int start_output_stream(struct stream_out *out)
1819{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001820 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001821 struct audio_usecase *uc_info;
1822 struct audio_device *adev = out->dev;
1823
Eric Laurent994a6932013-07-17 11:51:42 -07001824 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001825 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001826
1827 if (out->card_status == CARD_STATUS_OFFLINE ||
1828 adev->card_status == CARD_STATUS_OFFLINE) {
1829 ALOGW("out->card_status or adev->card_status offline, try again");
1830 ret = -EAGAIN;
1831 goto error_config;
1832 }
1833
Eric Laurentb23d5282013-05-14 15:27:20 -07001834 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001835 if (out->pcm_device_id < 0) {
1836 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1837 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001838 ret = -EINVAL;
1839 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001840 }
1841
1842 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1843 uc_info->id = out->usecase;
1844 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001845 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001846 uc_info->devices = out->devices;
1847 uc_info->in_snd_device = SND_DEVICE_NONE;
1848 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001849
Eric Laurent07eeafd2013-10-06 12:52:49 -07001850 /* This must be called before adding this usecase to the list */
1851 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1852 check_and_set_hdmi_channels(adev, out->config.channels);
1853
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001854 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001855
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001856 audio_extn_perf_lock_acquire();
1857
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001858 select_devices(adev, out->usecase);
1859
Eric Laurent0499d4f2014-08-25 22:39:29 -05001860 audio_extn_extspk_update(adev->extspk);
1861
Andy Hung31aca912014-03-20 17:14:59 -07001862 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001863 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001864 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1865 out->pcm = NULL;
1866 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1867 COMPRESS_IN, &out->compr_config);
1868 if (out->compr && !is_compress_ready(out->compr)) {
1869 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1870 compress_close(out->compr);
1871 out->compr = NULL;
1872 ret = -EIO;
1873 goto error_open;
1874 }
1875 if (out->offload_callback)
1876 compress_nonblock(out->compr, out->non_blocking);
1877
1878 if (adev->visualizer_start_output != NULL)
1879 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1880 if (adev->offload_effects_start_output != NULL)
1881 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
1882 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001883 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001884 ALOGE("%s: pcm stream not ready", __func__);
1885 goto error_open;
1886 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001887 ret = pcm_start(out->pcm);
1888 if (ret < 0) {
1889 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1890 goto error_open;
1891 }
1892 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07001893 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001894 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001895
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001896 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1897 flags |= PCM_MMAP | PCM_NOIRQ;
1898 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001899 } else if (out->realtime) {
1900 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07001901 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001902
1903 while (1) {
1904 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1905 flags, &out->config);
1906 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1907 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1908 if (out->pcm != NULL) {
1909 pcm_close(out->pcm);
1910 out->pcm = NULL;
1911 }
1912 if (pcm_open_retry_count-- == 0) {
1913 ret = -EIO;
1914 goto error_open;
1915 }
1916 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1917 continue;
1918 }
1919 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001920 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001921 ALOGV("%s: pcm_prepare", __func__);
1922 if (pcm_is_ready(out->pcm)) {
1923 ret = pcm_prepare(out->pcm);
1924 if (ret < 0) {
1925 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1926 pcm_close(out->pcm);
1927 out->pcm = NULL;
1928 goto error_open;
1929 }
1930 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001931 if (out->realtime) {
1932 ret = pcm_start(out->pcm);
1933 if (ret < 0) {
1934 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1935 pcm_close(out->pcm);
1936 out->pcm = NULL;
1937 goto error_open;
1938 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001939 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001940 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001941 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001942 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001943 audio_extn_tfa_98xx_enable_speaker();
vivek mehta4a824772017-06-08 19:05:49 -07001944 audio_extn_utils_send_app_type_gain(out->dev,
1945 out->app_type_cfg.app_type,
1946 &out->app_type_cfg.gain[0]);
vivek mehtae59cfb22017-06-16 15:57:11 -07001947
1948 // consider a scenario where on pause lower layers are tear down.
1949 // so on resume, swap mixer control need to be sent only when
1950 // backend is active, hence rather than sending from enable device
1951 // sending it from start of streamtream
1952
1953 platform_set_swap_channels(adev, true);
1954
Eric Laurent994a6932013-07-17 11:51:42 -07001955 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001956 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001957error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001958 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001959 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001960error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001961 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001962}
1963
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001964static int check_input_parameters(uint32_t sample_rate,
1965 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07001966 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001967{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001968 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
1969 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07001970 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
1971 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07001972 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1973 return -EINVAL;
1974 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001975
Eric Laurent74b55762017-07-09 17:04:53 -07001976 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
1977 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001978 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07001979 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07001980 return -EINVAL;
1981 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001982
1983 switch (sample_rate) {
1984 case 8000:
1985 case 11025:
1986 case 12000:
1987 case 16000:
1988 case 22050:
1989 case 24000:
1990 case 32000:
1991 case 44100:
1992 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001993 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001994 break;
1995 default:
vivek mehtadae44712015-07-27 14:13:18 -07001996 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001997 return -EINVAL;
1998 }
1999
2000 return 0;
2001}
2002
vivek mehtaa68fea62017-06-08 19:04:02 -07002003static size_t get_stream_buffer_size(size_t duration_ms,
2004 uint32_t sample_rate,
2005 audio_format_t format,
2006 int channel_count,
2007 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002008{
2009 size_t size = 0;
2010
vivek mehtaa68fea62017-06-08 19:04:02 -07002011 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002012 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002013 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002014
2015 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002016
Glenn Kasten4f993392014-05-14 07:30:48 -07002017 /* make sure the size is multiple of 32 bytes
2018 * At 48 kHz mono 16-bit PCM:
2019 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2020 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2021 */
2022 size += 0x1f;
2023 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002024
2025 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002026}
2027
2028static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2029{
2030 struct stream_out *out = (struct stream_out *)stream;
2031
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002032 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002033}
2034
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002035static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002036{
2037 return -ENOSYS;
2038}
2039
2040static size_t out_get_buffer_size(const struct audio_stream *stream)
2041{
2042 struct stream_out *out = (struct stream_out *)stream;
2043
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002044 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2045 return out->compr_config.fragment_size;
2046 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002047 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002048 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002049}
2050
2051static uint32_t out_get_channels(const struct audio_stream *stream)
2052{
2053 struct stream_out *out = (struct stream_out *)stream;
2054
2055 return out->channel_mask;
2056}
2057
2058static audio_format_t out_get_format(const struct audio_stream *stream)
2059{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002060 struct stream_out *out = (struct stream_out *)stream;
2061
2062 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002063}
2064
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002065static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002066{
2067 return -ENOSYS;
2068}
2069
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002070/* must be called with out->lock locked */
2071static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002072{
2073 struct stream_out *out = (struct stream_out *)stream;
2074 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002075 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002076
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002077 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002078 if (adev->adm_deregister_stream)
2079 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002080 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002081 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002082 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2083 if (out->pcm) {
2084 pcm_close(out->pcm);
2085 out->pcm = NULL;
2086 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002087 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002088 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002089 out->playback_started = false;
2090 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002091 } else {
2092 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002093 out->gapless_mdata.encoder_delay = 0;
2094 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002095 if (out->compr != NULL) {
2096 compress_close(out->compr);
2097 out->compr = NULL;
2098 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002099 }
Phil Burkbc991042017-02-24 08:06:44 -08002100 if (do_stop) {
2101 stop_output_stream(out);
2102 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002103 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002104 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002105 return 0;
2106}
2107
2108static int out_standby(struct audio_stream *stream)
2109{
2110 struct stream_out *out = (struct stream_out *)stream;
2111
2112 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2113 out->usecase, use_case_table[out->usecase]);
2114
2115 lock_output_stream(out);
2116 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002117 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002118 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002119 return 0;
2120}
2121
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002122static int out_on_error(struct audio_stream *stream)
2123{
2124 struct stream_out *out = (struct stream_out *)stream;
2125 struct audio_device *adev = out->dev;
2126 bool do_standby = false;
2127
2128 lock_output_stream(out);
2129 if (!out->standby) {
2130 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2131 stop_compressed_output_l(out);
2132 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2133 } else
2134 do_standby = true;
2135 }
2136 pthread_mutex_unlock(&out->lock);
2137
2138 if (do_standby)
2139 return out_standby(&out->stream.common);
2140
2141 return 0;
2142}
2143
Andy Hung7401c7c2016-09-21 12:41:21 -07002144static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002145{
Andy Hung7401c7c2016-09-21 12:41:21 -07002146 struct stream_out *out = (struct stream_out *)stream;
2147
2148 // We try to get the lock for consistency,
2149 // but it isn't necessary for these variables.
2150 // If we're not in standby, we may be blocked on a write.
2151 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2152 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2153 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2154
2155 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002156 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002157 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002158
2159 // dump error info
2160 (void)error_log_dump(
2161 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hungfc044e12017-03-20 09:24:22 -07002162 // dump power info (out->power_log may be null)
Andy Hung62c9b882017-03-22 16:43:42 -07002163 (void)power_log_dump(
2164 out->power_log, fd, " " /* prefix */, POWER_LOG_LINES, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002165 return 0;
2166}
2167
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002168static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2169{
2170 int ret = 0;
2171 char value[32];
2172 struct compr_gapless_mdata tmp_mdata;
2173
2174 if (!out || !parms) {
2175 return -EINVAL;
2176 }
2177
2178 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2179 if (ret >= 0) {
2180 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2181 } else {
2182 return -EINVAL;
2183 }
2184
2185 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2186 if (ret >= 0) {
2187 tmp_mdata.encoder_padding = atoi(value);
2188 } else {
2189 return -EINVAL;
2190 }
2191
2192 out->gapless_mdata = tmp_mdata;
2193 out->send_new_metadata = 1;
2194 ALOGV("%s new encoder delay %u and padding %u", __func__,
2195 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2196
2197 return 0;
2198}
2199
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002200static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2201{
2202 return out == adev->primary_output || out == adev->voice_tx_output;
2203}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002204
Kevin Rocard1e02c882017-08-09 15:26:07 -07002205static int get_alive_usb_card(struct str_parms* parms) {
2206 int card;
2207 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2208 !audio_extn_usb_alive(card)) {
2209 return card;
2210 }
2211 return -ENODEV;
2212}
2213
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002214static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2215{
2216 struct stream_out *out = (struct stream_out *)stream;
2217 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002218 struct audio_usecase *usecase;
2219 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002220 struct str_parms *parms;
2221 char value[32];
2222 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002223 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002224 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002225
Eric Laurent2e140aa2016-06-30 17:14:46 -07002226 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002227 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002228 parms = str_parms_create_str(kvpairs);
2229 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2230 if (ret >= 0) {
2231 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002232
Eric Laurenta1478072015-09-21 17:21:52 -07002233 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002234
2235 // The usb driver needs to be closed after usb device disconnection
2236 // otherwise audio is no longer played on the new usb devices.
2237 // By forcing the stream in standby, the usb stack refcount drops to 0
2238 // and the driver is closed.
2239 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD && val == AUDIO_DEVICE_NONE &&
2240 audio_is_usb_out_device(out->devices)) {
2241 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2242 out_standby_l(&out->stream.common);
2243 }
2244
Eric Laurent150dbfe2013-02-27 14:31:02 -08002245 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002246
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002247 /*
2248 * When HDMI cable is unplugged the music playback is paused and
2249 * the policy manager sends routing=0. But the audioflinger
2250 * continues to write data until standby time (3sec).
2251 * As the HDMI core is turned off, the write gets blocked.
2252 * Avoid this by routing audio to speaker until standby.
2253 */
2254 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2255 val == AUDIO_DEVICE_NONE) {
2256 val = AUDIO_DEVICE_OUT_SPEAKER;
2257 }
2258
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002259 audio_devices_t new_dev = val;
2260
2261 // Workaround: If routing to an non existing usb device, fail gracefully
2262 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002263 int card;
2264 if (audio_is_usb_out_device(new_dev) &&
2265 (card = get_alive_usb_card(parms)) >= 0) {
2266
2267 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002268 pthread_mutex_unlock(&adev->lock);
2269 pthread_mutex_unlock(&out->lock);
2270 status = -ENOSYS;
2271 goto routing_fail;
2272 }
2273
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002274 /*
2275 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002276 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002277 * the select_devices(). But how do we undo this?
2278 *
2279 * For example, music playback is active on headset (deep-buffer usecase)
2280 * and if we go to ringtones and select a ringtone, low-latency usecase
2281 * will be started on headset+speaker. As we can't enable headset+speaker
2282 * and headset devices at the same time, select_devices() switches the music
2283 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2284 * So when the ringtone playback is completed, how do we undo the same?
2285 *
2286 * We are relying on the out_set_parameters() call on deep-buffer output,
2287 * once the ringtone playback is ended.
2288 * NOTE: We should not check if the current devices are same as new devices.
2289 * Because select_devices() must be called to switch back the music
2290 * playback to headset.
2291 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002292 if (new_dev != AUDIO_DEVICE_NONE) {
2293 bool same_dev = out->devices == new_dev;
2294 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002295
Eric Laurenta7657192014-10-09 21:09:33 -07002296 if (output_drives_call(adev, out)) {
2297 if (!voice_is_in_call(adev)) {
2298 if (adev->mode == AUDIO_MODE_IN_CALL) {
2299 adev->current_call_output = out;
2300 ret = voice_start_call(adev);
2301 }
2302 } else {
2303 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002304 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002305 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002306 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002307
2308 if (!out->standby) {
2309 if (!same_dev) {
2310 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002311 // inform adm before actual routing to prevent glitches.
2312 if (adev->adm_on_routing_change) {
2313 adev->adm_on_routing_change(adev->adm_data,
2314 out->handle);
2315 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002316 }
2317 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002318 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002319
2320 // on device switch force swap, lower functions will make sure
2321 // to check if swap is allowed or not.
2322
2323 if (!same_dev)
2324 platform_set_swap_channels(adev, true);
vivek mehta0d3637a2016-07-24 09:32:02 -07002325 }
2326
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002327 }
2328
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002329 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002330 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002331
2332 /*handles device and call state changes*/
2333 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002334 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002335 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002336
2337 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2338 parse_compress_metadata(out, parms);
2339 }
2340
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002341 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002342 ALOGV("%s: exit: code(%d)", __func__, status);
2343 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002344}
2345
Haynes Mathew George569b7482017-05-08 14:44:27 -07002346static bool stream_get_parameter_channels(struct str_parms *query,
2347 struct str_parms *reply,
2348 audio_channel_mask_t *supported_channel_masks) {
2349 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002350 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002351 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002352 size_t i, j;
2353
2354 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2355 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002356 value[0] = '\0';
2357 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002358 while (supported_channel_masks[i] != 0) {
2359 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2360 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002361 if (!first) {
2362 strcat(value, "|");
2363 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002364 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002365 first = false;
2366 break;
2367 }
2368 }
2369 i++;
2370 }
2371 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002372 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002373 return ret >= 0;
2374}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002375
Haynes Mathew George569b7482017-05-08 14:44:27 -07002376static bool stream_get_parameter_formats(struct str_parms *query,
2377 struct str_parms *reply,
2378 audio_format_t *supported_formats) {
2379 int ret = -1;
2380 char value[256];
2381 int i;
2382
2383 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2384 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002385 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002386 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002387 case AUDIO_FORMAT_PCM_16_BIT:
2388 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2389 break;
2390 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2391 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2392 break;
2393 case AUDIO_FORMAT_PCM_32_BIT:
2394 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2395 break;
2396 default:
2397 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002398 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002399 break;
2400 }
2401 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002402 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002403 return ret >= 0;
2404}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002405
Haynes Mathew George569b7482017-05-08 14:44:27 -07002406static bool stream_get_parameter_rates(struct str_parms *query,
2407 struct str_parms *reply,
2408 uint32_t *supported_sample_rates) {
2409
2410 int i;
2411 char value[256];
2412 int ret = -1;
2413 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2414 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002415 value[0] = '\0';
2416 i=0;
2417 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002418 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002419 int avail = sizeof(value) - cursor;
2420 ret = snprintf(value + cursor, avail, "%s%d",
2421 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002422 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002423 if (ret < 0 || ret >= avail) {
2424 // if cursor is at the last element of the array
2425 // overwrite with \0 is duplicate work as
2426 // snprintf already put a \0 in place.
2427 // else
2428 // we had space to write the '|' at value[cursor]
2429 // (which will be overwritten) or no space to fill
2430 // the first element (=> cursor == 0)
2431 value[cursor] = '\0';
2432 break;
2433 }
2434 cursor += ret;
2435 ++i;
2436 }
2437 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2438 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002439 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002440 return ret >= 0;
2441}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002442
Haynes Mathew George569b7482017-05-08 14:44:27 -07002443static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2444{
2445 struct stream_out *out = (struct stream_out *)stream;
2446 struct str_parms *query = str_parms_create_str(keys);
2447 char *str;
2448 struct str_parms *reply = str_parms_create();
2449 bool replied = false;
2450 ALOGV("%s: enter: keys - %s", __func__, keys);
2451
2452 replied |= stream_get_parameter_channels(query, reply,
2453 &out->supported_channel_masks[0]);
2454 replied |= stream_get_parameter_formats(query, reply,
2455 &out->supported_formats[0]);
2456 replied |= stream_get_parameter_rates(query, reply,
2457 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002458 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002459 str = str_parms_to_str(reply);
2460 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002461 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002462 }
2463 str_parms_destroy(query);
2464 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002465 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002466 return str;
2467}
2468
2469static uint32_t out_get_latency(const struct audio_stream_out *stream)
2470{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002471 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002472 struct stream_out *out = (struct stream_out *)stream;
2473
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002474 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2475 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002476 else if ((out->realtime) ||
2477 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002478 // since the buffer won't be filled up faster than realtime,
2479 // return a smaller number
2480 period_ms = (out->af_period_multiplier * out->config.period_size *
2481 1000) / (out->config.rate);
2482 hw_delay = platform_render_latency(out->usecase)/1000;
2483 return period_ms + hw_delay;
2484 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002485
2486 return (out->config.period_count * out->config.period_size * 1000) /
2487 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002488}
2489
2490static int out_set_volume(struct audio_stream_out *stream, float left,
2491 float right)
2492{
Eric Laurenta9024de2013-04-04 09:19:12 -07002493 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002494 int volume[2];
2495
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002496 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002497 /* only take left channel into account: the API is for stereo anyway */
2498 out->muted = (left == 0.0f);
2499 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002500 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2501 const char *mixer_ctl_name = "Compress Playback Volume";
2502 struct audio_device *adev = out->dev;
2503 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002504 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2505 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002506 /* try with the control based on device id */
2507 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2508 PCM_PLAYBACK);
2509 char ctl_name[128] = {0};
2510 snprintf(ctl_name, sizeof(ctl_name),
2511 "Compress Playback %d Volume", pcm_device_id);
2512 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2513 if (!ctl) {
2514 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2515 return -EINVAL;
2516 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002517 }
2518 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2519 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2520 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2521 return 0;
vivek mehtaa68fea62017-06-08 19:04:02 -07002522 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002523 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2524 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2525 if (!out->standby) {
2526 // if in standby, cached volume will be sent after stream is opened
2527 audio_extn_utils_send_app_type_gain(out->dev,
2528 out->app_type_cfg.app_type,
2529 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002530 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002531 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002532 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002533
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002534 return -ENOSYS;
2535}
2536
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002537// note: this call is safe only if the stream_cb is
2538// removed first in close_output_stream (as is done now).
2539static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2540{
2541 if (!stream || !parms)
2542 return;
2543
2544 struct stream_out *out = (struct stream_out *)stream;
2545 struct audio_device *adev = out->dev;
2546
2547 card_status_t status;
2548 int card;
2549 if (parse_snd_card_status(parms, &card, &status) < 0)
2550 return;
2551
2552 pthread_mutex_lock(&adev->lock);
2553 bool valid_cb = (card == adev->snd_card);
2554 pthread_mutex_unlock(&adev->lock);
2555
2556 if (!valid_cb)
2557 return;
2558
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002559 lock_output_stream(out);
2560 if (out->card_status != status)
2561 out->card_status = status;
2562 pthread_mutex_unlock(&out->lock);
2563
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002564 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2565 use_case_table[out->usecase],
2566 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2567
2568 if (status == CARD_STATUS_OFFLINE)
2569 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002570
2571 return;
2572}
2573
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002574#ifdef NO_AUDIO_OUT
2575static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002576 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002577{
2578 struct stream_out *out = (struct stream_out *)stream;
2579
2580 /* No Output device supported other than BT for playback.
2581 * Sleep for the amount of buffer duration
2582 */
Eric Laurenta1478072015-09-21 17:21:52 -07002583 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002584 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2585 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002586 out_get_sample_rate(&out->stream.common));
2587 pthread_mutex_unlock(&out->lock);
2588 return bytes;
2589}
2590#endif
2591
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002592static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2593 size_t bytes)
2594{
2595 struct stream_out *out = (struct stream_out *)stream;
2596 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002597 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002598 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002599
Eric Laurenta1478072015-09-21 17:21:52 -07002600 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002601 // this is always nonzero
Andy Hung928efbe2017-06-12 14:05:22 -07002602 const size_t frame_size = audio_stream_out_frame_size(stream);
2603 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002604
Eric Laurent0e46adf2016-12-16 12:49:24 -08002605 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2606 error_code = ERROR_CODE_WRITE;
2607 goto exit;
2608 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002609 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002610 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002611 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002612 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002613 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002614 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002615 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002616 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002617 goto exit;
2618 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002619
2620 if (last_known_cal_step != -1) {
2621 ALOGD("%s: retry previous failed cal level set", __func__);
2622 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2623 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002624 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002625
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002626 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002627 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002628 if (out->send_new_metadata) {
2629 ALOGVV("send new gapless metadata");
2630 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2631 out->send_new_metadata = 0;
2632 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002633 unsigned int avail;
2634 struct timespec tstamp;
2635 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2636 /* Do not limit write size if the available frames count is unknown */
2637 if (ret != 0) {
2638 avail = bytes;
2639 }
2640 if (avail == 0) {
2641 ret = 0;
2642 } else {
2643 if (avail > bytes) {
2644 avail = bytes;
2645 }
2646 ret = compress_write(out->compr, buffer, avail);
2647 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2648 __func__, avail, ret);
2649 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002650
Eric Laurent6e895242013-09-05 16:10:57 -07002651 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002652 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2653 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002654 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002655 compress_start(out->compr);
2656 out->playback_started = 1;
2657 out->offload_state = OFFLOAD_STATE_PLAYING;
2658 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002659 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002660 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002661 } else {
2662 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002663 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002664 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002665 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002666 return ret;
2667 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002668 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002669 if (out->pcm) {
2670 if (out->muted)
2671 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002672
Eric Laurent0e46adf2016-12-16 12:49:24 -08002673 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002674
Haynes Mathew George03c40102016-01-29 17:57:48 -08002675 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2676 out->config.rate;
2677 request_out_focus(out, ns);
2678
2679 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2680 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002681 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002682 else
2683 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002684
Haynes Mathew George03c40102016-01-29 17:57:48 -08002685 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002686 } else {
2687 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002688 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002689 }
2690
2691exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002692 // For PCM we always consume the buffer and return #bytes regardless of ret.
2693 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung928efbe2017-06-12 14:05:22 -07002694 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07002695 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002696 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07002697
2698 // only get time if needed for logging, as it is a system call on 32 bit devices.
2699 // TODO: Consider always enabling for 64 bit vDSO using compile time check on __LP64__.
2700 const int64_t now_ns = out->power_log != 0 || (ret != 0 && out->error_log != 0)
2701 ? audio_utils_get_real_time_ns() : 0;
Andy Hungfc044e12017-03-20 09:24:22 -07002702
Andy Hung7401c7c2016-09-21 12:41:21 -07002703 if (ret != 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002704 error_log_log(out->error_log, error_code, now_ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002705 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2706 ALOGE_IF(out->pcm != NULL,
2707 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung928efbe2017-06-12 14:05:22 -07002708 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002709 // usleep not guaranteed for values over 1 second but we don't limit here.
2710 }
2711 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002712
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002713 pthread_mutex_unlock(&out->lock);
2714
2715 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002716 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002717 if (sleeptime_us != 0)
2718 usleep(sleeptime_us);
Andy Hungfc044e12017-03-20 09:24:22 -07002719 } else {
2720 // only log if the data is properly written (out->power_log may be null)
Andy Hung928efbe2017-06-12 14:05:22 -07002721 power_log_log(out->power_log, buffer, frames, now_ns);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002722 }
2723 return bytes;
2724}
2725
2726static int out_get_render_position(const struct audio_stream_out *stream,
2727 uint32_t *dsp_frames)
2728{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002729 struct stream_out *out = (struct stream_out *)stream;
2730 *dsp_frames = 0;
2731 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002732 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002733 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002734 unsigned long frames = 0;
2735 // TODO: check return value
2736 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2737 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002738 ALOGVV("%s rendered frames %d sample_rate %d",
2739 __func__, *dsp_frames, out->sample_rate);
2740 }
2741 pthread_mutex_unlock(&out->lock);
2742 return 0;
2743 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002744 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002745}
2746
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002747static int out_add_audio_effect(const struct audio_stream *stream __unused,
2748 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002749{
2750 return 0;
2751}
2752
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002753static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2754 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002755{
2756 return 0;
2757}
2758
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002759static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2760 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002761{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002762 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002763}
2764
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002765static int out_get_presentation_position(const struct audio_stream_out *stream,
2766 uint64_t *frames, struct timespec *timestamp)
2767{
2768 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002769 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07002770 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002771
Eric Laurenta1478072015-09-21 17:21:52 -07002772 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002773
Eric Laurent949a0892013-09-20 09:20:13 -07002774 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2775 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002776 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002777 compress_get_tstamp(out->compr, &dsp_frames,
2778 &out->sample_rate);
2779 ALOGVV("%s rendered frames %ld sample_rate %d",
2780 __func__, dsp_frames, out->sample_rate);
2781 *frames = dsp_frames;
2782 ret = 0;
2783 /* this is the best we can do */
2784 clock_gettime(CLOCK_MONOTONIC, timestamp);
2785 }
2786 } else {
2787 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002788 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002789 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2790 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002791 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002792 // This adjustment accounts for buffering after app processor.
2793 // It is based on estimated DSP latency per use case, rather than exact.
2794 signed_frames -=
2795 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2796
Eric Laurent949a0892013-09-20 09:20:13 -07002797 // It would be unusual for this value to be negative, but check just in case ...
2798 if (signed_frames >= 0) {
2799 *frames = signed_frames;
2800 ret = 0;
2801 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002802 }
2803 }
2804 }
2805
2806 pthread_mutex_unlock(&out->lock);
2807
2808 return ret;
2809}
2810
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002811static int out_set_callback(struct audio_stream_out *stream,
2812 stream_callback_t callback, void *cookie)
2813{
2814 struct stream_out *out = (struct stream_out *)stream;
2815
2816 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002817 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002818 out->offload_callback = callback;
2819 out->offload_cookie = cookie;
2820 pthread_mutex_unlock(&out->lock);
2821 return 0;
2822}
2823
2824static int out_pause(struct audio_stream_out* stream)
2825{
2826 struct stream_out *out = (struct stream_out *)stream;
2827 int status = -ENOSYS;
2828 ALOGV("%s", __func__);
2829 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002830 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002831 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2832 status = compress_pause(out->compr);
2833 out->offload_state = OFFLOAD_STATE_PAUSED;
2834 }
2835 pthread_mutex_unlock(&out->lock);
2836 }
2837 return status;
2838}
2839
2840static int out_resume(struct audio_stream_out* stream)
2841{
2842 struct stream_out *out = (struct stream_out *)stream;
2843 int status = -ENOSYS;
2844 ALOGV("%s", __func__);
2845 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2846 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002847 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002848 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2849 status = compress_resume(out->compr);
2850 out->offload_state = OFFLOAD_STATE_PLAYING;
2851 }
2852 pthread_mutex_unlock(&out->lock);
2853 }
2854 return status;
2855}
2856
2857static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2858{
2859 struct stream_out *out = (struct stream_out *)stream;
2860 int status = -ENOSYS;
2861 ALOGV("%s", __func__);
2862 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002863 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002864 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2865 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2866 else
2867 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2868 pthread_mutex_unlock(&out->lock);
2869 }
2870 return status;
2871}
2872
2873static int out_flush(struct audio_stream_out* stream)
2874{
2875 struct stream_out *out = (struct stream_out *)stream;
2876 ALOGV("%s", __func__);
2877 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002878 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002879 stop_compressed_output_l(out);
2880 pthread_mutex_unlock(&out->lock);
2881 return 0;
2882 }
2883 return -ENOSYS;
2884}
2885
Eric Laurent0e46adf2016-12-16 12:49:24 -08002886static int out_stop(const struct audio_stream_out* stream)
2887{
2888 struct stream_out *out = (struct stream_out *)stream;
2889 struct audio_device *adev = out->dev;
2890 int ret = -ENOSYS;
2891
2892 ALOGV("%s", __func__);
2893 pthread_mutex_lock(&adev->lock);
2894 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2895 out->playback_started && out->pcm != NULL) {
2896 pcm_stop(out->pcm);
2897 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08002898 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002899 }
2900 pthread_mutex_unlock(&adev->lock);
2901 return ret;
2902}
2903
2904static int out_start(const struct audio_stream_out* stream)
2905{
2906 struct stream_out *out = (struct stream_out *)stream;
2907 struct audio_device *adev = out->dev;
2908 int ret = -ENOSYS;
2909
2910 ALOGV("%s", __func__);
2911 pthread_mutex_lock(&adev->lock);
2912 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2913 !out->playback_started && out->pcm != NULL) {
2914 ret = start_output_stream(out);
2915 if (ret == 0) {
2916 out->playback_started = true;
2917 }
2918 }
2919 pthread_mutex_unlock(&adev->lock);
2920 return ret;
2921}
2922
Phil Burkbc991042017-02-24 08:06:44 -08002923/*
2924 * Modify config->period_count based on min_size_frames
2925 */
2926static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
2927{
2928 int periodCountRequested = (min_size_frames + config->period_size - 1)
2929 / config->period_size;
2930 int periodCount = MMAP_PERIOD_COUNT_MIN;
2931
2932 ALOGV("%s original config.period_size = %d config.period_count = %d",
2933 __func__, config->period_size, config->period_count);
2934
2935 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
2936 periodCount *= 2;
2937 }
2938 config->period_count = periodCount;
2939
2940 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
2941}
2942
Eric Laurent0e46adf2016-12-16 12:49:24 -08002943static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2944 int32_t min_size_frames,
2945 struct audio_mmap_buffer_info *info)
2946{
2947 struct stream_out *out = (struct stream_out *)stream;
2948 struct audio_device *adev = out->dev;
2949 int ret = 0;
2950 unsigned int offset1;
2951 unsigned int frames1;
2952 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07002953 uint32_t mmap_size;
2954 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002955
2956 ALOGV("%s", __func__);
2957 pthread_mutex_lock(&adev->lock);
2958
2959 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002960 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002961 ret = -EINVAL;
2962 goto exit;
2963 }
2964 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08002965 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002966 ret = -ENOSYS;
2967 goto exit;
2968 }
2969 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
2970 if (out->pcm_device_id < 0) {
2971 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2972 __func__, out->pcm_device_id, out->usecase);
2973 ret = -EINVAL;
2974 goto exit;
2975 }
Phil Burkbc991042017-02-24 08:06:44 -08002976
2977 adjust_mmap_period_count(&out->config, min_size_frames);
2978
Eric Laurent0e46adf2016-12-16 12:49:24 -08002979 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2980 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
2981 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2982 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
2983 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2984 step = "open";
2985 ret = -ENODEV;
2986 goto exit;
2987 }
2988 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
2989 if (ret < 0) {
2990 step = "begin";
2991 goto exit;
2992 }
2993 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07002994 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002995 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07002996 ret = platform_get_mmap_data_fd(adev->platform,
2997 out->pcm_device_id, 0 /*playback*/,
2998 &info->shared_memory_fd,
2999 &mmap_size);
3000 if (ret < 0) {
3001 // Fall back to non exclusive mode
3002 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3003 } else {
3004 if (mmap_size < buffer_size) {
3005 step = "mmap";
3006 goto exit;
3007 }
3008 // FIXME: indicate exclusive mode support by returning a negative buffer size
3009 info->buffer_size_frames *= -1;
3010 }
3011 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003012
3013 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3014 if (ret < 0) {
3015 step = "commit";
3016 goto exit;
3017 }
Phil Burkbc991042017-02-24 08:06:44 -08003018
3019 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003020 ret = 0;
3021
3022 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3023 __func__, info->shared_memory_address, info->buffer_size_frames);
3024
3025exit:
3026 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003027 if (out->pcm == NULL) {
3028 ALOGE("%s: %s - %d", __func__, step, ret);
3029 } else {
3030 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003031 pcm_close(out->pcm);
3032 out->pcm = NULL;
3033 }
3034 }
3035 pthread_mutex_unlock(&adev->lock);
3036 return ret;
3037}
3038
3039static int out_get_mmap_position(const struct audio_stream_out *stream,
3040 struct audio_mmap_position *position)
3041{
3042 struct stream_out *out = (struct stream_out *)stream;
3043 ALOGVV("%s", __func__);
3044 if (position == NULL) {
3045 return -EINVAL;
3046 }
3047 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
3048 return -ENOSYS;
3049 }
3050 if (out->pcm == NULL) {
3051 return -ENOSYS;
3052 }
3053
3054 struct timespec ts = { 0, 0 };
3055 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
3056 if (ret < 0) {
3057 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
3058 return ret;
3059 }
Andy Hungfc044e12017-03-20 09:24:22 -07003060 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003061 return 0;
3062}
3063
3064
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003065/** audio_stream_in implementation **/
3066static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3067{
3068 struct stream_in *in = (struct stream_in *)stream;
3069
3070 return in->config.rate;
3071}
3072
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003073static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003074{
3075 return -ENOSYS;
3076}
3077
3078static size_t in_get_buffer_size(const struct audio_stream *stream)
3079{
3080 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003081 return in->config.period_size * in->af_period_multiplier *
3082 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003083}
3084
3085static uint32_t in_get_channels(const struct audio_stream *stream)
3086{
3087 struct stream_in *in = (struct stream_in *)stream;
3088
3089 return in->channel_mask;
3090}
3091
vivek mehta4ed66e62016-04-15 23:33:34 -07003092static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003093{
vivek mehta4ed66e62016-04-15 23:33:34 -07003094 struct stream_in *in = (struct stream_in *)stream;
3095 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003096}
3097
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003098static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003099{
3100 return -ENOSYS;
3101}
3102
3103static int in_standby(struct audio_stream *stream)
3104{
3105 struct stream_in *in = (struct stream_in *)stream;
3106 struct audio_device *adev = in->dev;
3107 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003108 bool do_stop = true;
3109
Eric Laurent994a6932013-07-17 11:51:42 -07003110 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003111
3112 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003113
3114 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003115 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003116 audio_extn_sound_trigger_stop_lab(in);
3117 in->standby = true;
3118 }
3119
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003120 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003121 if (adev->adm_deregister_stream)
3122 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3123
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003124 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003125 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003126 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003127 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003128 in->capture_started = false;
3129 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003130 if (in->pcm) {
3131 pcm_close(in->pcm);
3132 in->pcm = NULL;
3133 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003134 adev->enable_voicerx = false;
3135 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003136 if (do_stop) {
3137 status = stop_input_stream(in);
3138 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003139 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003140 }
3141 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003142 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003143 return status;
3144}
3145
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003146static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003147{
3148 return 0;
3149}
3150
3151static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3152{
3153 struct stream_in *in = (struct stream_in *)stream;
3154 struct audio_device *adev = in->dev;
3155 struct str_parms *parms;
3156 char *str;
3157 char value[32];
3158 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003159 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003160
Eric Laurent994a6932013-07-17 11:51:42 -07003161 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003162 parms = str_parms_create_str(kvpairs);
3163
3164 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3165
Eric Laurenta1478072015-09-21 17:21:52 -07003166 lock_input_stream(in);
3167
Eric Laurent150dbfe2013-02-27 14:31:02 -08003168 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003169 if (ret >= 0) {
3170 val = atoi(value);
3171 /* no audio source uses val == 0 */
3172 if ((in->source != val) && (val != 0)) {
3173 in->source = val;
3174 }
3175 }
3176
3177 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003178
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003179 if (ret >= 0) {
3180 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003181 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003182
3183 // Workaround: If routing to an non existing usb device, fail gracefully
3184 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003185 int card;
3186 if (audio_is_usb_in_device(val) &&
3187 (card = get_alive_usb_card(parms)) >= 0) {
3188
3189 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003190 status = -ENOSYS;
3191 } else {
3192
3193 in->device = val;
3194 /* If recording is in progress, change the tx device to new device */
3195 if (!in->standby) {
3196 ALOGV("update input routing change");
3197 // inform adm before actual routing to prevent glitches.
3198 if (adev->adm_on_routing_change) {
3199 adev->adm_on_routing_change(adev->adm_data,
3200 in->capture_handle);
3201 }
3202 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003203 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003204 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003205 }
3206 }
3207
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003208 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003209 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003210
3211 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003212 ALOGV("%s: exit: status(%d)", __func__, status);
3213 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003214}
3215
Haynes Mathew George569b7482017-05-08 14:44:27 -07003216static char* in_get_parameters(const struct audio_stream *stream,
3217 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003218{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003219 struct stream_in *in = (struct stream_in *)stream;
3220 struct str_parms *query = str_parms_create_str(keys);
3221 char *str;
3222 struct str_parms *reply = str_parms_create();
3223 bool replied = false;
3224
3225 ALOGV("%s: enter: keys - %s", __func__, keys);
3226 replied |= stream_get_parameter_channels(query, reply,
3227 &in->supported_channel_masks[0]);
3228 replied |= stream_get_parameter_formats(query, reply,
3229 &in->supported_formats[0]);
3230 replied |= stream_get_parameter_rates(query, reply,
3231 &in->supported_sample_rates[0]);
3232 if (replied) {
3233 str = str_parms_to_str(reply);
3234 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003235 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003236 }
3237 str_parms_destroy(query);
3238 str_parms_destroy(reply);
3239 ALOGV("%s: exit: returns - %s", __func__, str);
3240 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003241}
3242
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003243static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003244{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003245 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003246}
3247
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003248static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3249{
3250 if (!stream || !parms)
3251 return;
3252
3253 struct stream_in *in = (struct stream_in *)stream;
3254 struct audio_device *adev = in->dev;
3255
3256 card_status_t status;
3257 int card;
3258 if (parse_snd_card_status(parms, &card, &status) < 0)
3259 return;
3260
3261 pthread_mutex_lock(&adev->lock);
3262 bool valid_cb = (card == adev->snd_card);
3263 pthread_mutex_unlock(&adev->lock);
3264
3265 if (!valid_cb)
3266 return;
3267
3268 lock_input_stream(in);
3269 if (in->card_status != status)
3270 in->card_status = status;
3271 pthread_mutex_unlock(&in->lock);
3272
3273 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3274 use_case_table[in->usecase],
3275 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3276
3277 // a better solution would be to report error back to AF and let
3278 // it put the stream to standby
3279 if (status == CARD_STATUS_OFFLINE)
3280 in_standby(&in->stream.common);
3281
3282 return;
3283}
3284
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003285static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3286 size_t bytes)
3287{
3288 struct stream_in *in = (struct stream_in *)stream;
3289 struct audio_device *adev = in->dev;
3290 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003291 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003292
Eric Laurenta1478072015-09-21 17:21:52 -07003293 lock_input_stream(in);
Andy Hung928efbe2017-06-12 14:05:22 -07003294 const size_t frame_size = audio_stream_in_frame_size(stream);
3295 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003296
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003297 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003298 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003299 /* Read from sound trigger HAL */
3300 audio_extn_sound_trigger_read(in, buffer, bytes);
3301 pthread_mutex_unlock(&in->lock);
3302 return bytes;
3303 }
3304
Eric Laurent0e46adf2016-12-16 12:49:24 -08003305 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3306 ret = -ENOSYS;
3307 goto exit;
3308 }
3309
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003310 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003311 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003312 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003313 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003314 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003315 goto exit;
3316 }
3317 in->standby = 0;
3318 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003319
Haynes Mathew George03c40102016-01-29 17:57:48 -08003320 //what's the duration requested by the client?
3321 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3322 in->config.rate;
3323 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003324
Haynes Mathew George03c40102016-01-29 17:57:48 -08003325 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003326 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003327 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003328 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003329 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003330 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003331 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003332 if (ret < 0) {
3333 ALOGE("Failed to read w/err %s", strerror(errno));
3334 ret = -errno;
3335 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003336 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3337 if (bytes % 4 == 0) {
3338 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3339 int_buf_stream = buffer;
3340 for (size_t itt=0; itt < bytes/4 ; itt++) {
3341 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003342 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003343 } else {
3344 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3345 ret = -EINVAL;
3346 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003347 }
3348 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003349 }
3350
Haynes Mathew George03c40102016-01-29 17:57:48 -08003351 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003352
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003353 /*
3354 * Instead of writing zeroes here, we could trust the hardware
3355 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003356 * 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 -08003357 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003358 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003359 memset(buffer, 0, bytes);
3360
3361exit:
3362 pthread_mutex_unlock(&in->lock);
3363
3364 if (ret != 0) {
3365 in_standby(&in->stream.common);
3366 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung928efbe2017-06-12 14:05:22 -07003367 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003368 memset(buffer, 0, bytes); // clear return data
3369 }
3370 if (bytes > 0) {
Andy Hung928efbe2017-06-12 14:05:22 -07003371 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003372 }
3373 return bytes;
3374}
3375
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003376static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003377{
3378 return 0;
3379}
3380
Andy Hung6ebe5962016-01-15 17:46:57 -08003381static int in_get_capture_position(const struct audio_stream_in *stream,
3382 int64_t *frames, int64_t *time)
3383{
3384 if (stream == NULL || frames == NULL || time == NULL) {
3385 return -EINVAL;
3386 }
3387 struct stream_in *in = (struct stream_in *)stream;
3388 int ret = -ENOSYS;
3389
3390 lock_input_stream(in);
3391 if (in->pcm) {
3392 struct timespec timestamp;
3393 unsigned int avail;
3394 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3395 *frames = in->frames_read + avail;
3396 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3397 ret = 0;
3398 }
3399 }
3400 pthread_mutex_unlock(&in->lock);
3401 return ret;
3402}
3403
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003404static int add_remove_audio_effect(const struct audio_stream *stream,
3405 effect_handle_t effect,
3406 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003407{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003408 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003409 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003410 int status = 0;
3411 effect_descriptor_t desc;
3412
3413 status = (*effect)->get_descriptor(effect, &desc);
3414 if (status != 0)
3415 return status;
3416
Eric Laurenta1478072015-09-21 17:21:52 -07003417 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003418 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003419 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003420 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003421 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003422 in->enable_aec != enable &&
3423 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3424 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003425 if (!enable)
3426 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003427 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3428 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3429 adev->enable_voicerx = enable;
3430 struct audio_usecase *usecase;
3431 struct listnode *node;
3432 list_for_each(node, &adev->usecase_list) {
3433 usecase = node_to_item(node, struct audio_usecase, list);
3434 if (usecase->type == PCM_PLAYBACK) {
3435 select_devices(adev, usecase->id);
3436 break;
3437 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003438 }
3439 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003440 if (!in->standby)
3441 select_devices(in->dev, in->usecase);
3442 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003443 if (in->enable_ns != enable &&
3444 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3445 in->enable_ns = enable;
3446 if (!in->standby)
3447 select_devices(in->dev, in->usecase);
3448 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003449 pthread_mutex_unlock(&in->dev->lock);
3450 pthread_mutex_unlock(&in->lock);
3451
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003452 return 0;
3453}
3454
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003455static int in_add_audio_effect(const struct audio_stream *stream,
3456 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003457{
Eric Laurent994a6932013-07-17 11:51:42 -07003458 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003459 return add_remove_audio_effect(stream, effect, true);
3460}
3461
3462static int in_remove_audio_effect(const struct audio_stream *stream,
3463 effect_handle_t effect)
3464{
Eric Laurent994a6932013-07-17 11:51:42 -07003465 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003466 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003467}
3468
Eric Laurent0e46adf2016-12-16 12:49:24 -08003469static int in_stop(const struct audio_stream_in* stream)
3470{
3471 struct stream_in *in = (struct stream_in *)stream;
3472 struct audio_device *adev = in->dev;
3473
3474 int ret = -ENOSYS;
3475 ALOGV("%s", __func__);
3476 pthread_mutex_lock(&adev->lock);
3477 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3478 in->capture_started && in->pcm != NULL) {
3479 pcm_stop(in->pcm);
3480 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003481 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003482 }
3483 pthread_mutex_unlock(&adev->lock);
3484 return ret;
3485}
3486
3487static int in_start(const struct audio_stream_in* stream)
3488{
3489 struct stream_in *in = (struct stream_in *)stream;
3490 struct audio_device *adev = in->dev;
3491 int ret = -ENOSYS;
3492
3493 ALOGV("%s in %p", __func__, in);
3494 pthread_mutex_lock(&adev->lock);
3495 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3496 !in->capture_started && in->pcm != NULL) {
3497 if (!in->capture_started) {
3498 ret = start_input_stream(in);
3499 if (ret == 0) {
3500 in->capture_started = true;
3501 }
3502 }
3503 }
3504 pthread_mutex_unlock(&adev->lock);
3505 return ret;
3506}
3507
3508static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3509 int32_t min_size_frames,
3510 struct audio_mmap_buffer_info *info)
3511{
3512 struct stream_in *in = (struct stream_in *)stream;
3513 struct audio_device *adev = in->dev;
3514 int ret = 0;
3515 unsigned int offset1;
3516 unsigned int frames1;
3517 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003518 uint32_t mmap_size;
3519 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003520
3521 pthread_mutex_lock(&adev->lock);
3522 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003523
Eric Laurent0e46adf2016-12-16 12:49:24 -08003524 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003525 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003526 ret = -EINVAL;
3527 goto exit;
3528 }
3529 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003530 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003531 ALOGV("%s in %p", __func__, in);
3532 ret = -ENOSYS;
3533 goto exit;
3534 }
3535 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3536 if (in->pcm_device_id < 0) {
3537 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3538 __func__, in->pcm_device_id, in->usecase);
3539 ret = -EINVAL;
3540 goto exit;
3541 }
Phil Burkbc991042017-02-24 08:06:44 -08003542
3543 adjust_mmap_period_count(&in->config, min_size_frames);
3544
Eric Laurent0e46adf2016-12-16 12:49:24 -08003545 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3546 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3547 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3548 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3549 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3550 step = "open";
3551 ret = -ENODEV;
3552 goto exit;
3553 }
3554
3555 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3556 if (ret < 0) {
3557 step = "begin";
3558 goto exit;
3559 }
3560 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003561 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003562 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003563 ret = platform_get_mmap_data_fd(adev->platform,
3564 in->pcm_device_id, 1 /*capture*/,
3565 &info->shared_memory_fd,
3566 &mmap_size);
3567 if (ret < 0) {
3568 // Fall back to non exclusive mode
3569 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3570 } else {
3571 if (mmap_size < buffer_size) {
3572 step = "mmap";
3573 goto exit;
3574 }
3575 // FIXME: indicate exclusive mode support by returning a negative buffer size
3576 info->buffer_size_frames *= -1;
3577 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08003578
Haynes Mathew George96483a22017-03-28 14:52:47 -07003579 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003580
3581 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3582 if (ret < 0) {
3583 step = "commit";
3584 goto exit;
3585 }
3586
Phil Burkbc991042017-02-24 08:06:44 -08003587 in->standby = false;
3588 ret = 0;
3589
Eric Laurent0e46adf2016-12-16 12:49:24 -08003590 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3591 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003592
3593exit:
3594 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003595 if (in->pcm == NULL) {
3596 ALOGE("%s: %s - %d", __func__, step, ret);
3597 } else {
3598 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003599 pcm_close(in->pcm);
3600 in->pcm = NULL;
3601 }
3602 }
3603 pthread_mutex_unlock(&adev->lock);
3604 return ret;
3605}
3606
3607static int in_get_mmap_position(const struct audio_stream_in *stream,
3608 struct audio_mmap_position *position)
3609{
3610 struct stream_in *in = (struct stream_in *)stream;
3611 ALOGVV("%s", __func__);
3612 if (position == NULL) {
3613 return -EINVAL;
3614 }
3615 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
3616 return -ENOSYS;
3617 }
3618 if (in->pcm == NULL) {
3619 return -ENOSYS;
3620 }
3621 struct timespec ts = { 0, 0 };
3622 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
3623 if (ret < 0) {
3624 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3625 return ret;
3626 }
Andy Hungfc044e12017-03-20 09:24:22 -07003627 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003628 return 0;
3629}
3630
3631
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003632static int adev_open_output_stream(struct audio_hw_device *dev,
3633 audio_io_handle_t handle,
3634 audio_devices_t devices,
3635 audio_output_flags_t flags,
3636 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003637 struct audio_stream_out **stream_out,
3638 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003639{
3640 struct audio_device *adev = (struct audio_device *)dev;
3641 struct stream_out *out;
3642 int i, ret;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003643 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
3644 bool is_usb_dev = audio_is_usb_out_device(devices) &&
3645 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
3646 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003647
Andy Hungd9653bd2017-08-01 19:31:39 -07003648 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
3649 return -ENOSYS;
3650 }
3651
Eric Laurent994a6932013-07-17 11:51:42 -07003652 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003653 __func__, config->sample_rate, config->channel_mask, devices, flags);
3654 *stream_out = NULL;
3655 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3656
3657 if (devices == AUDIO_DEVICE_NONE)
3658 devices = AUDIO_DEVICE_OUT_SPEAKER;
3659
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003660 out->flags = flags;
3661 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003662 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003663 out->format = config->format;
3664 out->sample_rate = config->sample_rate;
3665 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3666 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003667 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003668
3669 /* Init use case and pcm_config */
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003670 if (audio_is_linear_pcm(out->format) &&
3671 (out->flags == AUDIO_OUTPUT_FLAG_NONE ||
Haynes Mathew George569b7482017-05-08 14:44:27 -07003672 out->flags == AUDIO_OUTPUT_FLAG_DIRECT) && direct_dev) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003673 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003674 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003675 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003676 if (config->sample_rate == 0)
3677 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3678 if (config->channel_mask == 0)
3679 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3680 if (config->format == AUDIO_FORMAT_DEFAULT)
3681 config->format = AUDIO_FORMAT_PCM_16_BIT;
3682 } else if (is_usb_dev) {
3683 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
3684 &config->format,
3685 &out->supported_formats[0],
3686 MAX_SUPPORTED_FORMATS,
3687 &config->channel_mask,
3688 &out->supported_channel_masks[0],
3689 MAX_SUPPORTED_CHANNEL_MASKS,
3690 &config->sample_rate,
3691 &out->supported_sample_rates[0],
3692 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003693 ALOGV("plugged dev USB ret %d", ret);
3694 } else {
3695 ret = -1;
3696 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003697 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003698 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003699 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003700
Haynes Mathew George569b7482017-05-08 14:44:27 -07003701 out->channel_mask = config->channel_mask;
3702 out->sample_rate = config->sample_rate;
3703 out->format = config->format;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003704 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3705 // does this change?
Haynes Mathew George569b7482017-05-08 14:44:27 -07003706 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003707 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003708 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Andy Hung928efbe2017-06-12 14:05:22 -07003709 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
3710 audio_bytes_per_sample(config->format));
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003711 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003712 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003713 pthread_mutex_lock(&adev->lock);
3714 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3715 pthread_mutex_unlock(&adev->lock);
3716
3717 // reject offload during card offline to allow
3718 // fallback to s/w paths
3719 if (offline) {
3720 ret = -ENODEV;
3721 goto error_open;
3722 }
3723
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003724 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3725 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3726 ALOGE("%s: Unsupported Offload information", __func__);
3727 ret = -EINVAL;
3728 goto error_open;
3729 }
3730 if (!is_supported_format(config->offload_info.format)) {
3731 ALOGE("%s: Unsupported audio format", __func__);
3732 ret = -EINVAL;
3733 goto error_open;
3734 }
3735
3736 out->compr_config.codec = (struct snd_codec *)
3737 calloc(1, sizeof(struct snd_codec));
3738
3739 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3740 if (config->offload_info.channel_mask)
3741 out->channel_mask = config->offload_info.channel_mask;
3742 else if (config->channel_mask)
3743 out->channel_mask = config->channel_mask;
3744 out->format = config->offload_info.format;
3745 out->sample_rate = config->offload_info.sample_rate;
3746
3747 out->stream.set_callback = out_set_callback;
3748 out->stream.pause = out_pause;
3749 out->stream.resume = out_resume;
3750 out->stream.drain = out_drain;
3751 out->stream.flush = out_flush;
3752
3753 out->compr_config.codec->id =
3754 get_snd_codec_id(config->offload_info.format);
3755 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3756 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07003757 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003758 out->compr_config.codec->bit_rate =
3759 config->offload_info.bit_rate;
3760 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003761 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003762 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3763
3764 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3765 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003766
3767 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003768 create_offload_callback_thread(out);
3769 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3770 __func__, config->offload_info.version,
3771 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003772 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07003773 switch (config->sample_rate) {
3774 case 8000:
3775 case 16000:
3776 case 48000:
3777 out->sample_rate = config->sample_rate;
3778 break;
3779 default:
3780 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003781 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003782 out->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003783 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3784 out->config = pcm_config_afe_proxy_playback;
3785 adev->voice_tx_output = out;
David Lin6b00c232017-07-26 00:20:16 -07003786 } else if (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT |
3787 AUDIO_OUTPUT_FLAG_VOIP_RX)) {
vivek mehtaa68fea62017-06-08 19:04:02 -07003788 uint32_t buffer_size, frame_size;
3789 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
3790 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
3791 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
3792 out->config = pcm_config_voip;
3793 out->config.format = pcm_format_from_audio_format(config->format);
3794 out->config.rate = config->sample_rate;
3795 out->config.channels =
3796 audio_channel_count_from_out_mask(config->channel_mask);
3797 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
3798 config->sample_rate,
3799 config->format,
3800 out->config.channels,
3801 false /*is_low_latency*/);
3802 frame_size = audio_bytes_per_sample(config->format) * out->config.channels;
3803 out->config.period_size = buffer_size / frame_size;
3804 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
3805 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003806 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003807 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3808 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3809 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003810 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
3811 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3812 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003813 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3814 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003815 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003816 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003817 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3818 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3819 out->config = pcm_config_mmap_playback;
3820 out->stream.start = out_start;
3821 out->stream.stop = out_stop;
3822 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3823 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003824 } else {
3825 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3826 out->config = pcm_config_low_latency;
3827 }
3828 if (config->format != audio_format_from_pcm_format(out->config.format)) {
Haynes Mathew Georgedf0f8862017-06-28 13:36:40 -07003829 out->config.format = pcm_format_from_audio_format(config->format);
Andy Hung6fcba9c2014-03-18 11:53:32 -07003830 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003831 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003832 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003833
3834 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
3835 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
3836 (config->channel_mask != 0 && config->channel_mask != out->channel_mask)) {
3837 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
3838 __func__, config->sample_rate, config->format, config->channel_mask);
3839 config->sample_rate = out->sample_rate;
3840 config->format = out->format;
3841 config->channel_mask = out->channel_mask;
3842 ret = -EINVAL;
3843 goto error_open;
3844 }
3845
Andy Hung6fcba9c2014-03-18 11:53:32 -07003846 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3847 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003848
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003849 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003850 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003851 adev->primary_output = out;
3852 else {
3853 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003854 ret = -EEXIST;
3855 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003856 }
3857 }
3858
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003859 /* Check if this usecase is already existing */
3860 pthread_mutex_lock(&adev->lock);
3861 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3862 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003863 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003864 ret = -EEXIST;
3865 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003866 }
3867 pthread_mutex_unlock(&adev->lock);
3868
3869 out->stream.common.get_sample_rate = out_get_sample_rate;
3870 out->stream.common.set_sample_rate = out_set_sample_rate;
3871 out->stream.common.get_buffer_size = out_get_buffer_size;
3872 out->stream.common.get_channels = out_get_channels;
3873 out->stream.common.get_format = out_get_format;
3874 out->stream.common.set_format = out_set_format;
3875 out->stream.common.standby = out_standby;
3876 out->stream.common.dump = out_dump;
3877 out->stream.common.set_parameters = out_set_parameters;
3878 out->stream.common.get_parameters = out_get_parameters;
3879 out->stream.common.add_audio_effect = out_add_audio_effect;
3880 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3881 out->stream.get_latency = out_get_latency;
3882 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003883#ifdef NO_AUDIO_OUT
3884 out->stream.write = out_write_for_no_output;
3885#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003886 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003887#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003888 out->stream.get_render_position = out_get_render_position;
3889 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003890 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003891
Eric Laurent0e46adf2016-12-16 12:49:24 -08003892 if (out->realtime)
3893 out->af_period_multiplier = af_period_multiplier;
3894 else
3895 out->af_period_multiplier = 1;
3896
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003897 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003898 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003899 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003900
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003901 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003902 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003903 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3904
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003905 config->format = out->stream.common.get_format(&out->stream.common);
3906 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3907 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3908
Andy Hunga452b0a2017-03-15 14:51:15 -07003909 out->error_log = error_log_create(
3910 ERROR_LOG_ENTRIES,
3911 1000000000 /* aggregate consecutive identical errors within one second in ns */);
3912
Andy Hungfc044e12017-03-20 09:24:22 -07003913 // power_log may be null if the format is not supported
Andy Hung9e737de2017-05-22 10:51:22 -07003914 // or not a userdebug or eng build.
Andy Hung02caae52017-06-06 12:33:33 -07003915 if (false /* is_userdebug_or_eng_build() */) {
Andy Hung9e737de2017-05-22 10:51:22 -07003916 const size_t POWER_LOG_FRAMES_PER_ENTRY =
3917 (long long)config->sample_rate * POWER_LOG_SAMPLING_INTERVAL_MS / 1000;
3918
3919 out->power_log = power_log_create(
3920 config->sample_rate,
3921 audio_channel_count_from_out_mask(config->channel_mask),
3922 config->format,
3923 POWER_LOG_ENTRIES,
3924 POWER_LOG_FRAMES_PER_ENTRY);
3925 }
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003926
3927 /*
3928 By locking output stream before registering, we allow the callback
3929 to update stream's state only after stream's initial state is set to
3930 adev state.
3931 */
3932 lock_output_stream(out);
3933 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3934 pthread_mutex_lock(&adev->lock);
3935 out->card_status = adev->card_status;
3936 pthread_mutex_unlock(&adev->lock);
3937 pthread_mutex_unlock(&out->lock);
3938
vivek mehta4a824772017-06-08 19:05:49 -07003939 stream_app_type_cfg_init(&out->app_type_cfg);
3940
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003941 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003942
Eric Laurent994a6932013-07-17 11:51:42 -07003943 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003944 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003945
3946error_open:
3947 free(out);
3948 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003949 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003950 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003951}
3952
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003953static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003954 struct audio_stream_out *stream)
3955{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003956 struct stream_out *out = (struct stream_out *)stream;
3957 struct audio_device *adev = out->dev;
3958
Eric Laurent994a6932013-07-17 11:51:42 -07003959 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003960
3961 // must deregister from sndmonitor first to prevent races
3962 // between the callback and close_stream
3963 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003964 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003965 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3966 destroy_offload_callback_thread(out);
3967
3968 if (out->compr_config.codec != NULL)
3969 free(out->compr_config.codec);
3970 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003971
3972 if (adev->voice_tx_output == out)
3973 adev->voice_tx_output = NULL;
3974
Andy Hungfc044e12017-03-20 09:24:22 -07003975 power_log_destroy(out->power_log);
3976 out->power_log = NULL;
3977
Andy Hunga452b0a2017-03-15 14:51:15 -07003978 error_log_destroy(out->error_log);
3979 out->error_log = NULL;
3980
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003981 pthread_cond_destroy(&out->cond);
3982 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003983 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003984 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003985}
3986
3987static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3988{
3989 struct audio_device *adev = (struct audio_device *)dev;
3990 struct str_parms *parms;
3991 char *str;
3992 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003993 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003994 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003995 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003996
Joe Onorato188b6222016-03-01 11:02:27 -08003997 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003998
3999 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004000
4001 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004002 status = voice_set_parameters(adev, parms);
4003 if (status != 0) {
4004 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004005 }
4006
4007 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4008 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07004009 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004010 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4011 adev->bluetooth_nrec = true;
4012 else
4013 adev->bluetooth_nrec = false;
4014 }
4015
4016 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4017 if (ret >= 0) {
4018 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4019 adev->screen_off = false;
4020 else
4021 adev->screen_off = true;
4022 }
4023
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004024 ret = str_parms_get_int(parms, "rotation", &val);
4025 if (ret >= 0) {
4026 bool reverse_speakers = false;
4027 switch(val) {
4028 // FIXME: note that the code below assumes that the speakers are in the correct placement
4029 // relative to the user when the device is rotated 90deg from its default rotation. This
4030 // assumption is device-specific, not platform-specific like this code.
4031 case 270:
4032 reverse_speakers = true;
4033 break;
4034 case 0:
4035 case 90:
4036 case 180:
4037 break;
4038 default:
4039 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07004040 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004041 }
Eric Laurent03f09432014-03-25 18:09:11 -07004042 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004043 // check and set swap
4044 // - check if orientation changed and speaker active
4045 // - set rotation and cache the rotation value
4046 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004047 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004048 }
4049
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004050 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4051 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004052 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004053 }
4054
David Linee3fe402017-03-13 10:00:42 -07004055 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4056 if (ret >= 0) {
4057 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004058 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004059 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4060 if (ret >= 0) {
4061 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004062 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004063 }
Eric Laurent99dab492017-06-17 15:19:08 -07004064 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004065 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4066 if (ret >= 0) {
4067 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004068 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004069 }
4070 }
4071 }
4072
4073 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4074 if (ret >= 0) {
4075 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004076 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004077 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4078 if (ret >= 0) {
4079 const int card = atoi(value);
4080
Eric Laurent99dab492017-06-17 15:19:08 -07004081 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004082 }
Eric Laurent99dab492017-06-17 15:19:08 -07004083 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004084 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4085 if (ret >= 0) {
4086 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004087 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004088 }
4089 }
4090 }
4091
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004092 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004093done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004094 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004095 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004096 ALOGV("%s: exit with code(%d)", __func__, status);
4097 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004098}
4099
4100static char* adev_get_parameters(const struct audio_hw_device *dev,
4101 const char *keys)
4102{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004103 struct audio_device *adev = (struct audio_device *)dev;
4104 struct str_parms *reply = str_parms_create();
4105 struct str_parms *query = str_parms_create_str(keys);
4106 char *str;
4107
4108 pthread_mutex_lock(&adev->lock);
4109
4110 voice_get_parameters(adev, query, reply);
4111 str = str_parms_to_str(reply);
4112 str_parms_destroy(query);
4113 str_parms_destroy(reply);
4114
4115 pthread_mutex_unlock(&adev->lock);
4116 ALOGV("%s: exit: returns - %s", __func__, str);
4117 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004118}
4119
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004120static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004121{
4122 return 0;
4123}
4124
Haynes Mathew George5191a852013-09-11 14:19:36 -07004125static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4126{
4127 int ret;
4128 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004129
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004130 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4131
Haynes Mathew George5191a852013-09-11 14:19:36 -07004132 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004133 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004134 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004135
Haynes Mathew George5191a852013-09-11 14:19:36 -07004136 return ret;
4137}
4138
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004139static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004140{
4141 return -ENOSYS;
4142}
4143
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004144static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4145 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004146{
4147 return -ENOSYS;
4148}
4149
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004150static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004151{
4152 return -ENOSYS;
4153}
4154
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004155static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004156{
4157 return -ENOSYS;
4158}
4159
4160static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4161{
4162 struct audio_device *adev = (struct audio_device *)dev;
4163
4164 pthread_mutex_lock(&adev->lock);
4165 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004166 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004167 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004168 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4169 voice_is_in_call(adev)) {
4170 voice_stop_call(adev);
4171 adev->current_call_output = NULL;
4172 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004173 }
4174 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004175
4176 audio_extn_extspk_set_mode(adev->extspk, mode);
4177
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004178 return 0;
4179}
4180
4181static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4182{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004183 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004184 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004185
Eric Laurent2bafff12016-03-17 12:17:23 -07004186 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004187 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004188 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4189 ret = audio_extn_hfp_set_mic_mute(adev, state);
4190 } else {
4191 ret = voice_set_mic_mute(adev, state);
4192 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004193 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004194 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004195
4196 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004197}
4198
4199static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4200{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004201 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004202 return 0;
4203}
4204
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004205static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004206 const struct audio_config *config)
4207{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004208 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004209
Eric Laurent74b55762017-07-09 17:04:53 -07004210 /* Don't know if USB HIFI in this context so use true to be conservative */
4211 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4212 true /*is_usb_hifi */) != 0)
4213 return 0;
4214
vivek mehtaa68fea62017-06-08 19:04:02 -07004215 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4216 config->sample_rate, config->format,
4217 channel_count,
4218 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004219}
4220
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004221static bool adev_input_allow_hifi_record(struct audio_device *adev,
4222 audio_devices_t devices,
4223 audio_input_flags_t flags,
4224 audio_source_t source) {
4225 const bool allowed = true;
4226
4227 if (!audio_is_usb_in_device(devices))
4228 return !allowed;
4229
4230 switch (flags) {
4231 case AUDIO_INPUT_FLAG_NONE:
4232 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4233 break;
4234 default:
4235 return !allowed;
4236 }
4237
4238 switch (source) {
4239 case AUDIO_SOURCE_DEFAULT:
4240 case AUDIO_SOURCE_MIC:
4241 case AUDIO_SOURCE_UNPROCESSED:
4242 break;
4243 default:
4244 return !allowed;
4245 }
4246
4247 switch (adev->mode) {
4248 case 0:
4249 break;
4250 default:
4251 return !allowed;
4252 }
4253
4254 return allowed;
4255}
4256
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004257static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004258 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004259 audio_devices_t devices,
4260 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004261 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004262 audio_input_flags_t flags,
4263 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004264 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004265{
4266 struct audio_device *adev = (struct audio_device *)dev;
4267 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004268 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004269 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004270 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004271 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004272 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4273 devices,
4274 flags,
4275 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004276 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004277 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004278
Andy Hungd9653bd2017-08-01 19:31:39 -07004279 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
4280 return -ENOSYS;
4281 }
4282
Eric Laurent74b55762017-07-09 17:04:53 -07004283 if (!(is_usb_dev && may_use_hifi_record)) {
4284 if (config->sample_rate == 0)
4285 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4286 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4287 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4288 if (config->format == AUDIO_FORMAT_DEFAULT)
4289 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004290
Eric Laurent74b55762017-07-09 17:04:53 -07004291 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
4292
4293 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
4294 return -EINVAL;
4295 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004296
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004297 if (audio_extn_tfa_98xx_is_supported() &&
4298 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004299 return -EINVAL;
4300
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004301 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4302
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004303 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004304 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004305
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004306 in->stream.common.get_sample_rate = in_get_sample_rate;
4307 in->stream.common.set_sample_rate = in_set_sample_rate;
4308 in->stream.common.get_buffer_size = in_get_buffer_size;
4309 in->stream.common.get_channels = in_get_channels;
4310 in->stream.common.get_format = in_get_format;
4311 in->stream.common.set_format = in_set_format;
4312 in->stream.common.standby = in_standby;
4313 in->stream.common.dump = in_dump;
4314 in->stream.common.set_parameters = in_set_parameters;
4315 in->stream.common.get_parameters = in_get_parameters;
4316 in->stream.common.add_audio_effect = in_add_audio_effect;
4317 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4318 in->stream.set_gain = in_set_gain;
4319 in->stream.read = in_read;
4320 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08004321 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004322
4323 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004324 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004325 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004326 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004327 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004328 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004329
Haynes Mathew George569b7482017-05-08 14:44:27 -07004330 if (is_usb_dev && may_use_hifi_record) {
4331 /* HiFi record selects an appropriate format, channel, rate combo
4332 depending on sink capabilities*/
4333 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
4334 &config->format,
4335 &in->supported_formats[0],
4336 MAX_SUPPORTED_FORMATS,
4337 &config->channel_mask,
4338 &in->supported_channel_masks[0],
4339 MAX_SUPPORTED_CHANNEL_MASKS,
4340 &config->sample_rate,
4341 &in->supported_sample_rates[0],
4342 MAX_SUPPORTED_SAMPLE_RATES);
4343 if (ret != 0) {
4344 ret = -EINVAL;
4345 goto err_open;
4346 }
Eric Laurent74b55762017-07-09 17:04:53 -07004347 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004348 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07004349 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07004350 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
4351 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
4352 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4353 bool ret_error = false;
4354 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4355 from HAL is 8_24
4356 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4357 8_24 return error indicating supported format is 8_24
4358 *> In case of any other source requesting 24 bit or float return error
4359 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07004360
vivek mehta57ff9b52016-04-28 14:13:08 -07004361 on error flinger will retry with supported format passed
4362 */
4363 if (source != AUDIO_SOURCE_UNPROCESSED) {
4364 config->format = AUDIO_FORMAT_PCM_16_BIT;
4365 ret_error = true;
4366 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
4367 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
4368 ret_error = true;
4369 }
4370
4371 if (ret_error) {
4372 ret = -EINVAL;
4373 goto err_open;
4374 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004375 }
4376
vivek mehta57ff9b52016-04-28 14:13:08 -07004377 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07004378 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07004379
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004380 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004381 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
4382 if (config->sample_rate == 0)
4383 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4384 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4385 config->sample_rate != 8000) {
4386 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4387 ret = -EINVAL;
4388 goto err_open;
4389 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004390
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004391 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4392 config->format = AUDIO_FORMAT_PCM_16_BIT;
4393 ret = -EINVAL;
4394 goto err_open;
4395 }
4396
4397 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4398 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07004399 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004400 } else if (is_usb_dev && may_use_hifi_record) {
4401 in->usecase = USECASE_AUDIO_RECORD_HIFI;
4402 in->config = pcm_config_audio_capture;
4403 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004404 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4405 config->sample_rate,
4406 config->format,
4407 channel_count,
4408 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004409 in->config.period_size = buffer_size / frame_size;
4410 in->config.rate = config->sample_rate;
4411 in->af_period_multiplier = 1;
4412 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004413 } else {
4414 in->usecase = USECASE_AUDIO_RECORD;
4415 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08004416 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004417 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07004418#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004419 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07004420#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08004421 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004422 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08004423 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004424 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004425 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4426 config->sample_rate,
4427 config->format,
4428 channel_count,
4429 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004430 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004431 in->config.rate = config->sample_rate;
4432 in->af_period_multiplier = 1;
4433 } else {
4434 // period size is left untouched for rt mode playback
4435 in->config = pcm_config_audio_capture_rt;
4436 in->af_period_multiplier = af_period_multiplier;
4437 }
4438 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
4439 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004440 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08004441 in->usecase = USECASE_AUDIO_RECORD_MMAP;
4442 in->config = pcm_config_mmap_capture;
4443 in->stream.start = in_start;
4444 in->stream.stop = in_stop;
4445 in->stream.create_mmap_buffer = in_create_mmap_buffer;
4446 in->stream.get_mmap_position = in_get_mmap_position;
4447 in->af_period_multiplier = 1;
4448 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07004449 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07004450 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07004451 (config->sample_rate == 8000 ||
4452 config->sample_rate == 16000 ||
4453 config->sample_rate == 32000 ||
4454 config->sample_rate == 48000) &&
4455 channel_count == 1) {
4456 in->usecase = USECASE_AUDIO_RECORD_VOIP;
4457 in->config = pcm_config_audio_capture;
4458 frame_size = audio_stream_in_frame_size(&in->stream);
4459 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
4460 config->sample_rate,
4461 config->format,
4462 channel_count, false /*is_low_latency*/);
4463 in->config.period_size = buffer_size / frame_size;
4464 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
4465 in->config.rate = config->sample_rate;
4466 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004467 } else {
4468 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004469 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004470 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4471 config->sample_rate,
4472 config->format,
4473 channel_count,
4474 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004475 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004476 in->config.rate = config->sample_rate;
4477 in->af_period_multiplier = 1;
4478 }
4479 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
4480 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004481 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004482
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004483 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07004484 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004485
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004486 /* This stream could be for sound trigger lab,
4487 get sound trigger pcm if present */
4488 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004489
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004490 lock_input_stream(in);
4491 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
4492 pthread_mutex_lock(&adev->lock);
4493 in->card_status = adev->card_status;
4494 pthread_mutex_unlock(&adev->lock);
4495 pthread_mutex_unlock(&in->lock);
4496
vivek mehta4a824772017-06-08 19:05:49 -07004497 stream_app_type_cfg_init(&in->app_type_cfg);
4498
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004499 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004500 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004501 return 0;
4502
4503err_open:
4504 free(in);
4505 *stream_in = NULL;
4506 return ret;
4507}
4508
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004509static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004510 struct audio_stream_in *stream)
4511{
Eric Laurent994a6932013-07-17 11:51:42 -07004512 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004513
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004514 // must deregister from sndmonitor first to prevent races
4515 // between the callback and close_stream
4516 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004517 in_standby(&stream->common);
4518 free(stream);
4519
4520 return;
4521}
4522
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004523static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004524{
4525 return 0;
4526}
4527
Andy Hung31aca912014-03-20 17:14:59 -07004528/* verifies input and output devices and their capabilities.
4529 *
4530 * This verification is required when enabling extended bit-depth or
4531 * sampling rates, as not all qcom products support it.
4532 *
4533 * Suitable for calling only on initialization such as adev_open().
4534 * It fills the audio_device use_case_table[] array.
4535 *
4536 * Has a side-effect that it needs to configure audio routing / devices
4537 * in order to power up the devices and read the device parameters.
4538 * It does not acquire any hw device lock. Should restore the devices
4539 * back to "normal state" upon completion.
4540 */
4541static int adev_verify_devices(struct audio_device *adev)
4542{
4543 /* enumeration is a bit difficult because one really wants to pull
4544 * the use_case, device id, etc from the hidden pcm_device_table[].
4545 * In this case there are the following use cases and device ids.
4546 *
4547 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
4548 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004549 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07004550 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
4551 * [USECASE_AUDIO_RECORD] = {0, 0},
4552 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
4553 * [USECASE_VOICE_CALL] = {2, 2},
4554 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004555 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07004556 * USECASE_VOICE_CALL omitted, but possible for either input or output.
4557 */
4558
4559 /* should be the usecases enabled in adev_open_input_stream() */
4560 static const int test_in_usecases[] = {
4561 USECASE_AUDIO_RECORD,
4562 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
4563 };
4564 /* should be the usecases enabled in adev_open_output_stream()*/
4565 static const int test_out_usecases[] = {
4566 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
4567 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
4568 };
4569 static const usecase_type_t usecase_type_by_dir[] = {
4570 PCM_PLAYBACK,
4571 PCM_CAPTURE,
4572 };
4573 static const unsigned flags_by_dir[] = {
4574 PCM_OUT,
4575 PCM_IN,
4576 };
4577
4578 size_t i;
4579 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004580 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07004581 char info[512]; /* for possible debug info */
4582
4583 for (dir = 0; dir < 2; ++dir) {
4584 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
4585 const unsigned flags_dir = flags_by_dir[dir];
4586 const size_t testsize =
4587 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
4588 const int *testcases =
4589 dir ? test_in_usecases : test_out_usecases;
4590 const audio_devices_t audio_device =
4591 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
4592
4593 for (i = 0; i < testsize; ++i) {
4594 const audio_usecase_t audio_usecase = testcases[i];
4595 int device_id;
4596 snd_device_t snd_device;
4597 struct pcm_params **pparams;
4598 struct stream_out out;
4599 struct stream_in in;
4600 struct audio_usecase uc_info;
4601 int retval;
4602
4603 pparams = &adev->use_case_table[audio_usecase];
4604 pcm_params_free(*pparams); /* can accept null input */
4605 *pparams = NULL;
4606
4607 /* find the device ID for the use case (signed, for error) */
4608 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
4609 if (device_id < 0)
4610 continue;
4611
4612 /* prepare structures for device probing */
4613 memset(&uc_info, 0, sizeof(uc_info));
4614 uc_info.id = audio_usecase;
4615 uc_info.type = usecase_type;
4616 if (dir) {
4617 adev->active_input = &in;
4618 memset(&in, 0, sizeof(in));
4619 in.device = audio_device;
4620 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4621 uc_info.stream.in = &in;
4622 } else {
4623 adev->active_input = NULL;
4624 }
4625 memset(&out, 0, sizeof(out));
4626 out.devices = audio_device; /* only field needed in select_devices */
4627 uc_info.stream.out = &out;
4628 uc_info.devices = audio_device;
4629 uc_info.in_snd_device = SND_DEVICE_NONE;
4630 uc_info.out_snd_device = SND_DEVICE_NONE;
4631 list_add_tail(&adev->usecase_list, &uc_info.list);
4632
4633 /* select device - similar to start_(in/out)put_stream() */
4634 retval = select_devices(adev, audio_usecase);
4635 if (retval >= 0) {
4636 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4637#if LOG_NDEBUG == 0
4638 if (*pparams) {
4639 ALOGV("%s: (%s) card %d device %d", __func__,
4640 dir ? "input" : "output", card_id, device_id);
4641 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004642 } else {
4643 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4644 }
4645#endif
4646 }
4647
4648 /* deselect device - similar to stop_(in/out)put_stream() */
4649 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004650 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004651 /* 2. Disable the rx device */
4652 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004653 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004654 list_remove(&uc_info.list);
4655 }
4656 }
4657 adev->active_input = NULL; /* restore adev state */
4658 return 0;
4659}
4660
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004661static int adev_close(hw_device_t *device)
4662{
Andy Hung31aca912014-03-20 17:14:59 -07004663 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004664 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004665
4666 if (!adev)
4667 return 0;
4668
4669 pthread_mutex_lock(&adev_init_lock);
4670
4671 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004672 audio_extn_snd_mon_unregister_listener(adev);
4673 audio_extn_tfa_98xx_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004674 audio_route_free(adev->audio_route);
4675 free(adev->snd_dev_ref_cnt);
4676 platform_deinit(adev->platform);
4677 audio_extn_extspk_deinit(adev->extspk);
4678 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004679 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004680 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4681 pcm_params_free(adev->use_case_table[i]);
4682 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004683 if (adev->adm_deinit)
4684 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004685 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004686 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004687
4688 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004689
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004690 return 0;
4691}
4692
Glenn Kasten4f993392014-05-14 07:30:48 -07004693/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4694 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4695 * just that it _might_ work.
4696 */
4697static int period_size_is_plausible_for_low_latency(int period_size)
4698{
4699 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004700 case 48:
4701 case 96:
4702 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004703 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004704 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004705 case 240:
4706 case 320:
4707 case 480:
4708 return 1;
4709 default:
4710 return 0;
4711 }
4712}
4713
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004714static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4715{
4716 int card;
4717 card_status_t status;
4718
4719 if (!parms)
4720 return;
4721
4722 if (parse_snd_card_status(parms, &card, &status) < 0)
4723 return;
4724
4725 pthread_mutex_lock(&adev->lock);
4726 bool valid_cb = (card == adev->snd_card);
4727 if (valid_cb) {
4728 if (adev->card_status != status) {
4729 adev->card_status = status;
4730 platform_snd_card_update(adev->platform, status);
4731 }
4732 }
4733 pthread_mutex_unlock(&adev->lock);
4734 return;
4735}
4736
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004737static int adev_open(const hw_module_t *module, const char *name,
4738 hw_device_t **device)
4739{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004740 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004741
Eric Laurent2bafff12016-03-17 12:17:23 -07004742 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004743 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004744 pthread_mutex_lock(&adev_init_lock);
4745 if (audio_device_ref_count != 0) {
4746 *device = &adev->device.common;
4747 audio_device_ref_count++;
4748 ALOGV("%s: returning existing instance of adev", __func__);
4749 ALOGV("%s: exit", __func__);
4750 pthread_mutex_unlock(&adev_init_lock);
4751 return 0;
4752 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004753 adev = calloc(1, sizeof(struct audio_device));
4754
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004755 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4756
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004757 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4758 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4759 adev->device.common.module = (struct hw_module_t *)module;
4760 adev->device.common.close = adev_close;
4761
4762 adev->device.init_check = adev_init_check;
4763 adev->device.set_voice_volume = adev_set_voice_volume;
4764 adev->device.set_master_volume = adev_set_master_volume;
4765 adev->device.get_master_volume = adev_get_master_volume;
4766 adev->device.set_master_mute = adev_set_master_mute;
4767 adev->device.get_master_mute = adev_get_master_mute;
4768 adev->device.set_mode = adev_set_mode;
4769 adev->device.set_mic_mute = adev_set_mic_mute;
4770 adev->device.get_mic_mute = adev_get_mic_mute;
4771 adev->device.set_parameters = adev_set_parameters;
4772 adev->device.get_parameters = adev_get_parameters;
4773 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4774 adev->device.open_output_stream = adev_open_output_stream;
4775 adev->device.close_output_stream = adev_close_output_stream;
4776 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004777
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004778 adev->device.close_input_stream = adev_close_input_stream;
4779 adev->device.dump = adev_dump;
4780
4781 /* Set the default route before the PCM stream is opened */
4782 pthread_mutex_lock(&adev->lock);
4783 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004784 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004785 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004786 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004787 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004788 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004789 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004790 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004791 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004792 pthread_mutex_unlock(&adev->lock);
4793
4794 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004795 adev->platform = platform_init(adev);
4796 if (!adev->platform) {
4797 free(adev->snd_dev_ref_cnt);
4798 free(adev);
4799 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4800 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004801 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004802 return -EINVAL;
4803 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05004804 adev->extspk = audio_extn_extspk_init(adev);
4805
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004806 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4807 if (adev->visualizer_lib == NULL) {
4808 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4809 } else {
4810 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4811 adev->visualizer_start_output =
4812 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4813 "visualizer_hal_start_output");
4814 adev->visualizer_stop_output =
4815 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4816 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07004817 }
4818
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004819 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4820 if (adev->offload_effects_lib == NULL) {
4821 ALOGW("%s: DLOPEN failed for %s", __func__,
4822 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4823 } else {
4824 ALOGV("%s: DLOPEN successful for %s", __func__,
4825 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4826 adev->offload_effects_start_output =
4827 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4828 "offload_effects_bundle_hal_start_output");
4829 adev->offload_effects_stop_output =
4830 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4831 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07004832 }
4833
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004834 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4835 if (adev->adm_lib == NULL) {
4836 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4837 } else {
4838 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4839 adev->adm_init = (adm_init_t)
4840 dlsym(adev->adm_lib, "adm_init");
4841 adev->adm_deinit = (adm_deinit_t)
4842 dlsym(adev->adm_lib, "adm_deinit");
4843 adev->adm_register_input_stream = (adm_register_input_stream_t)
4844 dlsym(adev->adm_lib, "adm_register_input_stream");
4845 adev->adm_register_output_stream = (adm_register_output_stream_t)
4846 dlsym(adev->adm_lib, "adm_register_output_stream");
4847 adev->adm_deregister_stream = (adm_deregister_stream_t)
4848 dlsym(adev->adm_lib, "adm_deregister_stream");
4849 adev->adm_request_focus = (adm_request_focus_t)
4850 dlsym(adev->adm_lib, "adm_request_focus");
4851 adev->adm_abandon_focus = (adm_abandon_focus_t)
4852 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08004853 adev->adm_set_config = (adm_set_config_t)
4854 dlsym(adev->adm_lib, "adm_set_config");
4855 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4856 dlsym(adev->adm_lib, "adm_request_focus_v2");
4857 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4858 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4859 adev->adm_on_routing_change = (adm_on_routing_change_t)
4860 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004861 }
4862
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004863 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004864 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004865
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004866 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004867
Andy Hung31aca912014-03-20 17:14:59 -07004868 if (k_enable_extended_precision)
4869 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004870
Glenn Kasten4f993392014-05-14 07:30:48 -07004871 char value[PROPERTY_VALUE_MAX];
4872 int trial;
4873 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4874 trial = atoi(value);
4875 if (period_size_is_plausible_for_low_latency(trial)) {
4876 pcm_config_low_latency.period_size = trial;
4877 pcm_config_low_latency.start_threshold = trial / 4;
4878 pcm_config_low_latency.avail_min = trial / 4;
4879 configured_low_latency_capture_period_size = trial;
4880 }
4881 }
4882 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4883 trial = atoi(value);
4884 if (period_size_is_plausible_for_low_latency(trial)) {
4885 configured_low_latency_capture_period_size = trial;
4886 }
4887 }
4888
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004889 // commented as full set of app type cfg is sent from platform
4890 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004891 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004892
4893 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4894 af_period_multiplier = atoi(value);
4895 if (af_period_multiplier < 0) {
4896 af_period_multiplier = 2;
4897 } else if (af_period_multiplier > 4) {
4898 af_period_multiplier = 4;
4899 }
4900 ALOGV("new period_multiplier = %d", af_period_multiplier);
4901 }
4902
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004903 audio_extn_tfa_98xx_init(adev);
4904
vivek mehta1a9b7c02015-06-25 11:49:38 -07004905 pthread_mutex_unlock(&adev_init_lock);
4906
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004907 if (adev->adm_init)
4908 adev->adm_data = adev->adm_init();
4909
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004910 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004911 audio_extn_snd_mon_init();
4912 pthread_mutex_lock(&adev->lock);
4913 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
4914 adev->card_status = CARD_STATUS_ONLINE;
4915 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004916 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004917
Eric Laurent2bafff12016-03-17 12:17:23 -07004918 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004919 return 0;
4920}
4921
4922static struct hw_module_methods_t hal_module_methods = {
4923 .open = adev_open,
4924};
4925
4926struct audio_module HAL_MODULE_INFO_SYM = {
4927 .common = {
4928 .tag = HARDWARE_MODULE_TAG,
4929 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4930 .hal_api_version = HARDWARE_HAL_API_VERSION,
4931 .id = AUDIO_HARDWARE_MODULE_ID,
4932 .name = "QCOM Audio HAL",
4933 .author = "Code Aurora Forum",
4934 .methods = &hal_module_methods,
4935 },
4936};